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