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 using std::error_code; 18 19 namespace { 20 21 class MappedMemoryTest : public ::testing::TestWithParam<unsigned> { 22 public: 23 MappedMemoryTest() { 24 Flags = GetParam(); 25 PageSize = sys::process::get_self()->page_size(); 26 } 27 28 protected: 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 60 TEST_P(MappedMemoryTest, AllocAndRelease) { 61 error_code EC; 62 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC); 63 EXPECT_EQ(error_code(), EC); 64 65 EXPECT_NE((void*)nullptr, M1.base()); 66 EXPECT_LE(sizeof(int), M1.size()); 67 68 EXPECT_FALSE(Memory::releaseMappedMemory(M1)); 69 } 70 71 TEST_P(MappedMemoryTest, MultipleAllocAndRelease) { 72 error_code EC; 73 MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); 74 EXPECT_EQ(error_code(), EC); 75 MemoryBlock M2 = Memory::allocateMappedMemory(64, nullptr, Flags, EC); 76 EXPECT_EQ(error_code(), EC); 77 MemoryBlock M3 = Memory::allocateMappedMemory(32, nullptr, Flags, EC); 78 EXPECT_EQ(error_code(), EC); 79 80 EXPECT_NE((void*)nullptr, M1.base()); 81 EXPECT_LE(16U, M1.size()); 82 EXPECT_NE((void*)nullptr, M2.base()); 83 EXPECT_LE(64U, M2.size()); 84 EXPECT_NE((void*)nullptr, 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, nullptr, Flags, EC); 94 EXPECT_EQ(error_code(), EC); 95 EXPECT_NE((void*)nullptr, M4.base()); 96 EXPECT_LE(16U, M4.size()); 97 EXPECT_FALSE(Memory::releaseMappedMemory(M4)); 98 EXPECT_FALSE(Memory::releaseMappedMemory(M2)); 99 } 100 101 TEST_P(MappedMemoryTest, BasicWrite) { 102 // This test applies only to readable and writeable combinations 103 if (Flags && 104 !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE))) 105 return; 106 107 error_code EC; 108 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC); 109 EXPECT_EQ(error_code(), EC); 110 111 EXPECT_NE((void*)nullptr, M1.base()); 112 EXPECT_LE(sizeof(int), M1.size()); 113 114 int *a = (int*)M1.base(); 115 *a = 1; 116 EXPECT_EQ(1, *a); 117 118 EXPECT_FALSE(Memory::releaseMappedMemory(M1)); 119 } 120 121 TEST_P(MappedMemoryTest, MultipleWrite) { 122 // This test applies only to readable and writeable combinations 123 if (Flags && 124 !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE))) 125 return; 126 error_code EC; 127 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags, 128 EC); 129 EXPECT_EQ(error_code(), EC); 130 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags, 131 EC); 132 EXPECT_EQ(error_code(), EC); 133 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags, 134 EC); 135 EXPECT_EQ(error_code(), EC); 136 137 EXPECT_FALSE(doesOverlap(M1, M2)); 138 EXPECT_FALSE(doesOverlap(M2, M3)); 139 EXPECT_FALSE(doesOverlap(M1, M3)); 140 141 EXPECT_NE((void*)nullptr, M1.base()); 142 EXPECT_LE(1U * sizeof(int), M1.size()); 143 EXPECT_NE((void*)nullptr, M2.base()); 144 EXPECT_LE(8U * sizeof(int), M2.size()); 145 EXPECT_NE((void*)nullptr, M3.base()); 146 EXPECT_LE(4U * sizeof(int), M3.size()); 147 148 int *x = (int*)M1.base(); 149 *x = 1; 150 151 int *y = (int*)M2.base(); 152 for (int i = 0; i < 8; i++) { 153 y[i] = i; 154 } 155 156 int *z = (int*)M3.base(); 157 *z = 42; 158 159 EXPECT_EQ(1, *x); 160 EXPECT_EQ(7, y[7]); 161 EXPECT_EQ(42, *z); 162 163 EXPECT_FALSE(Memory::releaseMappedMemory(M1)); 164 EXPECT_FALSE(Memory::releaseMappedMemory(M3)); 165 166 MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), nullptr, 167 Flags, EC); 168 EXPECT_EQ(error_code(), EC); 169 EXPECT_NE((void*)nullptr, M4.base()); 170 EXPECT_LE(64U * sizeof(int), M4.size()); 171 x = (int*)M4.base(); 172 *x = 4; 173 EXPECT_EQ(4, *x); 174 EXPECT_FALSE(Memory::releaseMappedMemory(M4)); 175 176 // Verify that M2 remains unaffected by other activity 177 for (int i = 0; i < 8; i++) { 178 EXPECT_EQ(i, y[i]); 179 } 180 EXPECT_FALSE(Memory::releaseMappedMemory(M2)); 181 } 182 183 TEST_P(MappedMemoryTest, EnabledWrite) { 184 error_code EC; 185 MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags, 186 EC); 187 EXPECT_EQ(error_code(), EC); 188 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags, 189 EC); 190 EXPECT_EQ(error_code(), EC); 191 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags, 192 EC); 193 EXPECT_EQ(error_code(), EC); 194 195 EXPECT_NE((void*)nullptr, M1.base()); 196 EXPECT_LE(2U * sizeof(int), M1.size()); 197 EXPECT_NE((void*)nullptr, M2.base()); 198 EXPECT_LE(8U * sizeof(int), M2.size()); 199 EXPECT_NE((void*)nullptr, M3.base()); 200 EXPECT_LE(4U * sizeof(int), M3.size()); 201 202 EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags))); 203 EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags))); 204 EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags))); 205 206 EXPECT_FALSE(doesOverlap(M1, M2)); 207 EXPECT_FALSE(doesOverlap(M2, M3)); 208 EXPECT_FALSE(doesOverlap(M1, M3)); 209 210 int *x = (int*)M1.base(); 211 *x = 1; 212 int *y = (int*)M2.base(); 213 for (unsigned int i = 0; i < 8; i++) { 214 y[i] = i; 215 } 216 int *z = (int*)M3.base(); 217 *z = 42; 218 219 EXPECT_EQ(1, *x); 220 EXPECT_EQ(7, y[7]); 221 EXPECT_EQ(42, *z); 222 223 EXPECT_FALSE(Memory::releaseMappedMemory(M1)); 224 EXPECT_FALSE(Memory::releaseMappedMemory(M3)); 225 EXPECT_EQ(6, y[6]); 226 227 MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); 228 EXPECT_EQ(error_code(), EC); 229 EXPECT_NE((void*)nullptr, M4.base()); 230 EXPECT_LE(16U, M4.size()); 231 EXPECT_EQ(error_code(), 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 239 TEST_P(MappedMemoryTest, SuccessiveNear) { 240 error_code EC; 241 MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); 242 EXPECT_EQ(error_code(), EC); 243 MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC); 244 EXPECT_EQ(error_code(), EC); 245 MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC); 246 EXPECT_EQ(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 264 TEST_P(MappedMemoryTest, DuplicateNear) { 265 error_code EC; 266 MemoryBlock Near((void*)(3*PageSize), 16); 267 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); 268 EXPECT_EQ(error_code(), EC); 269 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); 270 EXPECT_EQ(error_code(), EC); 271 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); 272 EXPECT_EQ(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 286 TEST_P(MappedMemoryTest, ZeroNear) { 287 error_code EC; 288 MemoryBlock Near(nullptr, 0); 289 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); 290 EXPECT_EQ(error_code(), EC); 291 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); 292 EXPECT_EQ(error_code(), EC); 293 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); 294 EXPECT_EQ(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 312 TEST_P(MappedMemoryTest, ZeroSizeNear) { 313 error_code EC; 314 MemoryBlock Near((void*)(4*PageSize), 0); 315 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); 316 EXPECT_EQ(error_code(), EC); 317 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); 318 EXPECT_EQ(error_code(), EC); 319 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); 320 EXPECT_EQ(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 338 TEST_P(MappedMemoryTest, UnalignedNear) { 339 error_code EC; 340 MemoryBlock Near((void*)(2*PageSize+5), 0); 341 MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC); 342 EXPECT_EQ(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