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 27COMPILER_RT_VISIBILITY 28void *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 79COMPILER_RT_VISIBILITY 80void munmap(void *addr, size_t length) 81{ 82 UnmapViewOfFile(addr); 83 /* ruh-ro, we leaked handle from CreateFileMapping() ... */ 84} 85 86COMPILER_RT_VISIBILITY 87int 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 115COMPILER_RT_VISIBILITY 116int 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 145COMPILER_RT_VISIBILITY 146int 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