]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/profile/WindowsMMap.c
Merge llvm, clang, lld, lldb, compiler-rt and libc++ release_70 branch
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / profile / WindowsMMap.c
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
35 COMPILER_RT_VISIBILITY
36 void *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
87 COMPILER_RT_VISIBILITY
88 void munmap(void *addr, size_t length)
89 {
90   UnmapViewOfFile(addr);
91   /* ruh-ro, we leaked handle from CreateFileMapping() ... */
92 }
93
94 COMPILER_RT_VISIBILITY
95 int 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
123 COMPILER_RT_VISIBILITY
124 int 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
153 COMPILER_RT_VISIBILITY
154 int 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 */