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
15using namespace llvm;
16using namespace sys;
17
18namespace {
19
20class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
21public:
22  MappedMemoryTest() {
23    Flags = GetParam();
24    PageSize = sys::process::get_self()->page_size();
25  }
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) {
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
120TEST_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
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
358