Commit | Line | Data |
---|---|---|
f7a2be83 MD |
1 | #ifndef _BABELTRACE_MMAP_ALIGN_H |
2 | #define _BABELTRACE_MMAP_ALIGN_H | |
3 | ||
4 | /* | |
5 | * BabelTrace mmap-align.h - mmap alignment header | |
6 | * | |
7 | * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
8 | * | |
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
10 | * of this software and associated documentation files (the "Software"), to deal | |
11 | * in the Software without restriction, including without limitation the rights | |
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
13 | * copies of the Software, and to permit persons to whom the Software is | |
14 | * furnished to do so, subject to the following conditions: | |
15 | * | |
16 | * The above copyright notice and this permission notice shall be included in | |
17 | * all copies or substantial portions of the Software. | |
c462e188 MD |
18 | * |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
25 | * SOFTWARE. | |
f7a2be83 MD |
26 | */ |
27 | ||
3d9990ac | 28 | #include <babeltrace/align-internal.h> |
f7a2be83 | 29 | #include <stdlib.h> |
544d0515 | 30 | #include <stdint.h> |
8f76831a | 31 | #include <babeltrace/compat/mman-internal.h> |
108e5a1e | 32 | #include <babeltrace/common-internal.h> |
f7a2be83 MD |
33 | |
34 | /* | |
35 | * This header implements a wrapper over mmap (mmap_align) that memory | |
36 | * maps a file region that is not necessarily multiple of the page size. | |
37 | * It returns a structure (instead of a pointer) that contains the mmap | |
38 | * pointer (page-aligned) and a pointer to the offset requested within | |
39 | * that page. Note: in the current implementation, the "addr" parameter | |
40 | * cannot be forced, so we allocate at an address chosen by the OS. | |
41 | */ | |
42 | ||
43 | struct mmap_align { | |
44 | void *page_aligned_addr; /* mmap address, aligned to floor */ | |
45 | size_t page_aligned_length; /* mmap length, containing range */ | |
46 | ||
47 | void *addr; /* virtual mmap address */ | |
48 | size_t length; /* virtual mmap length */ | |
49 | }; | |
50 | ||
8f76831a MJ |
51 | #ifdef __WIN32__ |
52 | #include <windows.h> | |
53 | ||
54 | /* | |
55 | * On windows the memory mapping offset must be aligned to the memory | |
56 | * allocator allocation granularity and not the page size. | |
57 | */ | |
58 | static inline | |
59 | off_t get_page_aligned_offset(off_t offset, size_t page_size) | |
60 | { | |
61 | SYSTEM_INFO sysinfo; | |
62 | ||
63 | GetNativeSystemInfo(&sysinfo); | |
64 | ||
65 | return ALIGN_FLOOR(offset, sysinfo.dwAllocationGranularity); | |
66 | } | |
67 | #else | |
68 | static inline | |
69 | off_t get_page_aligned_offset(off_t offset, size_t page_size) | |
70 | { | |
71 | return ALIGN_FLOOR(offset, page_size); | |
72 | } | |
73 | #endif | |
74 | ||
f7a2be83 MD |
75 | static inline |
76 | struct mmap_align *mmap_align(size_t length, int prot, | |
77 | int flags, int fd, off_t offset) | |
78 | { | |
79 | struct mmap_align *mma; | |
80 | off_t page_aligned_offset; /* mmap offset, aligned to floor */ | |
108e5a1e MJ |
81 | size_t page_size; |
82 | ||
83 | page_size = bt_common_get_page_size(); | |
f7a2be83 MD |
84 | |
85 | mma = malloc(sizeof(*mma)); | |
86 | if (!mma) | |
87 | return MAP_FAILED; | |
88 | mma->length = length; | |
8f76831a | 89 | page_aligned_offset = get_page_aligned_offset(offset, page_size); |
f7a2be83 MD |
90 | /* |
91 | * Page aligned length needs to contain the requested range. | |
92 | * E.g., for a small range that fits within a single page, we might | |
93 | * require a 2 pages page_aligned_length if the range crosses a page | |
94 | * boundary. | |
95 | */ | |
108e5a1e | 96 | mma->page_aligned_length = ALIGN(length + offset - page_aligned_offset, page_size); |
f7a2be83 MD |
97 | mma->page_aligned_addr = mmap(NULL, mma->page_aligned_length, |
98 | prot, flags, fd, page_aligned_offset); | |
8f76831a | 99 | if (mma->page_aligned_addr == MAP_FAILED) { |
f7a2be83 MD |
100 | free(mma); |
101 | return MAP_FAILED; | |
102 | } | |
544d0515 | 103 | mma->addr = ((uint8_t *) mma->page_aligned_addr) + (offset - page_aligned_offset); |
f7a2be83 MD |
104 | return mma; |
105 | } | |
106 | ||
107 | static inline | |
108 | int munmap_align(struct mmap_align *mma) | |
109 | { | |
110 | void *page_aligned_addr; | |
111 | size_t page_aligned_length; | |
112 | ||
113 | page_aligned_addr = mma->page_aligned_addr; | |
114 | page_aligned_length = mma->page_aligned_length; | |
115 | free(mma); | |
116 | return munmap(page_aligned_addr, page_aligned_length); | |
117 | } | |
118 | ||
119 | static inline | |
120 | void *mmap_align_addr(struct mmap_align *mma) | |
121 | { | |
122 | return mma->addr; | |
123 | } | |
124 | ||
125 | /* | |
126 | * Helper for special-cases, normally unused. | |
127 | */ | |
128 | static inline | |
129 | void mmap_align_set_addr(struct mmap_align *mma, void *addr) | |
130 | { | |
131 | mma->addr = addr; | |
132 | } | |
133 | ||
134 | #endif /* _BABELTRACE_MMAP_ALIGN_H */ |