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