[llvm-commits] [compiler-rt] r170097 - in /compiler-rt/trunk/lib/sanitizer_common: sanitizer_allocator.h tests/sanitizer_allocator_test.cc

Kostya Serebryany kcc at google.com
Wed Dec 12 21:05:11 PST 2012


Author: kcc
Date: Wed Dec 12 23:05:11 2012
New Revision: 170097

URL: http://llvm.org/viewvc/llvm-project?rev=170097&view=rev
Log:
[sanitizer] change the way SizeClassAllocator64 allocated memory from the system: instead of one huge mmap(NORESERVE) it does one huge mprotect and then does small on-demand mmaps. This allows us to call OnMap callbacks which are required to poison newly allocated memory in asan

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator_test.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h?rev=170097&r1=170096&r2=170097&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h Wed Dec 12 23:05:11 2012
@@ -132,6 +132,8 @@
 // Space: a portion of address space of kSpaceSize bytes starting at
 // a fixed address (kSpaceBeg). Both constants are powers of two and
 // kSpaceBeg is kSpaceSize-aligned.
+// At the beginning the entire space is mprotect-ed, then small parts of it
+// are mapped on demand.
 //
 // Region: a part of Space dedicated to a single size class.
 // There are kNumClasses Regions of equal size.
@@ -147,8 +149,8 @@
 class SizeClassAllocator64 {
  public:
   void Init() {
-    CHECK_EQ(kSpaceBeg, reinterpret_cast<uptr>(MmapFixedNoReserve(
-             kSpaceBeg, kSpaceSize)));
+    CHECK_EQ(kSpaceBeg,
+             reinterpret_cast<uptr>(Mprotect(kSpaceBeg, kSpaceSize)));
     MapWithCallback(kSpaceEnd, AdditionalSize());
   }
 
@@ -253,15 +255,20 @@
   // Populate the free list with at most this number of bytes at once
   // or with one element if its size is greater.
   static const uptr kPopulateSize = 1 << 18;
+  // Call mmap for user memory with this size.
+  static const uptr kUserMapSize = 1 << 22;
+  // Call mmap for metadata memory with this size.
+  static const uptr kMetaMapSize = 1 << 20;
 
   struct RegionInfo {
     SpinMutex mutex;
     AllocatorFreeList free_list;
     uptr allocated_user;  // Bytes allocated for user memory.
     uptr allocated_meta;  // Bytes allocated for metadata.
-    char padding[kCacheLineSize - 3 * sizeof(uptr) - sizeof(AllocatorFreeList)];
+    uptr mapped_user;  // Bytes mapped for user memory.
+    uptr mapped_meta;  // Bytes mapped for metadata.
   };
-  COMPILER_CHECK(sizeof(RegionInfo) == kCacheLineSize);
+  COMPILER_CHECK(sizeof(RegionInfo) >= kCacheLineSize);
 
   static uptr AdditionalSize() {
     uptr PageSize = GetPageSizeCached();
@@ -290,6 +297,12 @@
     uptr beg_idx = region->allocated_user;
     uptr end_idx = beg_idx + kPopulateSize;
     uptr region_beg = kSpaceBeg + kRegionSize * class_id;
+    if (end_idx > region->mapped_user) {
+      // Do the mmap for the user memory.
+      CHECK_GT(region->mapped_user + kUserMapSize, end_idx);
+      MapWithCallback(region_beg + region->mapped_user, kUserMapSize);
+      region->mapped_user += kUserMapSize;
+    }
     uptr idx = beg_idx;
     uptr i = 0;
     do {  // do-while loop because we need to put at least one item.
@@ -300,6 +313,13 @@
     } while (idx < end_idx);
     region->allocated_user += idx - beg_idx;
     region->allocated_meta += i * kMetadataSize;
+    if (region->allocated_meta > region->mapped_meta) {
+      // Do the mmap for the metadata.
+      CHECK_GT(region->mapped_meta + kMetaMapSize, region->allocated_meta);
+      MapWithCallback(region_beg + kRegionSize -
+                      region->mapped_meta - kMetaMapSize, kMetaMapSize);
+      region->mapped_meta += kMetaMapSize;
+    }
     if (region->allocated_user + region->allocated_meta > kRegionSize) {
       Printf("Out of memory. Dying.\n");
       Printf("The process has exhausted %zuMB for size class %zu.\n",

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator_test.cc?rev=170097&r1=170096&r2=170097&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator_test.cc Wed Dec 12 23:05:11 2012
@@ -197,6 +197,8 @@
   Allocator64WithCallBack *a = new Allocator64WithCallBack;
   a->Init();
   EXPECT_EQ(TestMapUnmapCallback::map_count, 1);  // Allocator state.
+  a->Allocate(100, 1);
+  EXPECT_EQ(TestMapUnmapCallback::map_count, 3);  // State + alloc + metadata.
   a->TestOnlyUnmap();
   EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);  // The whole thing.
   delete a;





More information about the llvm-commits mailing list