[tsan] add metadata to the new tsan allocator
llvm-svn: 159002
This commit is contained in:
parent
052f60d384
commit
278ccdacdc
|
|
@ -96,10 +96,12 @@ class SizeClassAllocator64 {
|
|||
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 @@ class SizeClassAllocator64 {
|
|||
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 @@ class SizeClassAllocator64 {
|
|||
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 @@ class SizeClassAllocator64 {
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -47,13 +47,13 @@ TEST(SanitizerCommon, DefaultSizeClassMap) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ TEST(SanitizerCommon, SizeClassAllocator64) {
|
|||
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 @@ TEST(SanitizerCommon, SizeClassAllocator64) {
|
|||
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue