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