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  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
70TEST_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
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  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
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  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
182TEST_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
239TEST_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
264TEST_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
286TEST_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
312TEST_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
338TEST_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
352unsigned 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
361INSTANTIATE_TEST_CASE_P(AllocationTests,
362			MappedMemoryTest,
363			::testing::ValuesIn(MemoryFlags));
364
365}  // anonymous namespace
366