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> |
f7a2be83 MD |
31 | #include <sys/mman.h> |
32 | ||
33 | /* | |
34 | * This header implements a wrapper over mmap (mmap_align) that memory | |
35 | * maps a file region that is not necessarily multiple of the page size. | |
36 | * It returns a structure (instead of a pointer) that contains the mmap | |
37 | * pointer (page-aligned) and a pointer to the offset requested within | |
38 | * that page. Note: in the current implementation, the "addr" parameter | |
39 | * cannot be forced, so we allocate at an address chosen by the OS. | |
40 | */ | |
41 | ||
42 | struct mmap_align { | |
43 | void *page_aligned_addr; /* mmap address, aligned to floor */ | |
44 | size_t page_aligned_length; /* mmap length, containing range */ | |
45 | ||
46 | void *addr; /* virtual mmap address */ | |
47 | size_t length; /* virtual mmap length */ | |
48 | }; | |
49 | ||
50 | static inline | |
51 | struct mmap_align *mmap_align(size_t length, int prot, | |
52 | int flags, int fd, off_t offset) | |
53 | { | |
54 | struct mmap_align *mma; | |
55 | off_t page_aligned_offset; /* mmap offset, aligned to floor */ | |
56 | ||
57 | mma = malloc(sizeof(*mma)); | |
58 | if (!mma) | |
59 | return MAP_FAILED; | |
60 | mma->length = length; | |
61 | page_aligned_offset = ALIGN_FLOOR(offset, PAGE_SIZE); | |
62 | /* | |
63 | * Page aligned length needs to contain the requested range. | |
64 | * E.g., for a small range that fits within a single page, we might | |
65 | * require a 2 pages page_aligned_length if the range crosses a page | |
66 | * boundary. | |
67 | */ | |
68 | mma->page_aligned_length = ALIGN(length + offset - page_aligned_offset, PAGE_SIZE); | |
69 | mma->page_aligned_addr = mmap(NULL, mma->page_aligned_length, | |
70 | prot, flags, fd, page_aligned_offset); | |
71 | if (mma->page_aligned_addr == (void *) -1UL) { | |
72 | free(mma); | |
73 | return MAP_FAILED; | |
74 | } | |
544d0515 | 75 | mma->addr = ((uint8_t *) mma->page_aligned_addr) + (offset - page_aligned_offset); |
f7a2be83 MD |
76 | return mma; |
77 | } | |
78 | ||
79 | static inline | |
80 | int munmap_align(struct mmap_align *mma) | |
81 | { | |
82 | void *page_aligned_addr; | |
83 | size_t page_aligned_length; | |
84 | ||
85 | page_aligned_addr = mma->page_aligned_addr; | |
86 | page_aligned_length = mma->page_aligned_length; | |
87 | free(mma); | |
88 | return munmap(page_aligned_addr, page_aligned_length); | |
89 | } | |
90 | ||
91 | static inline | |
92 | void *mmap_align_addr(struct mmap_align *mma) | |
93 | { | |
94 | return mma->addr; | |
95 | } | |
96 | ||
97 | /* | |
98 | * Helper for special-cases, normally unused. | |
99 | */ | |
100 | static inline | |
101 | void mmap_align_set_addr(struct mmap_align *mma, void *addr) | |
102 | { | |
103 | mma->addr = addr; | |
104 | } | |
105 | ||
106 | #endif /* _BABELTRACE_MMAP_ALIGN_H */ |