4 * Copyright (C) 2013 JP Ikaheimonen <jp_ikaheimonen@mentor.com>
5 * 2016 Michael Jeanson <mjeanson@efficios.com>
7 * These sources are based on ftp://g.oswego.edu/pub/misc/malloc.c
8 * file by Doug Lea, released to the public domain.
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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
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
29 #define BT_LOG_TAG "COMPAT-MMAN"
40 #include <babeltrace/compat/mman-internal.h>
43 HANDLE file_handle
; /* the duplicated handle */
44 HANDLE map_handle
; /* handle returned by CreateFileMapping */
45 void *start
; /* ptr returned by MapViewOfFile */
49 * This mutex protects the array of memory mappings and its associated
50 * counters. (mmap_infos, mmap_infos_cur mmap_infos_max)
52 static pthread_mutex_t mmap_mutex
= PTHREAD_MUTEX_INITIALIZER
;
54 static int mmap_infos_cur
= 0;
55 static int mmap_infos_max
= 0;
56 static struct mmap_info
*mmap_infos
= NULL
;
58 #define NEW_MMAP_STRUCT_CNT 10
63 if (pthread_mutex_lock(&mmap_mutex
)) {
69 void mmap_unlock(void)
71 if (pthread_mutex_unlock(&mmap_mutex
)) {
77 * Convert mmap memory protection flags to CreateFileMapping page protection
78 * flag and MapViewOfFile desired access flag.
81 DWORD
map_prot_flags(int prot
, DWORD
*dwDesiredAccess
)
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
;
89 return PAGE_READWRITE
;
91 if (prot
& PROT_EXEC
) {
92 *dwDesiredAccess
= FILE_MAP_EXECUTE
;
93 return PAGE_EXECUTE_READ
;
95 *dwDesiredAccess
= FILE_MAP_READ
;
98 if (prot
& PROT_WRITE
) {
99 *dwDesiredAccess
= FILE_MAP_COPY
;
100 return PAGE_WRITECOPY
;
102 if (prot
& PROT_EXEC
) {
103 *dwDesiredAccess
= FILE_MAP_EXECUTE
;
104 return PAGE_EXECUTE_READ
;
108 *dwDesiredAccess
= 0;
112 void *mmap(void *start
, size_t length
, int prot
, int flags
, int fd
,
115 struct mmap_info mapping
;
116 DWORD dwDesiredAccess
;
120 /* Check for a valid fd */
126 /* we don't support this atm */
127 if (flags
== MAP_FIXED
) {
132 /* Map mmap flags to windows API */
133 flProtect
= map_prot_flags(prot
, &dwDesiredAccess
);
134 if (flProtect
== 0) {
139 /* Get a handle from the fd */
140 handle
= (HANDLE
) _get_osfhandle(fd
);
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
)) {
150 * Create a file mapping object with a maximum size
151 * of 'offset' + 'length'
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
)) {
163 /* Map the requested block starting at 'offset' for 'length' bytes */
164 mapping
.start
= MapViewOfFile(mapping
.map_handle
, dwDesiredAccess
, 0,
166 if (mapping
.start
== 0) {
167 DWORD dwLastErr
= GetLastError();
168 if (!CloseHandle(mapping
.map_handle
)) {
171 if (!CloseHandle(mapping
.file_handle
)) {
175 if (dwLastErr
== ERROR_MAPPED_ALIGNMENT
) {
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
) {
193 goto error_mutex_unlock
;
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
;
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
;
208 mmap_infos
= realloc_mmap_infos
;
211 /* Add the new mapping to the array */
212 memcpy(&mmap_infos
[mmap_infos_cur
], &mapping
,
213 sizeof(struct mmap_info
));
218 return mapping
.start
;
223 if (!CloseHandle(mapping
.map_handle
)) {
226 if (!CloseHandle(mapping
.file_handle
)) {
234 int munmap(void *start
, size_t length
)
238 /* Find the mapping to unmap */
239 for (i
= 0; i
< mmap_infos_cur
; i
++) {
240 if (mmap_infos
[i
].start
== start
)
244 /* Mapping was not found */
245 if (i
== mmap_infos_cur
) {
250 /* Cleanup of handles should never fail */
251 if (!UnmapViewOfFile(mmap_infos
[i
].start
)) {
254 if (!CloseHandle(mmap_infos
[i
].map_handle
)) {
257 if (!CloseHandle(mmap_infos
[i
].file_handle
)) {
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
));
270 /* If the mapping list is now empty, free it */
271 if (mmap_infos_cur
== 0) {