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::get_self()->page_size(); 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 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 70 TEST_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 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 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 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 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 178 TEST_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 231 TEST_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 256 TEST_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 278 TEST_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 304 TEST_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 330 TEST_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 344 unsigned 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 353 INSTANTIATE_TEST_CASE_P(AllocationTests, 354 MappedMemoryTest, 355 ::testing::ValuesIn(MemoryFlags)); 356 357 } // anonymous namespace 358