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
22 #define WIN32_LEAN_AND_MEAN
23 #include <windows.h>
24
25 #include "InstrProfiling.h"
26
27 COMPILER_RT_VISIBILITY
mmap(void * start,size_t length,int prot,int flags,int fd,off_t offset)28 void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
29 {
30 if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
31 return MAP_FAILED;
32 if (fd == -1) {
33 if (!(flags & MAP_ANON) || offset)
34 return MAP_FAILED;
35 } else if (flags & MAP_ANON)
36 return MAP_FAILED;
37
38 DWORD flProtect;
39 if (prot & PROT_WRITE) {
40 if (prot & PROT_EXEC)
41 flProtect = PAGE_EXECUTE_READWRITE;
42 else
43 flProtect = PAGE_READWRITE;
44 } else if (prot & PROT_EXEC) {
45 if (prot & PROT_READ)
46 flProtect = PAGE_EXECUTE_READ;
47 else if (prot & PROT_EXEC)
48 flProtect = PAGE_EXECUTE;
49 } else
50 flProtect = PAGE_READONLY;
51
52 off_t end = length + offset;
53 HANDLE mmap_fd, h;
54 if (fd == -1)
55 mmap_fd = INVALID_HANDLE_VALUE;
56 else
57 mmap_fd = (HANDLE)_get_osfhandle(fd);
58 h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL);
59 if (h == NULL)
60 return MAP_FAILED;
61
62 DWORD dwDesiredAccess;
63 if (prot & PROT_WRITE)
64 dwDesiredAccess = FILE_MAP_WRITE;
65 else
66 dwDesiredAccess = FILE_MAP_READ;
67 if (prot & PROT_EXEC)
68 dwDesiredAccess |= FILE_MAP_EXECUTE;
69 if (flags & MAP_PRIVATE)
70 dwDesiredAccess |= FILE_MAP_COPY;
71 void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length);
72 if (ret == NULL) {
73 CloseHandle(h);
74 ret = MAP_FAILED;
75 }
76 return ret;
77 }
78
79 COMPILER_RT_VISIBILITY
munmap(void * addr,size_t length)80 void munmap(void *addr, size_t length)
81 {
82 UnmapViewOfFile(addr);
83 /* ruh-ro, we leaked handle from CreateFileMapping() ... */
84 }
85
86 COMPILER_RT_VISIBILITY
msync(void * addr,size_t length,int flags)87 int msync(void *addr, size_t length, int flags)
88 {
89 if (flags & MS_INVALIDATE)
90 return -1; /* Not supported. */
91
92 /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */
93 switch (flags & (MS_ASYNC | MS_SYNC)) {
94 case MS_SYNC:
95 case MS_ASYNC:
96 break;
97 default:
98 return -1;
99 }
100
101 if (!FlushViewOfFile(addr, length))
102 return -1;
103
104 if (flags & MS_SYNC) {
105 /* FIXME: No longer have access to handle from CreateFileMapping(). */
106 /*
107 * if (!FlushFileBuffers(h))
108 * return -1;
109 */
110 }
111
112 return 0;
113 }
114
115 COMPILER_RT_VISIBILITY
madvise(void * addr,size_t length,int advice)116 int madvise(void *addr, size_t length, int advice)
117 {
118 if (advice != MADV_DONTNEED)
119 return -1; /* Not supported. */
120
121 if (!VirtualUnlock(addr, length))
122 return -1;
123
124 return 0;
125 }
126
127 COMPILER_RT_VISIBILITY
lock(HANDLE handle,DWORD lockType,BOOL blocking)128 int lock(HANDLE handle, DWORD lockType, BOOL blocking) {
129 DWORD flags = lockType;
130 if (!blocking)
131 flags |= LOCKFILE_FAIL_IMMEDIATELY;
132
133 OVERLAPPED overlapped;
134 ZeroMemory(&overlapped, sizeof(OVERLAPPED));
135 overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
136 BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped);
137 if (!result) {
138 DWORD dw = GetLastError();
139
140 // In non-blocking mode, return an error if the file is locked.
141 if (!blocking && dw == ERROR_LOCK_VIOLATION)
142 return -1; // EWOULDBLOCK
143
144 // If the error is ERROR_IO_PENDING, we need to wait until the operation
145 // finishes. Otherwise, we return an error.
146 if (dw != ERROR_IO_PENDING)
147 return -1;
148
149 DWORD dwNumBytes;
150 if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE))
151 return -1;
152 }
153
154 return 0;
155 }
156
157 COMPILER_RT_VISIBILITY
flock(int fd,int operation)158 int flock(int fd, int operation) {
159 HANDLE handle = (HANDLE)_get_osfhandle(fd);
160 if (handle == INVALID_HANDLE_VALUE)
161 return -1;
162
163 BOOL blocking = (operation & LOCK_NB) == 0;
164 int op = operation & ~LOCK_NB;
165
166 switch (op) {
167 case LOCK_EX:
168 return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking);
169
170 case LOCK_SH:
171 return lock(handle, 0, blocking);
172
173 case LOCK_UN:
174 if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD))
175 return -1;
176 break;
177
178 default:
179 return -1;
180 }
181
182 return 0;
183 }
184
185 #undef DWORD_HI
186 #undef DWORD_LO
187
188 #endif /* _WIN32 */
189