1293253Sdim/* 2293253Sdim * This code is derived from uClibc (original license follows). 3293253Sdim * https://git.uclibc.org/uClibc/tree/utils/mmap-windows.c 4293253Sdim */ 5293253Sdim /* mmap() replacement for Windows 6293253Sdim * 7293253Sdim * Author: Mike Frysinger <vapier@gentoo.org> 8293253Sdim * Placed into the public domain 9293253Sdim */ 10293253Sdim 11293253Sdim/* References: 12293253Sdim * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx 13293253Sdim * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx 14293253Sdim * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx 15293253Sdim * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx 16293253Sdim */ 17293253Sdim 18293253Sdim#if defined(_WIN32) 19293253Sdim 20293253Sdim#include "WindowsMMap.h" 21293253Sdim 22314564Sdim#define WIN32_LEAN_AND_MEAN 23314564Sdim#include <windows.h> 24314564Sdim 25327952Sdim#include "InstrProfiling.h" 26327952Sdim 27293253SdimCOMPILER_RT_VISIBILITY 28293253Sdimvoid *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) 29293253Sdim{ 30293253Sdim if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) 31293253Sdim return MAP_FAILED; 32293253Sdim if (fd == -1) { 33293253Sdim if (!(flags & MAP_ANON) || offset) 34293253Sdim return MAP_FAILED; 35293253Sdim } else if (flags & MAP_ANON) 36293253Sdim return MAP_FAILED; 37293253Sdim 38293253Sdim DWORD flProtect; 39293253Sdim if (prot & PROT_WRITE) { 40293253Sdim if (prot & PROT_EXEC) 41293253Sdim flProtect = PAGE_EXECUTE_READWRITE; 42293253Sdim else 43293253Sdim flProtect = PAGE_READWRITE; 44293253Sdim } else if (prot & PROT_EXEC) { 45293253Sdim if (prot & PROT_READ) 46293253Sdim flProtect = PAGE_EXECUTE_READ; 47293253Sdim else if (prot & PROT_EXEC) 48293253Sdim flProtect = PAGE_EXECUTE; 49293253Sdim } else 50293253Sdim flProtect = PAGE_READONLY; 51293253Sdim 52293253Sdim off_t end = length + offset; 53293253Sdim HANDLE mmap_fd, h; 54293253Sdim if (fd == -1) 55293253Sdim mmap_fd = INVALID_HANDLE_VALUE; 56293253Sdim else 57293253Sdim mmap_fd = (HANDLE)_get_osfhandle(fd); 58293253Sdim h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); 59293253Sdim if (h == NULL) 60293253Sdim return MAP_FAILED; 61293253Sdim 62293253Sdim DWORD dwDesiredAccess; 63293253Sdim if (prot & PROT_WRITE) 64293253Sdim dwDesiredAccess = FILE_MAP_WRITE; 65293253Sdim else 66293253Sdim dwDesiredAccess = FILE_MAP_READ; 67293253Sdim if (prot & PROT_EXEC) 68293253Sdim dwDesiredAccess |= FILE_MAP_EXECUTE; 69293253Sdim if (flags & MAP_PRIVATE) 70293253Sdim dwDesiredAccess |= FILE_MAP_COPY; 71293253Sdim void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); 72293253Sdim if (ret == NULL) { 73293253Sdim CloseHandle(h); 74293253Sdim ret = MAP_FAILED; 75293253Sdim } 76293253Sdim return ret; 77293253Sdim} 78293253Sdim 79293253SdimCOMPILER_RT_VISIBILITY 80293253Sdimvoid munmap(void *addr, size_t length) 81293253Sdim{ 82293253Sdim UnmapViewOfFile(addr); 83293253Sdim /* ruh-ro, we leaked handle from CreateFileMapping() ... */ 84293253Sdim} 85293253Sdim 86293253SdimCOMPILER_RT_VISIBILITY 87293253Sdimint msync(void *addr, size_t length, int flags) 88293253Sdim{ 89293253Sdim if (flags & MS_INVALIDATE) 90293253Sdim return -1; /* Not supported. */ 91293253Sdim 92293253Sdim /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */ 93293253Sdim switch (flags & (MS_ASYNC | MS_SYNC)) { 94293253Sdim case MS_SYNC: 95293253Sdim case MS_ASYNC: 96293253Sdim break; 97293253Sdim default: 98293253Sdim return -1; 99293253Sdim } 100293253Sdim 101293253Sdim if (!FlushViewOfFile(addr, length)) 102293253Sdim return -1; 103293253Sdim 104293253Sdim if (flags & MS_SYNC) { 105293253Sdim /* FIXME: No longer have access to handle from CreateFileMapping(). */ 106293253Sdim /* 107293253Sdim * if (!FlushFileBuffers(h)) 108293253Sdim * return -1; 109293253Sdim */ 110293253Sdim } 111293253Sdim 112293253Sdim return 0; 113293253Sdim} 114293253Sdim 115293253SdimCOMPILER_RT_VISIBILITY 116327952Sdimint lock(HANDLE handle, DWORD lockType, BOOL blocking) { 117327952Sdim DWORD flags = lockType; 118327952Sdim if (!blocking) 119327952Sdim flags |= LOCKFILE_FAIL_IMMEDIATELY; 120327952Sdim 121327952Sdim OVERLAPPED overlapped; 122327952Sdim ZeroMemory(&overlapped, sizeof(OVERLAPPED)); 123327952Sdim overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 124327952Sdim BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped); 125327952Sdim if (!result) { 126327952Sdim DWORD dw = GetLastError(); 127327952Sdim 128327952Sdim // In non-blocking mode, return an error if the file is locked. 129327952Sdim if (!blocking && dw == ERROR_LOCK_VIOLATION) 130327952Sdim return -1; // EWOULDBLOCK 131327952Sdim 132327952Sdim // If the error is ERROR_IO_PENDING, we need to wait until the operation 133327952Sdim // finishes. Otherwise, we return an error. 134327952Sdim if (dw != ERROR_IO_PENDING) 135327952Sdim return -1; 136327952Sdim 137327952Sdim DWORD dwNumBytes; 138327952Sdim if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE)) 139327952Sdim return -1; 140327952Sdim } 141327952Sdim 142327952Sdim return 0; 143293253Sdim} 144293253Sdim 145327952SdimCOMPILER_RT_VISIBILITY 146327952Sdimint flock(int fd, int operation) { 147327952Sdim HANDLE handle = (HANDLE)_get_osfhandle(fd); 148327952Sdim if (handle == INVALID_HANDLE_VALUE) 149327952Sdim return -1; 150327952Sdim 151327952Sdim BOOL blocking = (operation & LOCK_NB) == 0; 152327952Sdim int op = operation & ~LOCK_NB; 153327952Sdim 154327952Sdim switch (op) { 155327952Sdim case LOCK_EX: 156327952Sdim return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking); 157327952Sdim 158327952Sdim case LOCK_SH: 159327952Sdim return lock(handle, 0, blocking); 160327952Sdim 161327952Sdim case LOCK_UN: 162327952Sdim if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD)) 163327952Sdim return -1; 164327952Sdim break; 165327952Sdim 166327952Sdim default: 167327952Sdim return -1; 168327952Sdim } 169327952Sdim 170327952Sdim return 0; 171327952Sdim} 172327952Sdim 173293253Sdim#undef DWORD_HI 174293253Sdim#undef DWORD_LO 175293253Sdim 176293253Sdim#endif /* _WIN32 */ 177