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