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