diff options
Diffstat (limited to 'contrib/llvm-project/compiler-rt/lib/profile/WindowsMMap.c')
-rw-r--r-- | contrib/llvm-project/compiler-rt/lib/profile/WindowsMMap.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/contrib/llvm-project/compiler-rt/lib/profile/WindowsMMap.c b/contrib/llvm-project/compiler-rt/lib/profile/WindowsMMap.c new file mode 100644 index 000000000000..41cc67f41f1f --- /dev/null +++ b/contrib/llvm-project/compiler-rt/lib/profile/WindowsMMap.c @@ -0,0 +1,176 @@ +/* + * 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 */ |