[llvm-commits] [compiler-rt] r159002 - in /compiler-rt/trunk/lib/sanitizer_common: sanitizer_allocator64.h tests/sanitizer_allocator64_test.cc

Kostya Serebryany kcc at google.com
Fri Jun 22 09:13:29 PDT 2012


Author: kcc
Date: Fri Jun 22 11:13:28 2012
New Revision: 159002

URL: http://llvm.org/viewvc/llvm-project?rev=159002&view=rev
Log:
[tsan] add metadata to the new tsan allocator

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator64.h
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator64.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator64.h?rev=159002&r1=159001&r2=159002&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator64.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator64.h Fri Jun 22 11:13:28 2012
@@ -96,10 +96,12 @@
     CHECK_EQ(AllocBeg(), reinterpret_cast<uptr>(MmapFixedNoReserve(
              AllocBeg(), AllocSize())));
   }
+  NOINLINE
   void *Allocate(uptr size) {
     CHECK_LE(size, SizeClassMap::kMaxSize);
     return AllocateBySizeClass(SizeClassMap::ClassID(size));
   }
+  NOINLINE
   void Deallocate(void *p) {
     DeallocateBySizeClass(p, GetSizeClass(p));
   }
@@ -110,6 +112,13 @@
     return (reinterpret_cast<uptr>(p) / kRegionSize) % kNumClasses;
   }
 
+  uptr GetMetaData(void *p) {
+    uptr class_id = GetSizeClass(p);
+    uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), class_id);
+    return kSpaceBeg + (kRegionSize * (class_id + 1)) -
+        (1 + chunk_idx) * kMetadataSize;
+  }
+
   uptr TotalMemoryUsedIncludingFreeLists() {
     uptr res = 0;
     for (uptr i = 0; i < kNumClasses; i++)
@@ -125,6 +134,7 @@
   static const uptr kNumClasses = 256;  // Power of two <= 256
   COMPILER_CHECK(kNumClasses <= SizeClassMap::kNumClasses);
   static const uptr kRegionSize = kSpaceSize / kNumClasses;
+  COMPILER_CHECK((kRegionSize >> 32) > 0);  // kRegionSize must be >= 2^32.
   // 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;
@@ -163,6 +173,14 @@
     return res;
   }
 
+  uptr GetChunkIdx(uptr chunk, uptr class_id) {
+    u32 offset = chunk % kRegionSize;
+    // Here we divide by a non-constant. This is costly.
+    // We require that kRegionSize is at least 2^32 so that offset is 32-bit.
+    // We save 2x by using 32-bit div, but may need to use a 256-way switch.
+    return offset / (u32)SizeClassMap::Size(class_id);
+  }
+
   LifoListNode *PopulateFreeList(uptr class_id, RegionInfo *region) {
     uptr size = SizeClassMap::Size(class_id);
     uptr beg_idx = region->allocated;

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc?rev=159002&r1=159001&r2=159002&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc Fri Jun 22 11:13:28 2012
@@ -47,13 +47,13 @@
   }
 }
 
+static const uptr kAllocatorSpace = 0x600000000000ULL;
+static const uptr kAllocatorSize = 0x10000000000;  // 1T.
+
 TEST(SanitizerCommon, SizeClassAllocator64) {
-  const uptr space_beg  = 0x600000000000ULL;
-  const uptr space_size = 0x10000000000;  // 1T
-  const uptr metadata_size = 16;
   typedef DefaultSizeClassMap SCMap;
-  typedef SizeClassAllocator64<space_beg, space_size,
-                               metadata_size, SCMap> Allocator;
+  typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize,
+                               16, SCMap> Allocator;
 
   Allocator a;
   a.Init();
@@ -76,11 +76,18 @@
         CHECK(a.PointerIsMine(x));
         uptr class_id = a.GetSizeClass(x);
         CHECK_EQ(class_id, SCMap::ClassID(size));
+        uptr *metadata = reinterpret_cast<uptr*>(a.GetMetaData(x));
+        metadata[0] = reinterpret_cast<uptr>(x) + 1;
+        metadata[1] = 0xABCD;
       }
     }
     // Deallocate all.
     for (uptr i = 0; i < allocated.size(); i++) {
-      a.Deallocate(allocated[i]);
+      void *x = allocated[i];
+      uptr *metadata = reinterpret_cast<uptr*>(a.GetMetaData(x));
+      CHECK_EQ(metadata[0], reinterpret_cast<uptr>(x) + 1);
+      CHECK_EQ(metadata[1], 0xABCD);
+      a.Deallocate(x);
     }
     allocated.clear();
     uptr total_allocated = a.TotalMemoryUsedIncludingFreeLists();
@@ -91,3 +98,30 @@
 
   a.TestOnlyUnmap();
 }
+
+
+TEST(SanitizerCommon, SizeClassAllocator64MetadataStress) {
+  typedef DefaultSizeClassMap SCMap;
+  typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize,
+          16, SCMap> Allocator;
+  Allocator a;
+  a.Init();
+  static volatile uptr sink;
+
+  const uptr kNumAllocs = 10000;
+  void *allocated[kNumAllocs];
+  for (uptr i = 0; i < kNumAllocs; i++) {
+    uptr size = (i % 4096) + 1;
+    void *x = a.Allocate(size);
+    allocated[i] = x;
+  }
+  // Get Metadata kNumAllocs^2 times.
+  for (uptr i = 0; i < kNumAllocs * kNumAllocs; i++) {
+    sink = a.GetMetaData(allocated[i % kNumAllocs]);
+  }
+  for (uptr i = 0; i < kNumAllocs; i++) {
+    a.Deallocate(allocated[i]);
+  }
+
+  a.TestOnlyUnmap();
+}





More information about the llvm-commits mailing list