1 //===- 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"
12 #include "gtest/gtest.h"
13 #include <cstdlib>
14 
15 using namespace llvm;
16 using namespace sys;
17 
18 namespace {
19 
20 class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
21 public:
22   MappedMemoryTest() {
23     Flags = GetParam();
24     PageSize = sys::process::get_self()->page_size();
25   }
26 
27 protected:
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 
59 TEST_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 
70 TEST_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 
100 TEST_P(MappedMemoryTest, BasicWrite) {
101   // This test applies only to readable and writeable combinations
102   if (Flags &&
103       !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
104     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 
120 TEST_P(MappedMemoryTest, MultipleWrite) {
121   // This test applies only to readable and writeable combinations
122   if (Flags &&
123       !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
124     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 
178 TEST_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 
231 TEST_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 
256 TEST_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 
278 TEST_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 
304 TEST_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 
330 TEST_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
344 unsigned 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 
353 INSTANTIATE_TEST_CASE_P(AllocationTests,
354 			MappedMemoryTest,
355 			::testing::ValuesIn(MemoryFlags));
356 
357 }  // anonymous namespace
358