1/*
2 * This code is derived from uClibc (original license follows).
3 * https://git.uclibc.org/uClibc/tree/utils/mmap-windows.c
4 */
5 /* mmap() replacement for Windows
6 *
7 * Author: Mike Frysinger <vapier@gentoo.org>
8 * Placed into the public domain
9 */
10
11/* References:
12 * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
13 * CloseHandle:       http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
14 * MapViewOfFile:     http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
15 * UnmapViewOfFile:   http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
16 */
17
18#if defined(_WIN32)
19
20#include "WindowsMMap.h"
21#include "InstrProfiling.h"
22
23#ifdef __USE_FILE_OFFSET64
24# define DWORD_HI(x) (x >> 32)
25# define DWORD_LO(x) ((x) & 0xffffffff)
26#else
27# define DWORD_HI(x) (0)
28# define DWORD_LO(x) (x)
29#endif
30
31COMPILER_RT_VISIBILITY
32void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
33{
34  if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
35    return MAP_FAILED;
36  if (fd == -1) {
37    if (!(flags & MAP_ANON) || offset)
38      return MAP_FAILED;
39  } else if (flags & MAP_ANON)
40    return MAP_FAILED;
41
42  DWORD flProtect;
43  if (prot & PROT_WRITE) {
44    if (prot & PROT_EXEC)
45      flProtect = PAGE_EXECUTE_READWRITE;
46    else
47      flProtect = PAGE_READWRITE;
48  } else if (prot & PROT_EXEC) {
49    if (prot & PROT_READ)
50      flProtect = PAGE_EXECUTE_READ;
51    else if (prot & PROT_EXEC)
52      flProtect = PAGE_EXECUTE;
53  } else
54    flProtect = PAGE_READONLY;
55
56  off_t end = length + offset;
57  HANDLE mmap_fd, h;
58  if (fd == -1)
59    mmap_fd = INVALID_HANDLE_VALUE;
60  else
61    mmap_fd = (HANDLE)_get_osfhandle(fd);
62  h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL);
63  if (h == NULL)
64    return MAP_FAILED;
65
66  DWORD dwDesiredAccess;
67  if (prot & PROT_WRITE)
68    dwDesiredAccess = FILE_MAP_WRITE;
69  else
70    dwDesiredAccess = FILE_MAP_READ;
71  if (prot & PROT_EXEC)
72    dwDesiredAccess |= FILE_MAP_EXECUTE;
73  if (flags & MAP_PRIVATE)
74    dwDesiredAccess |= FILE_MAP_COPY;
75  void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length);
76  if (ret == NULL) {
77    CloseHandle(h);
78    ret = MAP_FAILED;
79  }
80  return ret;
81}
82
83COMPILER_RT_VISIBILITY
84void munmap(void *addr, size_t length)
85{
86  UnmapViewOfFile(addr);
87  /* ruh-ro, we leaked handle from CreateFileMapping() ... */
88}
89
90COMPILER_RT_VISIBILITY
91int msync(void *addr, size_t length, int flags)
92{
93  if (flags & MS_INVALIDATE)
94    return -1; /* Not supported. */
95
96  /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */
97  switch (flags & (MS_ASYNC | MS_SYNC)) {
98    case MS_SYNC:
99    case MS_ASYNC:
100      break;
101    default:
102      return -1;
103  }
104
105  if (!FlushViewOfFile(addr, length))
106    return -1;
107
108  if (flags & MS_SYNC) {
109    /* FIXME: No longer have access to handle from CreateFileMapping(). */
110    /*
111     * if (!FlushFileBuffers(h))
112     *   return -1;
113     */
114  }
115
116  return 0;
117}
118
119COMPILER_RT_VISIBILITY
120int flock(int fd, int operation)
121{
122  return -1; /* Not supported. */
123}
124
125#undef DWORD_HI
126#undef DWORD_LO
127
128#endif /* _WIN32 */
129