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: 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 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 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 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 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 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 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 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 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 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 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 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