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:
MappedMemoryTest()22   MappedMemoryTest() {
23     Flags = GetParam();
24     PageSize = sys::Process::getPageSize();
25   }
26 
27 protected:
28   // Adds RW flags to permit testing of the resulting memory
getTestableEquivalent(unsigned RequestedFlags)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
doesOverlap(MemoryBlock M1,MemoryBlock M2)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 
TEST_P(MappedMemoryTest,AllocAndRelease)59 TEST_P(MappedMemoryTest, AllocAndRelease) {
60   std::error_code EC;
61   MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
62   EXPECT_EQ(std::error_code(), EC);
63 
64   EXPECT_NE((void*)nullptr, M1.base());
65   EXPECT_LE(sizeof(int), M1.size());
66 
67   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
68 }
69 
TEST_P(MappedMemoryTest,MultipleAllocAndRelease)70 TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
71   std::error_code EC;
72   MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
73   EXPECT_EQ(std::error_code(), EC);
74   MemoryBlock M2 = Memory::allocateMappedMemory(64, nullptr, Flags, EC);
75   EXPECT_EQ(std::error_code(), EC);
76   MemoryBlock M3 = Memory::allocateMappedMemory(32, nullptr, Flags, EC);
77   EXPECT_EQ(std::error_code(), EC);
78 
79   EXPECT_NE((void*)nullptr, M1.base());
80   EXPECT_LE(16U, M1.size());
81   EXPECT_NE((void*)nullptr, M2.base());
82   EXPECT_LE(64U, M2.size());
83   EXPECT_NE((void*)nullptr, 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, nullptr, Flags, EC);
93   EXPECT_EQ(std::error_code(), EC);
94   EXPECT_NE((void*)nullptr, M4.base());
95   EXPECT_LE(16U, M4.size());
96   EXPECT_FALSE(Memory::releaseMappedMemory(M4));
97   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
98 }
99 
TEST_P(MappedMemoryTest,BasicWrite)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   std::error_code EC;
107   MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
108   EXPECT_EQ(std::error_code(), EC);
109 
110   EXPECT_NE((void*)nullptr, 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 
TEST_P(MappedMemoryTest,MultipleWrite)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   std::error_code EC;
126   MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,
127                                                 EC);
128   EXPECT_EQ(std::error_code(), EC);
129   MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
130                                                 EC);
131   EXPECT_EQ(std::error_code(), EC);
132   MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
133                                                 EC);
134   EXPECT_EQ(std::error_code(), EC);
135 
136   EXPECT_FALSE(doesOverlap(M1, M2));
137   EXPECT_FALSE(doesOverlap(M2, M3));
138   EXPECT_FALSE(doesOverlap(M1, M3));
139 
140   EXPECT_NE((void*)nullptr, M1.base());
141   EXPECT_LE(1U * sizeof(int), M1.size());
142   EXPECT_NE((void*)nullptr, M2.base());
143   EXPECT_LE(8U * sizeof(int), M2.size());
144   EXPECT_NE((void*)nullptr, M3.base());
145   EXPECT_LE(4U * sizeof(int), M3.size());
146 
147   int *x = (int*)M1.base();
148   *x = 1;
149 
150   int *y = (int*)M2.base();
151   for (int i = 0; i < 8; i++) {
152     y[i] = i;
153   }
154 
155   int *z = (int*)M3.base();
156   *z = 42;
157 
158   EXPECT_EQ(1, *x);
159   EXPECT_EQ(7, y[7]);
160   EXPECT_EQ(42, *z);
161 
162   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
163   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
164 
165   MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), nullptr,
166                                                 Flags, EC);
167   EXPECT_EQ(std::error_code(), EC);
168   EXPECT_NE((void*)nullptr, M4.base());
169   EXPECT_LE(64U * sizeof(int), M4.size());
170   x = (int*)M4.base();
171   *x = 4;
172   EXPECT_EQ(4, *x);
173   EXPECT_FALSE(Memory::releaseMappedMemory(M4));
174 
175   // Verify that M2 remains unaffected by other activity
176   for (int i = 0; i < 8; i++) {
177     EXPECT_EQ(i, y[i]);
178   }
179   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
180 }
181 
TEST_P(MappedMemoryTest,EnabledWrite)182 TEST_P(MappedMemoryTest, EnabledWrite) {
183   std::error_code EC;
184   MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags,
185                                                 EC);
186   EXPECT_EQ(std::error_code(), EC);
187   MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
188                                                 EC);
189   EXPECT_EQ(std::error_code(), EC);
190   MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
191                                                 EC);
192   EXPECT_EQ(std::error_code(), EC);
193 
194   EXPECT_NE((void*)nullptr, M1.base());
195   EXPECT_LE(2U * sizeof(int), M1.size());
196   EXPECT_NE((void*)nullptr, M2.base());
197   EXPECT_LE(8U * sizeof(int), M2.size());
198   EXPECT_NE((void*)nullptr, M3.base());
199   EXPECT_LE(4U * sizeof(int), M3.size());
200 
201   EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
202   EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
203   EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
204 
205   EXPECT_FALSE(doesOverlap(M1, M2));
206   EXPECT_FALSE(doesOverlap(M2, M3));
207   EXPECT_FALSE(doesOverlap(M1, M3));
208 
209   int *x = (int*)M1.base();
210   *x = 1;
211   int *y = (int*)M2.base();
212   for (unsigned int i = 0; i < 8; i++) {
213     y[i] = i;
214   }
215   int *z = (int*)M3.base();
216   *z = 42;
217 
218   EXPECT_EQ(1, *x);
219   EXPECT_EQ(7, y[7]);
220   EXPECT_EQ(42, *z);
221 
222   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
223   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
224   EXPECT_EQ(6, y[6]);
225 
226   MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
227   EXPECT_EQ(std::error_code(), EC);
228   EXPECT_NE((void*)nullptr, M4.base());
229   EXPECT_LE(16U, M4.size());
230   EXPECT_EQ(std::error_code(),
231             Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
232   x = (int*)M4.base();
233   *x = 4;
234   EXPECT_EQ(4, *x);
235   EXPECT_FALSE(Memory::releaseMappedMemory(M4));
236   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
237 }
238 
TEST_P(MappedMemoryTest,SuccessiveNear)239 TEST_P(MappedMemoryTest, SuccessiveNear) {
240   std::error_code EC;
241   MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
242   EXPECT_EQ(std::error_code(), EC);
243   MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
244   EXPECT_EQ(std::error_code(), EC);
245   MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
246   EXPECT_EQ(std::error_code(), EC);
247 
248   EXPECT_NE((void*)nullptr, M1.base());
249   EXPECT_LE(16U, M1.size());
250   EXPECT_NE((void*)nullptr, M2.base());
251   EXPECT_LE(64U, M2.size());
252   EXPECT_NE((void*)nullptr, M3.base());
253   EXPECT_LE(32U, M3.size());
254 
255   EXPECT_FALSE(doesOverlap(M1, M2));
256   EXPECT_FALSE(doesOverlap(M2, M3));
257   EXPECT_FALSE(doesOverlap(M1, M3));
258 
259   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
260   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
261   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
262 }
263 
TEST_P(MappedMemoryTest,DuplicateNear)264 TEST_P(MappedMemoryTest, DuplicateNear) {
265   std::error_code EC;
266   MemoryBlock Near((void*)(3*PageSize), 16);
267   MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
268   EXPECT_EQ(std::error_code(), EC);
269   MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
270   EXPECT_EQ(std::error_code(), EC);
271   MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
272   EXPECT_EQ(std::error_code(), EC);
273 
274   EXPECT_NE((void*)nullptr, M1.base());
275   EXPECT_LE(16U, M1.size());
276   EXPECT_NE((void*)nullptr, M2.base());
277   EXPECT_LE(64U, M2.size());
278   EXPECT_NE((void*)nullptr, M3.base());
279   EXPECT_LE(32U, M3.size());
280 
281   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
282   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
283   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
284 }
285 
TEST_P(MappedMemoryTest,ZeroNear)286 TEST_P(MappedMemoryTest, ZeroNear) {
287   std::error_code EC;
288   MemoryBlock Near(nullptr, 0);
289   MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
290   EXPECT_EQ(std::error_code(), EC);
291   MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
292   EXPECT_EQ(std::error_code(), EC);
293   MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
294   EXPECT_EQ(std::error_code(), EC);
295 
296   EXPECT_NE((void*)nullptr, M1.base());
297   EXPECT_LE(16U, M1.size());
298   EXPECT_NE((void*)nullptr, M2.base());
299   EXPECT_LE(64U, M2.size());
300   EXPECT_NE((void*)nullptr, M3.base());
301   EXPECT_LE(32U, M3.size());
302 
303   EXPECT_FALSE(doesOverlap(M1, M2));
304   EXPECT_FALSE(doesOverlap(M2, M3));
305   EXPECT_FALSE(doesOverlap(M1, M3));
306 
307   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
308   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
309   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
310 }
311 
TEST_P(MappedMemoryTest,ZeroSizeNear)312 TEST_P(MappedMemoryTest, ZeroSizeNear) {
313   std::error_code EC;
314   MemoryBlock Near((void*)(4*PageSize), 0);
315   MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
316   EXPECT_EQ(std::error_code(), EC);
317   MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
318   EXPECT_EQ(std::error_code(), EC);
319   MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
320   EXPECT_EQ(std::error_code(), EC);
321 
322   EXPECT_NE((void*)nullptr, M1.base());
323   EXPECT_LE(16U, M1.size());
324   EXPECT_NE((void*)nullptr, M2.base());
325   EXPECT_LE(64U, M2.size());
326   EXPECT_NE((void*)nullptr, M3.base());
327   EXPECT_LE(32U, M3.size());
328 
329   EXPECT_FALSE(doesOverlap(M1, M2));
330   EXPECT_FALSE(doesOverlap(M2, M3));
331   EXPECT_FALSE(doesOverlap(M1, M3));
332 
333   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
334   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
335   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
336 }
337 
TEST_P(MappedMemoryTest,UnalignedNear)338 TEST_P(MappedMemoryTest, UnalignedNear) {
339   std::error_code EC;
340   MemoryBlock Near((void*)(2*PageSize+5), 0);
341   MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
342   EXPECT_EQ(std::error_code(), EC);
343 
344   EXPECT_NE((void*)nullptr, M1.base());
345   EXPECT_LE(sizeof(int), M1.size());
346 
347   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
348 }
349 
350 // Note that Memory::MF_WRITE is not supported exclusively across
351 // operating systems and architectures and can imply MF_READ|MF_WRITE
352 unsigned MemoryFlags[] = {
353 			   Memory::MF_READ,
354 			   Memory::MF_WRITE,
355 			   Memory::MF_READ|Memory::MF_WRITE,
356 			   Memory::MF_EXEC,
357 			   Memory::MF_READ|Memory::MF_EXEC,
358 			   Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
359 			 };
360 
361 INSTANTIATE_TEST_CASE_P(AllocationTests,
362 			MappedMemoryTest,
363 			::testing::ValuesIn(MemoryFlags));
364 
365 }  // anonymous namespace
366