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