Home | History | Annotate | Download | only in Support
      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