Add logging to compat
[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
1f0f70c0
MJ
29#define BT_LOG_TAG "COMPAT-MMAN"
30#include "logging.h"
31
8f76831a
MJ
32#ifdef __MINGW32__
33
34#include <assert.h>
35#include <errno.h>
36#include <io.h>
37#include <pthread.h>
38#include <stdlib.h>
39#include <windows.h>
40#include <babeltrace/compat/mman-internal.h>
41
42struct mmap_info {
43 HANDLE file_handle; /* the duplicated handle */
44 HANDLE map_handle; /* handle returned by CreateFileMapping */
45 void *start; /* ptr returned by MapViewOfFile */
46};
47
48/*
49 * This mutex protects the array of memory mappings and its associated
50 * counters. (mmap_infos, mmap_infos_cur mmap_infos_max)
51 */
52static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
53
54static int mmap_infos_cur = 0;
55static int mmap_infos_max = 0;
56static struct mmap_info *mmap_infos = NULL;
57
58#define NEW_MMAP_STRUCT_CNT 10
59
60static
61void mmap_lock(void)
62{
63 if (pthread_mutex_lock(&mmap_mutex)) {
f23a034a 64 abort();
8f76831a
MJ
65 }
66}
67
68static
69void mmap_unlock(void)
70{
71 if (pthread_mutex_unlock(&mmap_mutex)) {
f23a034a 72 abort();
8f76831a
MJ
73 }
74}
75
76/*
77 * Convert mmap memory protection flags to CreateFileMapping page protection
78 * flag and MapViewOfFile desired access flag.
79 */
80static
81DWORD map_prot_flags(int prot, DWORD *dwDesiredAccess)
82{
83 if (prot & PROT_READ) {
84 if (prot & PROT_WRITE) {
85 *dwDesiredAccess = FILE_MAP_WRITE;
86 if (prot & PROT_EXEC) {
87 return PAGE_EXECUTE_READWRITE;
88 }
89 return PAGE_READWRITE;
90 }
91 if (prot & PROT_EXEC) {
92 *dwDesiredAccess = FILE_MAP_EXECUTE;
93 return PAGE_EXECUTE_READ;
94 }
95 *dwDesiredAccess = FILE_MAP_READ;
96 return PAGE_READONLY;
97 }
98 if (prot & PROT_WRITE) {
99 *dwDesiredAccess = FILE_MAP_COPY;
100 return PAGE_WRITECOPY;
101 }
102 if (prot & PROT_EXEC) {
103 *dwDesiredAccess = FILE_MAP_EXECUTE;
104 return PAGE_EXECUTE_READ;
105 }
106
107 /* Mapping failed */
108 *dwDesiredAccess = 0;
109 return 0;
110}
111
112void *mmap(void *start, size_t length, int prot, int flags, int fd,
113 off_t offset)
114{
115 struct mmap_info mapping;
116 DWORD dwDesiredAccess;
117 DWORD flProtect;
118 HANDLE handle;
119
120 /* Check for a valid fd */
121 if (fd == -1) {
122 _set_errno(EBADF);
123 return MAP_FAILED;
124 }
125
126 /* we don't support this atm */
127 if (flags == MAP_FIXED) {
128 _set_errno(ENOTSUP);
129 return MAP_FAILED;
130 }
131
132 /* Map mmap flags to windows API */
133 flProtect = map_prot_flags(prot, &dwDesiredAccess);
134 if (flProtect == 0) {
135 _set_errno(EINVAL);
136 return MAP_FAILED;
137 }
138
139 /* Get a handle from the fd */
140 handle = (HANDLE) _get_osfhandle(fd);
141
142 /* Duplicate the handle and store it in 'mapping.file_handle' */
143 if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
144 &mapping.file_handle, 0, FALSE,
145 DUPLICATE_SAME_ACCESS)) {
146 return MAP_FAILED;
147 }
148
149 /*
150 * Create a file mapping object with a maximum size
151 * of 'offset' + 'length'
152 */
153 mapping.map_handle = CreateFileMapping(mapping.file_handle, NULL,
154 flProtect, 0, offset + length, NULL);
155 if (mapping.map_handle == 0) {
156 if (!CloseHandle(mapping.file_handle)) {
f23a034a 157 abort();
8f76831a
MJ
158 }
159 _set_errno(EACCES);
160 return MAP_FAILED;
161 }
162
163 /* Map the requested block starting at 'offset' for 'length' bytes */
164 mapping.start = MapViewOfFile(mapping.map_handle, dwDesiredAccess, 0,
165 offset, length);
166 if (mapping.start == 0) {
167 DWORD dwLastErr = GetLastError();
168 if (!CloseHandle(mapping.map_handle)) {
f23a034a 169 abort();
8f76831a
MJ
170 }
171 if (!CloseHandle(mapping.file_handle)) {
f23a034a 172 abort();
8f76831a
MJ
173 }
174
175 if (dwLastErr == ERROR_MAPPED_ALIGNMENT) {
176 _set_errno(EINVAL);
177 } else {
178 _set_errno(EACCES);
179 }
180
181 return MAP_FAILED;
182 }
183
184 mmap_lock();
185
186 /* If we have never done any mappings, allocate the array */
187 if (mmap_infos == NULL) {
188 mmap_infos_max = NEW_MMAP_STRUCT_CNT;
189 mmap_infos = (struct mmap_info *) calloc(mmap_infos_max,
190 sizeof(struct mmap_info));
191 if (mmap_infos == NULL) {
192 mmap_infos_max = 0;
193 goto error_mutex_unlock;
194 }
195 }
196
197 /* if we have reached our current mapping limit, expand it */
198 if (mmap_infos_cur == mmap_infos_max) {
199 struct mmap_info *realloc_mmap_infos = NULL;
200
201 mmap_infos_max += NEW_MMAP_STRUCT_CNT;
202 realloc_mmap_infos = (struct mmap_info *) realloc(mmap_infos,
203 mmap_infos_max * sizeof(struct mmap_info));
204 if (realloc_mmap_infos == NULL) {
205 mmap_infos_max -= NEW_MMAP_STRUCT_CNT;
206 goto error_mutex_unlock;
207 }
208 mmap_infos = realloc_mmap_infos;
209 }
210
211 /* Add the new mapping to the array */
212 memcpy(&mmap_infos[mmap_infos_cur], &mapping,
213 sizeof(struct mmap_info));
214 mmap_infos_cur++;
215
216 mmap_unlock();
217
218 return mapping.start;
219
220error_mutex_unlock:
221 mmap_unlock();
222
223 if (!CloseHandle(mapping.map_handle)) {
f23a034a 224 abort();
8f76831a
MJ
225 }
226 if (!CloseHandle(mapping.file_handle)) {
f23a034a 227 abort();
8f76831a
MJ
228 }
229
230 _set_errno(ENOMEM);
231 return MAP_FAILED;
232}
233
234int munmap(void *start, size_t length)
235{
236 int i, j;
237
238 /* Find the mapping to unmap */
239 for (i = 0; i < mmap_infos_cur; i++) {
240 if (mmap_infos[i].start == start)
241 break;
242 }
243
244 /* Mapping was not found */
245 if (i == mmap_infos_cur) {
246 _set_errno(EINVAL);
247 return -1;
248 }
249
250 /* Cleanup of handles should never fail */
251 if (!UnmapViewOfFile(mmap_infos[i].start)) {
f23a034a 252 abort();
8f76831a
MJ
253 }
254 if (!CloseHandle(mmap_infos[i].map_handle)) {
f23a034a 255 abort();
8f76831a
MJ
256 }
257 if (!CloseHandle(mmap_infos[i].file_handle)) {
f23a034a 258 abort();
8f76831a
MJ
259 }
260
261 mmap_lock();
262
263 /* Clean the mapping list */
264 for (j = i + 1; j < mmap_infos_cur; j++) {
265 memcpy(&mmap_infos[j - 1], &mmap_infos[j],
266 sizeof(struct mmap_info));
267 }
268 mmap_infos_cur--;
269
270 /* If the mapping list is now empty, free it */
271 if (mmap_infos_cur == 0) {
272 free(mmap_infos);
273 mmap_infos = NULL;
274 mmap_infos_max = 0;
275 }
276
277 mmap_unlock();
278
279 return 0;
280}
281
282#endif
This page took 0.035009 seconds and 4 git commands to generate.