lib: fully configure graph (add components, connect ports), then run
[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
18fc0d90
MJ
29#define BT_LOG_TAG "COMPAT-MMAN"
30#include "logging.h"
31
7af8f2e4
MJ
32#ifdef __APPLE__
33/*
34 * On macOS, we need a dummy symbol so that the linker won't
35 * complain of an empty table of contents.
36 */
37BT_HIDDEN
38int bt_mman_dummy_symbol;
39#endif /* __APPLE__ */
40
8f76831a
MJ
41#ifdef __MINGW32__
42
8f76831a
MJ
43#include <errno.h>
44#include <io.h>
45#include <pthread.h>
46#include <stdlib.h>
47#include <windows.h>
48#include <babeltrace/compat/mman-internal.h>
49
a555e971
MJ
50struct mmap_mapping {
51 /* The duplicated handle. */
52 HANDLE file_handle;
53 /* Handle returned by CreateFileMapping. */
54 HANDLE map_handle;
8f76831a
MJ
55};
56
a555e971
MJ
57static
58GHashTable *mmap_mappings = NULL;
59
8f76831a 60/*
a555e971 61 * This mutex protects the hashtable of memory mappings.
8f76831a
MJ
62 */
63static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
64
a555e971
MJ
65static
66struct mmap_mapping *mapping_create(void)
67{
68 struct mmap_mapping *mapping;
69
70 mapping = malloc(sizeof(struct mmap_mapping));
71 if (mapping != NULL) {
72 mapping->file_handle = NULL;
73 mapping->map_handle = NULL;
74 }
8f76831a 75
a555e971
MJ
76 return mapping;
77}
78
79static
80void mapping_clean(struct mmap_mapping *mapping)
81{
82 if (mapping) {
83 if (!CloseHandle(mapping->map_handle)) {
84 BT_LOGF_STR("Failed to close mmap map_handle.");
85 abort();
86 }
87 if (!CloseHandle(mapping->file_handle)) {
88 BT_LOGF_STR("Failed to close mmap file_handle.");
89 abort();
90 }
91 free(mapping);
92 mapping = NULL;
93 }
94}
95
96static
97void addr_clean(void *addr)
98{
99 /* Cleanup of handles should never fail. */
100 if (!UnmapViewOfFile(addr)) {
101 BT_LOGF_STR("Failed to unmap mmap mapping.");
102 abort();
103 }
104}
8f76831a
MJ
105
106static
107void mmap_lock(void)
108{
109 if (pthread_mutex_lock(&mmap_mutex)) {
a555e971 110 BT_LOGF_STR("Failed to acquire mmap_mutex.");
f23a034a 111 abort();
8f76831a
MJ
112 }
113}
114
115static
116void mmap_unlock(void)
117{
118 if (pthread_mutex_unlock(&mmap_mutex)) {
a555e971 119 BT_LOGF_STR("Failed to release mmap_mutex.");
f23a034a 120 abort();
8f76831a
MJ
121 }
122}
123
124/*
125 * Convert mmap memory protection flags to CreateFileMapping page protection
126 * flag and MapViewOfFile desired access flag.
127 */
128static
129DWORD map_prot_flags(int prot, DWORD *dwDesiredAccess)
130{
131 if (prot & PROT_READ) {
132 if (prot & PROT_WRITE) {
133 *dwDesiredAccess = FILE_MAP_WRITE;
134 if (prot & PROT_EXEC) {
135 return PAGE_EXECUTE_READWRITE;
136 }
137 return PAGE_READWRITE;
138 }
139 if (prot & PROT_EXEC) {
140 *dwDesiredAccess = FILE_MAP_EXECUTE;
141 return PAGE_EXECUTE_READ;
142 }
143 *dwDesiredAccess = FILE_MAP_READ;
144 return PAGE_READONLY;
145 }
146 if (prot & PROT_WRITE) {
147 *dwDesiredAccess = FILE_MAP_COPY;
148 return PAGE_WRITECOPY;
149 }
150 if (prot & PROT_EXEC) {
151 *dwDesiredAccess = FILE_MAP_EXECUTE;
152 return PAGE_EXECUTE_READ;
153 }
154
a555e971 155 /* Mapping failed. */
8f76831a
MJ
156 *dwDesiredAccess = 0;
157 return 0;
158}
159
a555e971
MJ
160BT_HIDDEN
161void *bt_mmap(void *addr, size_t length, int prot, int flags, int fd,
8f76831a
MJ
162 off_t offset)
163{
a555e971
MJ
164 struct mmap_mapping *mapping = NULL;
165 void *mapping_addr;
8f76831a
MJ
166 DWORD dwDesiredAccess;
167 DWORD flProtect;
168 HANDLE handle;
169
a555e971 170 /* Check for a valid fd. */
8f76831a
MJ
171 if (fd == -1) {
172 _set_errno(EBADF);
a555e971 173 goto error;
8f76831a
MJ
174 }
175
a555e971 176 /* We don't support this at the moment. */
8f76831a
MJ
177 if (flags == MAP_FIXED) {
178 _set_errno(ENOTSUP);
a555e971 179 goto error;
8f76831a
MJ
180 }
181
a555e971 182 /* Map mmap flags to those of the Windows API. */
8f76831a
MJ
183 flProtect = map_prot_flags(prot, &dwDesiredAccess);
184 if (flProtect == 0) {
185 _set_errno(EINVAL);
a555e971 186 goto error;
8f76831a
MJ
187 }
188
a555e971
MJ
189 /* Allocate the mapping struct. */
190 mapping = mapping_create();
191 if (!mapping) {
192 BT_LOGE_STR("Failed to allocate mmap mapping.");
193 _set_errno(ENOMEM);
194 goto error;
195 }
196
197 /* Get a handle from the fd. */
8f76831a
MJ
198 handle = (HANDLE) _get_osfhandle(fd);
199
a555e971 200 /* Duplicate the handle and store it in 'mapping.file_handle'. */
8f76831a 201 if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
a555e971 202 &mapping->file_handle, 0, FALSE,
8f76831a 203 DUPLICATE_SAME_ACCESS)) {
a555e971
MJ
204 _set_errno(ENOMEM);
205 goto error;
8f76831a
MJ
206 }
207
208 /*
209 * Create a file mapping object with a maximum size
a555e971 210 * of 'offset' + 'length'.
8f76831a 211 */
a555e971 212 mapping->map_handle = CreateFileMapping(mapping->file_handle, NULL,
8f76831a 213 flProtect, 0, offset + length, NULL);
a555e971 214 if (mapping->map_handle == 0) {
8f76831a 215 _set_errno(EACCES);
a555e971 216 goto error;
8f76831a
MJ
217 }
218
a555e971
MJ
219 /* Map the requested block starting at 'offset' for 'length' bytes. */
220 mapping_addr = MapViewOfFile(mapping->map_handle, dwDesiredAccess, 0,
8f76831a 221 offset, length);
a555e971 222 if (mapping_addr == 0) {
8f76831a 223 DWORD dwLastErr = GetLastError();
8f76831a
MJ
224 if (dwLastErr == ERROR_MAPPED_ALIGNMENT) {
225 _set_errno(EINVAL);
226 } else {
227 _set_errno(EACCES);
228 }
a555e971 229 goto error;
8f76831a
MJ
230 }
231
232 mmap_lock();
233
a555e971
MJ
234 /* If we have never done any mappings, allocate the hashtable. */
235 if (!mmap_mappings) {
236 mmap_mappings = g_hash_table_new_full(g_direct_hash,
237 g_direct_equal, (GDestroyNotify) addr_clean,
238 (GDestroyNotify) mapping_clean);
239 if (!mmap_mappings) {
240 BT_LOGE_STR("Failed to allocate mmap hashtable.");
241 _set_errno(ENOMEM);
8f76831a
MJ
242 goto error_mutex_unlock;
243 }
244 }
245
a555e971
MJ
246 /* Add the new mapping to the hashtable. */
247 if (!g_hash_table_insert(mmap_mappings, mapping_addr, mapping)) {
248 BT_LOGF_STR("Failed to insert mapping in the hashtable.");
249 abort();
8f76831a
MJ
250 }
251
8f76831a
MJ
252 mmap_unlock();
253
a555e971 254 return mapping_addr;
8f76831a
MJ
255
256error_mutex_unlock:
257 mmap_unlock();
a555e971
MJ
258error:
259 mapping_clean(mapping);
8f76831a
MJ
260 return MAP_FAILED;
261}
262
a555e971
MJ
263BT_HIDDEN
264int bt_munmap(void *addr, size_t length)
8f76831a 265{
a555e971 266 int ret = 0;
8f76831a 267
a555e971 268 mmap_lock();
8f76831a 269
a555e971
MJ
270 /* Check if the mapping exists in the hashtable. */
271 if (g_hash_table_lookup(mmap_mappings, addr) == NULL) {
8f76831a 272 _set_errno(EINVAL);
a555e971
MJ
273 ret = -1;
274 goto end;
8f76831a
MJ
275 }
276
a555e971
MJ
277 /* Remove it. */
278 if (!g_hash_table_remove(mmap_mappings, addr)) {
279 BT_LOGF_STR("Failed to remove mapping from hashtable.");
f23a034a 280 abort();
8f76831a 281 }
8f76831a 282
a555e971 283end:
8f76831a 284 mmap_unlock();
a555e971 285 return ret;
8f76831a
MJ
286}
287
288#endif
This page took 0.040882 seconds and 4 git commands to generate.