|  | /* | 
|  | * This code is derived from uClibc (original license follows). | 
|  | * https://git.uclibc.org/uClibc/tree/utils/mmap-windows.c | 
|  | */ | 
|  | /* mmap() replacement for Windows | 
|  | * | 
|  | * Author: Mike Frysinger <vapier@gentoo.org> | 
|  | * Placed into the public domain | 
|  | */ | 
|  |  | 
|  | /* References: | 
|  | * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx | 
|  | * CloseHandle:       http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx | 
|  | * MapViewOfFile:     http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx | 
|  | * UnmapViewOfFile:   http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx | 
|  | */ | 
|  |  | 
|  | #if defined(_WIN32) | 
|  |  | 
|  | #include "WindowsMMap.h" | 
|  |  | 
|  | #define WIN32_LEAN_AND_MEAN | 
|  | #include <windows.h> | 
|  |  | 
|  | #include "InstrProfiling.h" | 
|  |  | 
|  | COMPILER_RT_VISIBILITY | 
|  | void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) | 
|  | { | 
|  | if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) | 
|  | return MAP_FAILED; | 
|  | if (fd == -1) { | 
|  | if (!(flags & MAP_ANON) || offset) | 
|  | return MAP_FAILED; | 
|  | } else if (flags & MAP_ANON) | 
|  | return MAP_FAILED; | 
|  |  | 
|  | DWORD flProtect; | 
|  | if (prot & PROT_WRITE) { | 
|  | if (prot & PROT_EXEC) | 
|  | flProtect = PAGE_EXECUTE_READWRITE; | 
|  | else | 
|  | flProtect = PAGE_READWRITE; | 
|  | } else if (prot & PROT_EXEC) { | 
|  | if (prot & PROT_READ) | 
|  | flProtect = PAGE_EXECUTE_READ; | 
|  | else if (prot & PROT_EXEC) | 
|  | flProtect = PAGE_EXECUTE; | 
|  | } else | 
|  | flProtect = PAGE_READONLY; | 
|  |  | 
|  | off_t end = length + offset; | 
|  | HANDLE mmap_fd, h; | 
|  | if (fd == -1) | 
|  | mmap_fd = INVALID_HANDLE_VALUE; | 
|  | else | 
|  | mmap_fd = (HANDLE)_get_osfhandle(fd); | 
|  | h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); | 
|  | if (h == NULL) | 
|  | return MAP_FAILED; | 
|  |  | 
|  | DWORD dwDesiredAccess; | 
|  | if (prot & PROT_WRITE) | 
|  | dwDesiredAccess = FILE_MAP_WRITE; | 
|  | else | 
|  | dwDesiredAccess = FILE_MAP_READ; | 
|  | if (prot & PROT_EXEC) | 
|  | dwDesiredAccess |= FILE_MAP_EXECUTE; | 
|  | if (flags & MAP_PRIVATE) | 
|  | dwDesiredAccess |= FILE_MAP_COPY; | 
|  | void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); | 
|  | if (ret == NULL) { | 
|  | CloseHandle(h); | 
|  | ret = MAP_FAILED; | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | COMPILER_RT_VISIBILITY | 
|  | void munmap(void *addr, size_t length) | 
|  | { | 
|  | UnmapViewOfFile(addr); | 
|  | /* ruh-ro, we leaked handle from CreateFileMapping() ... */ | 
|  | } | 
|  |  | 
|  | COMPILER_RT_VISIBILITY | 
|  | int msync(void *addr, size_t length, int flags) | 
|  | { | 
|  | if (flags & MS_INVALIDATE) | 
|  | return -1; /* Not supported. */ | 
|  |  | 
|  | /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */ | 
|  | switch (flags & (MS_ASYNC | MS_SYNC)) { | 
|  | case MS_SYNC: | 
|  | case MS_ASYNC: | 
|  | break; | 
|  | default: | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (!FlushViewOfFile(addr, length)) | 
|  | return -1; | 
|  |  | 
|  | if (flags & MS_SYNC) { | 
|  | /* FIXME: No longer have access to handle from CreateFileMapping(). */ | 
|  | /* | 
|  | * if (!FlushFileBuffers(h)) | 
|  | *   return -1; | 
|  | */ | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | COMPILER_RT_VISIBILITY | 
|  | int lock(HANDLE handle, DWORD lockType, BOOL blocking) { | 
|  | DWORD flags = lockType; | 
|  | if (!blocking) | 
|  | flags |= LOCKFILE_FAIL_IMMEDIATELY; | 
|  |  | 
|  | OVERLAPPED overlapped; | 
|  | ZeroMemory(&overlapped, sizeof(OVERLAPPED)); | 
|  | overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 
|  | BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped); | 
|  | if (!result) { | 
|  | DWORD dw = GetLastError(); | 
|  |  | 
|  | // In non-blocking mode, return an error if the file is locked. | 
|  | if (!blocking && dw == ERROR_LOCK_VIOLATION) | 
|  | return -1; // EWOULDBLOCK | 
|  |  | 
|  | // If the error is ERROR_IO_PENDING, we need to wait until the operation | 
|  | // finishes. Otherwise, we return an error. | 
|  | if (dw != ERROR_IO_PENDING) | 
|  | return -1; | 
|  |  | 
|  | DWORD dwNumBytes; | 
|  | if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE)) | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | COMPILER_RT_VISIBILITY | 
|  | int flock(int fd, int operation) { | 
|  | HANDLE handle = (HANDLE)_get_osfhandle(fd); | 
|  | if (handle == INVALID_HANDLE_VALUE) | 
|  | return -1; | 
|  |  | 
|  | BOOL blocking = (operation & LOCK_NB) == 0; | 
|  | int op = operation & ~LOCK_NB; | 
|  |  | 
|  | switch (op) { | 
|  | case LOCK_EX: | 
|  | return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking); | 
|  |  | 
|  | case LOCK_SH: | 
|  | return lock(handle, 0, blocking); | 
|  |  | 
|  | case LOCK_UN: | 
|  | if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD)) | 
|  | return -1; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | #undef DWORD_HI | 
|  | #undef DWORD_LO | 
|  |  | 
|  | #endif /* _WIN32 */ |