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