xref: /openbsd-src/gnu/llvm/compiler-rt/lib/profile/WindowsMMap.c (revision d89ec533011f513df1010f142a111086a0785f09)
13cab2bb3Spatrick /*
23cab2bb3Spatrick  * This code is derived from uClibc (original license follows).
33cab2bb3Spatrick  * https://git.uclibc.org/uClibc/tree/utils/mmap-windows.c
43cab2bb3Spatrick  */
53cab2bb3Spatrick  /* mmap() replacement for Windows
63cab2bb3Spatrick  *
73cab2bb3Spatrick  * Author: Mike Frysinger <vapier@gentoo.org>
83cab2bb3Spatrick  * Placed into the public domain
93cab2bb3Spatrick  */
103cab2bb3Spatrick 
113cab2bb3Spatrick /* References:
123cab2bb3Spatrick  * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
133cab2bb3Spatrick  * CloseHandle:       http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
143cab2bb3Spatrick  * MapViewOfFile:     http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
153cab2bb3Spatrick  * UnmapViewOfFile:   http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
163cab2bb3Spatrick  */
173cab2bb3Spatrick 
183cab2bb3Spatrick #if defined(_WIN32)
193cab2bb3Spatrick 
203cab2bb3Spatrick #include "WindowsMMap.h"
213cab2bb3Spatrick 
223cab2bb3Spatrick #define WIN32_LEAN_AND_MEAN
233cab2bb3Spatrick #include <windows.h>
243cab2bb3Spatrick 
253cab2bb3Spatrick #include "InstrProfiling.h"
263cab2bb3Spatrick 
273cab2bb3Spatrick COMPILER_RT_VISIBILITY
mmap(void * start,size_t length,int prot,int flags,int fd,off_t offset)283cab2bb3Spatrick void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
293cab2bb3Spatrick {
303cab2bb3Spatrick   if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
313cab2bb3Spatrick     return MAP_FAILED;
323cab2bb3Spatrick   if (fd == -1) {
333cab2bb3Spatrick     if (!(flags & MAP_ANON) || offset)
343cab2bb3Spatrick       return MAP_FAILED;
353cab2bb3Spatrick   } else if (flags & MAP_ANON)
363cab2bb3Spatrick     return MAP_FAILED;
373cab2bb3Spatrick 
383cab2bb3Spatrick   DWORD flProtect;
393cab2bb3Spatrick   if (prot & PROT_WRITE) {
403cab2bb3Spatrick     if (prot & PROT_EXEC)
413cab2bb3Spatrick       flProtect = PAGE_EXECUTE_READWRITE;
423cab2bb3Spatrick     else
433cab2bb3Spatrick       flProtect = PAGE_READWRITE;
443cab2bb3Spatrick   } else if (prot & PROT_EXEC) {
453cab2bb3Spatrick     if (prot & PROT_READ)
463cab2bb3Spatrick       flProtect = PAGE_EXECUTE_READ;
473cab2bb3Spatrick     else if (prot & PROT_EXEC)
483cab2bb3Spatrick       flProtect = PAGE_EXECUTE;
493cab2bb3Spatrick   } else
503cab2bb3Spatrick     flProtect = PAGE_READONLY;
513cab2bb3Spatrick 
523cab2bb3Spatrick   off_t end = length + offset;
533cab2bb3Spatrick   HANDLE mmap_fd, h;
543cab2bb3Spatrick   if (fd == -1)
553cab2bb3Spatrick     mmap_fd = INVALID_HANDLE_VALUE;
563cab2bb3Spatrick   else
573cab2bb3Spatrick     mmap_fd = (HANDLE)_get_osfhandle(fd);
583cab2bb3Spatrick   h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL);
593cab2bb3Spatrick   if (h == NULL)
603cab2bb3Spatrick     return MAP_FAILED;
613cab2bb3Spatrick 
623cab2bb3Spatrick   DWORD dwDesiredAccess;
633cab2bb3Spatrick   if (prot & PROT_WRITE)
643cab2bb3Spatrick     dwDesiredAccess = FILE_MAP_WRITE;
653cab2bb3Spatrick   else
663cab2bb3Spatrick     dwDesiredAccess = FILE_MAP_READ;
673cab2bb3Spatrick   if (prot & PROT_EXEC)
683cab2bb3Spatrick     dwDesiredAccess |= FILE_MAP_EXECUTE;
693cab2bb3Spatrick   if (flags & MAP_PRIVATE)
703cab2bb3Spatrick     dwDesiredAccess |= FILE_MAP_COPY;
713cab2bb3Spatrick   void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length);
723cab2bb3Spatrick   if (ret == NULL) {
733cab2bb3Spatrick     CloseHandle(h);
743cab2bb3Spatrick     ret = MAP_FAILED;
753cab2bb3Spatrick   }
763cab2bb3Spatrick   return ret;
773cab2bb3Spatrick }
783cab2bb3Spatrick 
793cab2bb3Spatrick COMPILER_RT_VISIBILITY
munmap(void * addr,size_t length)803cab2bb3Spatrick void munmap(void *addr, size_t length)
813cab2bb3Spatrick {
823cab2bb3Spatrick   UnmapViewOfFile(addr);
833cab2bb3Spatrick   /* ruh-ro, we leaked handle from CreateFileMapping() ... */
843cab2bb3Spatrick }
853cab2bb3Spatrick 
863cab2bb3Spatrick COMPILER_RT_VISIBILITY
msync(void * addr,size_t length,int flags)873cab2bb3Spatrick int msync(void *addr, size_t length, int flags)
883cab2bb3Spatrick {
893cab2bb3Spatrick   if (flags & MS_INVALIDATE)
903cab2bb3Spatrick     return -1; /* Not supported. */
913cab2bb3Spatrick 
923cab2bb3Spatrick   /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */
933cab2bb3Spatrick   switch (flags & (MS_ASYNC | MS_SYNC)) {
943cab2bb3Spatrick     case MS_SYNC:
953cab2bb3Spatrick     case MS_ASYNC:
963cab2bb3Spatrick       break;
973cab2bb3Spatrick     default:
983cab2bb3Spatrick       return -1;
993cab2bb3Spatrick   }
1003cab2bb3Spatrick 
1013cab2bb3Spatrick   if (!FlushViewOfFile(addr, length))
1023cab2bb3Spatrick     return -1;
1033cab2bb3Spatrick 
1043cab2bb3Spatrick   if (flags & MS_SYNC) {
1053cab2bb3Spatrick     /* FIXME: No longer have access to handle from CreateFileMapping(). */
1063cab2bb3Spatrick     /*
1073cab2bb3Spatrick      * if (!FlushFileBuffers(h))
1083cab2bb3Spatrick      *   return -1;
1093cab2bb3Spatrick      */
1103cab2bb3Spatrick   }
1113cab2bb3Spatrick 
1123cab2bb3Spatrick   return 0;
1133cab2bb3Spatrick }
1143cab2bb3Spatrick 
1153cab2bb3Spatrick COMPILER_RT_VISIBILITY
madvise(void * addr,size_t length,int advice)116*d89ec533Spatrick int madvise(void *addr, size_t length, int advice)
117*d89ec533Spatrick {
118*d89ec533Spatrick   if (advice != MADV_DONTNEED)
119*d89ec533Spatrick     return -1; /* Not supported. */
120*d89ec533Spatrick 
121*d89ec533Spatrick   if (!VirtualUnlock(addr, length))
122*d89ec533Spatrick     return -1;
123*d89ec533Spatrick 
124*d89ec533Spatrick   return 0;
125*d89ec533Spatrick }
126*d89ec533Spatrick 
127*d89ec533Spatrick COMPILER_RT_VISIBILITY
lock(HANDLE handle,DWORD lockType,BOOL blocking)1283cab2bb3Spatrick int lock(HANDLE handle, DWORD lockType, BOOL blocking) {
1293cab2bb3Spatrick   DWORD flags = lockType;
1303cab2bb3Spatrick   if (!blocking)
1313cab2bb3Spatrick     flags |= LOCKFILE_FAIL_IMMEDIATELY;
1323cab2bb3Spatrick 
1333cab2bb3Spatrick   OVERLAPPED overlapped;
1343cab2bb3Spatrick   ZeroMemory(&overlapped, sizeof(OVERLAPPED));
1353cab2bb3Spatrick   overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1363cab2bb3Spatrick   BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped);
1373cab2bb3Spatrick   if (!result) {
1383cab2bb3Spatrick     DWORD dw = GetLastError();
1393cab2bb3Spatrick 
1403cab2bb3Spatrick     // In non-blocking mode, return an error if the file is locked.
1413cab2bb3Spatrick     if (!blocking && dw == ERROR_LOCK_VIOLATION)
1423cab2bb3Spatrick       return -1; // EWOULDBLOCK
1433cab2bb3Spatrick 
1443cab2bb3Spatrick     // If the error is ERROR_IO_PENDING, we need to wait until the operation
1453cab2bb3Spatrick     // finishes. Otherwise, we return an error.
1463cab2bb3Spatrick     if (dw != ERROR_IO_PENDING)
1473cab2bb3Spatrick       return -1;
1483cab2bb3Spatrick 
1493cab2bb3Spatrick     DWORD dwNumBytes;
1503cab2bb3Spatrick     if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE))
1513cab2bb3Spatrick       return -1;
1523cab2bb3Spatrick   }
1533cab2bb3Spatrick 
1543cab2bb3Spatrick   return 0;
1553cab2bb3Spatrick }
1563cab2bb3Spatrick 
1573cab2bb3Spatrick COMPILER_RT_VISIBILITY
flock(int fd,int operation)1583cab2bb3Spatrick int flock(int fd, int operation) {
1593cab2bb3Spatrick   HANDLE handle = (HANDLE)_get_osfhandle(fd);
1603cab2bb3Spatrick   if (handle == INVALID_HANDLE_VALUE)
1613cab2bb3Spatrick     return -1;
1623cab2bb3Spatrick 
1633cab2bb3Spatrick   BOOL blocking = (operation & LOCK_NB) == 0;
1643cab2bb3Spatrick   int op = operation & ~LOCK_NB;
1653cab2bb3Spatrick 
1663cab2bb3Spatrick   switch (op) {
1673cab2bb3Spatrick   case LOCK_EX:
1683cab2bb3Spatrick     return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking);
1693cab2bb3Spatrick 
1703cab2bb3Spatrick   case LOCK_SH:
1713cab2bb3Spatrick     return lock(handle, 0, blocking);
1723cab2bb3Spatrick 
1733cab2bb3Spatrick   case LOCK_UN:
1743cab2bb3Spatrick     if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD))
1753cab2bb3Spatrick       return -1;
1763cab2bb3Spatrick     break;
1773cab2bb3Spatrick 
1783cab2bb3Spatrick   default:
1793cab2bb3Spatrick     return -1;
1803cab2bb3Spatrick   }
1813cab2bb3Spatrick 
1823cab2bb3Spatrick   return 0;
1833cab2bb3Spatrick }
1843cab2bb3Spatrick 
1853cab2bb3Spatrick #undef DWORD_HI
1863cab2bb3Spatrick #undef DWORD_LO
1873cab2bb3Spatrick 
1883cab2bb3Spatrick #endif /* _WIN32 */
189