blob: fae67a8dd2569a495b8aef11fc348b4849ac1ef2 [file] [log] [blame]
Jakub Staszakde7c8532012-11-14 20:18:34 +00001//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/Memory.h"
11#include "llvm/Support/Process.h"
Jakub Staszakde7c8532012-11-14 20:18:34 +000012#include "gtest/gtest.h"
13#include <cstdlib>
14
15using namespace llvm;
16using namespace sys;
17
18namespace {
19
20class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
21public:
22 MappedMemoryTest() {
23 Flags = GetParam();
Chandler Carruthf5867ab2012-12-31 23:31:56 +000024 PageSize = sys::process::get_self()->page_size();
Jakub Staszakde7c8532012-11-14 20:18:34 +000025 }
26
27protected:
28 // Adds RW flags to permit testing of the resulting memory
29 unsigned getTestableEquivalent(unsigned RequestedFlags) {
30 switch (RequestedFlags) {
31 case Memory::MF_READ:
32 case Memory::MF_WRITE:
33 case Memory::MF_READ|Memory::MF_WRITE:
34 return Memory::MF_READ|Memory::MF_WRITE;
35 case Memory::MF_READ|Memory::MF_EXEC:
36 case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
37 case Memory::MF_EXEC:
38 return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
39 }
40 // Default in case values are added to the enum, as required by some compilers
41 return Memory::MF_READ|Memory::MF_WRITE;
42 }
43
44 // Returns true if the memory blocks overlap
45 bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {
46 if (M1.base() == M2.base())
47 return true;
48
49 if (M1.base() > M2.base())
50 return (unsigned char *)M2.base() + M2.size() > M1.base();
51
52 return (unsigned char *)M1.base() + M1.size() > M2.base();
53 }
54
55 unsigned Flags;
56 size_t PageSize;
57};
58
59TEST_P(MappedMemoryTest, AllocAndRelease) {
60 error_code EC;
61 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
62 EXPECT_EQ(error_code::success(), EC);
63
64 EXPECT_NE((void*)0, M1.base());
65 EXPECT_LE(sizeof(int), M1.size());
66
67 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
68}
69
70TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
71 error_code EC;
72 MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);
73 EXPECT_EQ(error_code::success(), EC);
74 MemoryBlock M2 = Memory::allocateMappedMemory(64, 0, Flags, EC);
75 EXPECT_EQ(error_code::success(), EC);
76 MemoryBlock M3 = Memory::allocateMappedMemory(32, 0, Flags, EC);
77 EXPECT_EQ(error_code::success(), EC);
78
79 EXPECT_NE((void*)0, M1.base());
80 EXPECT_LE(16U, M1.size());
81 EXPECT_NE((void*)0, M2.base());
82 EXPECT_LE(64U, M2.size());
83 EXPECT_NE((void*)0, M3.base());
84 EXPECT_LE(32U, M3.size());
85
86 EXPECT_FALSE(doesOverlap(M1, M2));
87 EXPECT_FALSE(doesOverlap(M2, M3));
88 EXPECT_FALSE(doesOverlap(M1, M3));
89
90 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
91 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
92 MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);
93 EXPECT_EQ(error_code::success(), EC);
94 EXPECT_NE((void*)0, M4.base());
95 EXPECT_LE(16U, M4.size());
96 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
97 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
98}
99
100TEST_P(MappedMemoryTest, BasicWrite) {
Akira Hatanakac4c14a72012-12-05 22:43:07 +0000101 // This test applies only to readable and writeable combinations
102 if (Flags &&
103 !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
Jakub Staszakde7c8532012-11-14 20:18:34 +0000104 return;
105
106 error_code EC;
107 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
108 EXPECT_EQ(error_code::success(), EC);
109
110 EXPECT_NE((void*)0, M1.base());
111 EXPECT_LE(sizeof(int), M1.size());
112
113 int *a = (int*)M1.base();
114 *a = 1;
115 EXPECT_EQ(1, *a);
116
117 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
118}
119
120TEST_P(MappedMemoryTest, MultipleWrite) {
Akira Hatanakac4c14a72012-12-05 22:43:07 +0000121 // This test applies only to readable and writeable combinations
122 if (Flags &&
123 !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
Jakub Staszakde7c8532012-11-14 20:18:34 +0000124 return;
125 error_code EC;
126 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
127 EXPECT_EQ(error_code::success(), EC);
128 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);
129 EXPECT_EQ(error_code::success(), EC);
130 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);
131 EXPECT_EQ(error_code::success(), EC);
132
133 EXPECT_FALSE(doesOverlap(M1, M2));
134 EXPECT_FALSE(doesOverlap(M2, M3));
135 EXPECT_FALSE(doesOverlap(M1, M3));
136
137 EXPECT_NE((void*)0, M1.base());
138 EXPECT_LE(1U * sizeof(int), M1.size());
139 EXPECT_NE((void*)0, M2.base());
140 EXPECT_LE(8U * sizeof(int), M2.size());
141 EXPECT_NE((void*)0, M3.base());
142 EXPECT_LE(4U * sizeof(int), M3.size());
143
144 int *x = (int*)M1.base();
145 *x = 1;
146
147 int *y = (int*)M2.base();
148 for (int i = 0; i < 8; i++) {
149 y[i] = i;
150 }
151
152 int *z = (int*)M3.base();
153 *z = 42;
154
155 EXPECT_EQ(1, *x);
156 EXPECT_EQ(7, y[7]);
157 EXPECT_EQ(42, *z);
158
159 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
160 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
161
162 MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), 0, Flags, EC);
163 EXPECT_EQ(error_code::success(), EC);
164 EXPECT_NE((void*)0, M4.base());
165 EXPECT_LE(64U * sizeof(int), M4.size());
166 x = (int*)M4.base();
167 *x = 4;
168 EXPECT_EQ(4, *x);
169 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
170
171 // Verify that M2 remains unaffected by other activity
172 for (int i = 0; i < 8; i++) {
173 EXPECT_EQ(i, y[i]);
174 }
175 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
176}
177
178TEST_P(MappedMemoryTest, EnabledWrite) {
179 error_code EC;
180 MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), 0, Flags, EC);
181 EXPECT_EQ(error_code::success(), EC);
182 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);
183 EXPECT_EQ(error_code::success(), EC);
184 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);
185 EXPECT_EQ(error_code::success(), EC);
186
187 EXPECT_NE((void*)0, M1.base());
188 EXPECT_LE(2U * sizeof(int), M1.size());
189 EXPECT_NE((void*)0, M2.base());
190 EXPECT_LE(8U * sizeof(int), M2.size());
191 EXPECT_NE((void*)0, M3.base());
192 EXPECT_LE(4U * sizeof(int), M3.size());
193
194 EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
195 EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
196 EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
197
198 EXPECT_FALSE(doesOverlap(M1, M2));
199 EXPECT_FALSE(doesOverlap(M2, M3));
200 EXPECT_FALSE(doesOverlap(M1, M3));
201
202 int *x = (int*)M1.base();
203 *x = 1;
204 int *y = (int*)M2.base();
205 for (unsigned int i = 0; i < 8; i++) {
206 y[i] = i;
207 }
208 int *z = (int*)M3.base();
209 *z = 42;
210
211 EXPECT_EQ(1, *x);
212 EXPECT_EQ(7, y[7]);
213 EXPECT_EQ(42, *z);
214
215 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
216 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
217 EXPECT_EQ(6, y[6]);
218
219 MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);
220 EXPECT_EQ(error_code::success(), EC);
221 EXPECT_NE((void*)0, M4.base());
222 EXPECT_LE(16U, M4.size());
223 EXPECT_EQ(error_code::success(), Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
224 x = (int*)M4.base();
225 *x = 4;
226 EXPECT_EQ(4, *x);
227 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
228 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
229}
230
231TEST_P(MappedMemoryTest, SuccessiveNear) {
232 error_code EC;
233 MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);
234 EXPECT_EQ(error_code::success(), EC);
235 MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
236 EXPECT_EQ(error_code::success(), EC);
237 MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
238 EXPECT_EQ(error_code::success(), EC);
239
240 EXPECT_NE((void*)0, M1.base());
241 EXPECT_LE(16U, M1.size());
242 EXPECT_NE((void*)0, M2.base());
243 EXPECT_LE(64U, M2.size());
244 EXPECT_NE((void*)0, M3.base());
245 EXPECT_LE(32U, M3.size());
246
247 EXPECT_FALSE(doesOverlap(M1, M2));
248 EXPECT_FALSE(doesOverlap(M2, M3));
249 EXPECT_FALSE(doesOverlap(M1, M3));
250
251 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
252 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
253 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
254}
255
256TEST_P(MappedMemoryTest, DuplicateNear) {
257 error_code EC;
258 MemoryBlock Near((void*)(3*PageSize), 16);
259 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
260 EXPECT_EQ(error_code::success(), EC);
261 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
262 EXPECT_EQ(error_code::success(), EC);
263 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
264 EXPECT_EQ(error_code::success(), EC);
265
266 EXPECT_NE((void*)0, M1.base());
267 EXPECT_LE(16U, M1.size());
268 EXPECT_NE((void*)0, M2.base());
269 EXPECT_LE(64U, M2.size());
270 EXPECT_NE((void*)0, M3.base());
271 EXPECT_LE(32U, M3.size());
272
273 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
274 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
275 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
276}
277
278TEST_P(MappedMemoryTest, ZeroNear) {
279 error_code EC;
280 MemoryBlock Near(0, 0);
281 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
282 EXPECT_EQ(error_code::success(), EC);
283 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
284 EXPECT_EQ(error_code::success(), EC);
285 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
286 EXPECT_EQ(error_code::success(), EC);
287
288 EXPECT_NE((void*)0, M1.base());
289 EXPECT_LE(16U, M1.size());
290 EXPECT_NE((void*)0, M2.base());
291 EXPECT_LE(64U, M2.size());
292 EXPECT_NE((void*)0, M3.base());
293 EXPECT_LE(32U, M3.size());
294
295 EXPECT_FALSE(doesOverlap(M1, M2));
296 EXPECT_FALSE(doesOverlap(M2, M3));
297 EXPECT_FALSE(doesOverlap(M1, M3));
298
299 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
300 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
301 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
302}
303
304TEST_P(MappedMemoryTest, ZeroSizeNear) {
305 error_code EC;
306 MemoryBlock Near((void*)(4*PageSize), 0);
307 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
308 EXPECT_EQ(error_code::success(), EC);
309 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
310 EXPECT_EQ(error_code::success(), EC);
311 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
312 EXPECT_EQ(error_code::success(), EC);
313
314 EXPECT_NE((void*)0, M1.base());
315 EXPECT_LE(16U, M1.size());
316 EXPECT_NE((void*)0, M2.base());
317 EXPECT_LE(64U, M2.size());
318 EXPECT_NE((void*)0, M3.base());
319 EXPECT_LE(32U, M3.size());
320
321 EXPECT_FALSE(doesOverlap(M1, M2));
322 EXPECT_FALSE(doesOverlap(M2, M3));
323 EXPECT_FALSE(doesOverlap(M1, M3));
324
325 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
326 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
327 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
328}
329
330TEST_P(MappedMemoryTest, UnalignedNear) {
331 error_code EC;
332 MemoryBlock Near((void*)(2*PageSize+5), 0);
333 MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
334 EXPECT_EQ(error_code::success(), EC);
335
336 EXPECT_NE((void*)0, M1.base());
337 EXPECT_LE(sizeof(int), M1.size());
338
339 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
340}
341
342// Note that Memory::MF_WRITE is not supported exclusively across
343// operating systems and architectures and can imply MF_READ|MF_WRITE
344unsigned MemoryFlags[] = {
345 Memory::MF_READ,
346 Memory::MF_WRITE,
347 Memory::MF_READ|Memory::MF_WRITE,
348 Memory::MF_EXEC,
349 Memory::MF_READ|Memory::MF_EXEC,
350 Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
351 };
352
353INSTANTIATE_TEST_CASE_P(AllocationTests,
354 MappedMemoryTest,
355 ::testing::ValuesIn(MemoryFlags));
356
357} // anonymous namespace