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