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 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 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 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 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 static int lock(HANDLE handle, DWORD lockType, BOOL blocking) { 128 DWORD flags = lockType; 129 if (!blocking) 130 flags |= LOCKFILE_FAIL_IMMEDIATELY; 131 132 OVERLAPPED overlapped; 133 ZeroMemory(&overlapped, sizeof(OVERLAPPED)); 134 overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 135 BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped); 136 if (!result) { 137 DWORD dw = GetLastError(); 138 139 // In non-blocking mode, return an error if the file is locked. 140 if (!blocking && dw == ERROR_LOCK_VIOLATION) 141 return -1; // EWOULDBLOCK 142 143 // If the error is ERROR_IO_PENDING, we need to wait until the operation 144 // finishes. Otherwise, we return an error. 145 if (dw != ERROR_IO_PENDING) 146 return -1; 147 148 DWORD dwNumBytes; 149 if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE)) 150 return -1; 151 } 152 153 return 0; 154 } 155 156 COMPILER_RT_VISIBILITY 157 int flock(int fd, int operation) { 158 HANDLE handle = (HANDLE)_get_osfhandle(fd); 159 if (handle == INVALID_HANDLE_VALUE) 160 return -1; 161 162 BOOL blocking = (operation & LOCK_NB) == 0; 163 int op = operation & ~LOCK_NB; 164 165 switch (op) { 166 case LOCK_EX: 167 return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking); 168 169 case LOCK_SH: 170 return lock(handle, 0, blocking); 171 172 case LOCK_UN: 173 if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD)) 174 return -1; 175 break; 176 177 default: 178 return -1; 179 } 180 181 return 0; 182 } 183 184 #undef DWORD_HI 185 #undef DWORD_LO 186 187 #endif /* _WIN32 */ 188