Port: Add mman.h compat for mingw
[babeltrace.git] / compat / compat_mman.c
CommitLineData
8f76831a
MJ
1/*
2 * compat/compat_mman.h
3 *
4 * Copyright (C) 2013 JP Ikaheimonen <jp_ikaheimonen@mentor.com>
5 * 2016 Michael Jeanson <mjeanson@efficios.com>
6 *
7 * These sources are based on ftp://g.oswego.edu/pub/misc/malloc.c
8 * file by Doug Lea, released to the public domain.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29#ifdef __MINGW32__
30
31#include <assert.h>
32#include <errno.h>
33#include <io.h>
34#include <pthread.h>
35#include <stdlib.h>
36#include <windows.h>
37#include <babeltrace/compat/mman-internal.h>
38
39struct mmap_info {
40 HANDLE file_handle; /* the duplicated handle */
41 HANDLE map_handle; /* handle returned by CreateFileMapping */
42 void *start; /* ptr returned by MapViewOfFile */
43};
44
45/*
46 * This mutex protects the array of memory mappings and its associated
47 * counters. (mmap_infos, mmap_infos_cur mmap_infos_max)
48 */
49static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
50
51static int mmap_infos_cur = 0;
52static int mmap_infos_max = 0;
53static struct mmap_info *mmap_infos = NULL;
54
55#define NEW_MMAP_STRUCT_CNT 10
56
57static
58void mmap_lock(void)
59{
60 if (pthread_mutex_lock(&mmap_mutex)) {
61 assert(0);
62 }
63}
64
65static
66void mmap_unlock(void)
67{
68 if (pthread_mutex_unlock(&mmap_mutex)) {
69 assert(0);
70 }
71}
72
73/*
74 * Convert mmap memory protection flags to CreateFileMapping page protection
75 * flag and MapViewOfFile desired access flag.
76 */
77static
78DWORD map_prot_flags(int prot, DWORD *dwDesiredAccess)
79{
80 if (prot & PROT_READ) {
81 if (prot & PROT_WRITE) {
82 *dwDesiredAccess = FILE_MAP_WRITE;
83 if (prot & PROT_EXEC) {
84 return PAGE_EXECUTE_READWRITE;
85 }
86 return PAGE_READWRITE;
87 }
88 if (prot & PROT_EXEC) {
89 *dwDesiredAccess = FILE_MAP_EXECUTE;
90 return PAGE_EXECUTE_READ;
91 }
92 *dwDesiredAccess = FILE_MAP_READ;
93 return PAGE_READONLY;
94 }
95 if (prot & PROT_WRITE) {
96 *dwDesiredAccess = FILE_MAP_COPY;
97 return PAGE_WRITECOPY;
98 }
99 if (prot & PROT_EXEC) {
100 *dwDesiredAccess = FILE_MAP_EXECUTE;
101 return PAGE_EXECUTE_READ;
102 }
103
104 /* Mapping failed */
105 *dwDesiredAccess = 0;
106 return 0;
107}
108
109void *mmap(void *start, size_t length, int prot, int flags, int fd,
110 off_t offset)
111{
112 struct mmap_info mapping;
113 DWORD dwDesiredAccess;
114 DWORD flProtect;
115 HANDLE handle;
116
117 /* Check for a valid fd */
118 if (fd == -1) {
119 _set_errno(EBADF);
120 return MAP_FAILED;
121 }
122
123 /* we don't support this atm */
124 if (flags == MAP_FIXED) {
125 _set_errno(ENOTSUP);
126 return MAP_FAILED;
127 }
128
129 /* Map mmap flags to windows API */
130 flProtect = map_prot_flags(prot, &dwDesiredAccess);
131 if (flProtect == 0) {
132 _set_errno(EINVAL);
133 return MAP_FAILED;
134 }
135
136 /* Get a handle from the fd */
137 handle = (HANDLE) _get_osfhandle(fd);
138
139 /* Duplicate the handle and store it in 'mapping.file_handle' */
140 if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
141 &mapping.file_handle, 0, FALSE,
142 DUPLICATE_SAME_ACCESS)) {
143 return MAP_FAILED;
144 }
145
146 /*
147 * Create a file mapping object with a maximum size
148 * of 'offset' + 'length'
149 */
150 mapping.map_handle = CreateFileMapping(mapping.file_handle, NULL,
151 flProtect, 0, offset + length, NULL);
152 if (mapping.map_handle == 0) {
153 if (!CloseHandle(mapping.file_handle)) {
154 assert(0);
155 }
156 _set_errno(EACCES);
157 return MAP_FAILED;
158 }
159
160 /* Map the requested block starting at 'offset' for 'length' bytes */
161 mapping.start = MapViewOfFile(mapping.map_handle, dwDesiredAccess, 0,
162 offset, length);
163 if (mapping.start == 0) {
164 DWORD dwLastErr = GetLastError();
165 if (!CloseHandle(mapping.map_handle)) {
166 assert(0);
167 }
168 if (!CloseHandle(mapping.file_handle)) {
169 assert(0);
170 }
171
172 if (dwLastErr == ERROR_MAPPED_ALIGNMENT) {
173 _set_errno(EINVAL);
174 } else {
175 _set_errno(EACCES);
176 }
177
178 return MAP_FAILED;
179 }
180
181 mmap_lock();
182
183 /* If we have never done any mappings, allocate the array */
184 if (mmap_infos == NULL) {
185 mmap_infos_max = NEW_MMAP_STRUCT_CNT;
186 mmap_infos = (struct mmap_info *) calloc(mmap_infos_max,
187 sizeof(struct mmap_info));
188 if (mmap_infos == NULL) {
189 mmap_infos_max = 0;
190 goto error_mutex_unlock;
191 }
192 }
193
194 /* if we have reached our current mapping limit, expand it */
195 if (mmap_infos_cur == mmap_infos_max) {
196 struct mmap_info *realloc_mmap_infos = NULL;
197
198 mmap_infos_max += NEW_MMAP_STRUCT_CNT;
199 realloc_mmap_infos = (struct mmap_info *) realloc(mmap_infos,
200 mmap_infos_max * sizeof(struct mmap_info));
201 if (realloc_mmap_infos == NULL) {
202 mmap_infos_max -= NEW_MMAP_STRUCT_CNT;
203 goto error_mutex_unlock;
204 }
205 mmap_infos = realloc_mmap_infos;
206 }
207
208 /* Add the new mapping to the array */
209 memcpy(&mmap_infos[mmap_infos_cur], &mapping,
210 sizeof(struct mmap_info));
211 mmap_infos_cur++;
212
213 mmap_unlock();
214
215 return mapping.start;
216
217error_mutex_unlock:
218 mmap_unlock();
219
220 if (!CloseHandle(mapping.map_handle)) {
221 assert(0);
222 }
223 if (!CloseHandle(mapping.file_handle)) {
224 assert(0);
225 }
226
227 _set_errno(ENOMEM);
228 return MAP_FAILED;
229}
230
231int munmap(void *start, size_t length)
232{
233 int i, j;
234
235 /* Find the mapping to unmap */
236 for (i = 0; i < mmap_infos_cur; i++) {
237 if (mmap_infos[i].start == start)
238 break;
239 }
240
241 /* Mapping was not found */
242 if (i == mmap_infos_cur) {
243 _set_errno(EINVAL);
244 return -1;
245 }
246
247 /* Cleanup of handles should never fail */
248 if (!UnmapViewOfFile(mmap_infos[i].start)) {
249 assert(0);
250 }
251 if (!CloseHandle(mmap_infos[i].map_handle)) {
252 assert(0);
253 }
254 if (!CloseHandle(mmap_infos[i].file_handle)) {
255 assert(0);
256 }
257
258 mmap_lock();
259
260 /* Clean the mapping list */
261 for (j = i + 1; j < mmap_infos_cur; j++) {
262 memcpy(&mmap_infos[j - 1], &mmap_infos[j],
263 sizeof(struct mmap_info));
264 }
265 mmap_infos_cur--;
266
267 /* If the mapping list is now empty, free it */
268 if (mmap_infos_cur == 0) {
269 free(mmap_infos);
270 mmap_infos = NULL;
271 mmap_infos_max = 0;
272 }
273
274 mmap_unlock();
275
276 return 0;
277}
278
279#endif
This page took 0.032932 seconds and 4 git commands to generate.