Skip to content

Commit 7411810

Browse files
author
Kostya Kortchinsky
committed
[sanitizer] Align & pad the allocator structures to the cacheline size
Summary: Both `SizeClassInfo` structures for the 32-bit primary & `RegionInfo` structures for the 64-bit primary can be used by different threads, and as such they should be aligned & padded to the cacheline size to avoid false sharing. The former was padded but the array was not aligned, the latter was not padded but we lucked up as the size of the structure was 192 bytes, and aligned by the properties of `mmap`. I plan on adding a couple of fields to the `RegionInfo`, and some highly threaded tests pointed out that without proper padding & alignment, performance was getting a hit - and it is going away with proper padding. This patch makes sure that we are properly padded & aligned for both. I used a template to avoid padding if the size is already a multiple of the cacheline size. There might be a better way to do this, I am open to suggestions. Reviewers: alekseyshl, dvyukov Reviewed By: alekseyshl Subscribers: kubamracek, delcypher, #sanitizers, llvm-commits Differential Revision: https://reviews.llvm.org/D44261 llvm-svn=327145
1 parent 8942fd1 commit 7411810

File tree

3 files changed

+14
-13
lines changed

3 files changed

+14
-13
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,12 @@ class SizeClassAllocator32 {
266266
static const uptr kRegionSize = 1 << kRegionSizeLog;
267267
static const uptr kNumPossibleRegions = kSpaceSize / kRegionSize;
268268

269-
struct SizeClassInfo {
269+
struct ALIGNED(kCacheLineSize) SizeClassInfo {
270270
SpinMutex mutex;
271271
IntrusiveList<TransferBatch> free_list;
272272
u32 rand_state;
273-
char padding[kCacheLineSize - 2 * sizeof(uptr) -
274-
sizeof(IntrusiveList<TransferBatch>)];
275273
};
276-
COMPILER_CHECK(sizeof(SizeClassInfo) == kCacheLineSize);
274+
COMPILER_CHECK(sizeof(SizeClassInfo) % kCacheLineSize == 0);
277275

278276
uptr ComputeRegionId(uptr mem) {
279277
const uptr res = mem >> kRegionSizeLog;
@@ -299,7 +297,7 @@ class SizeClassAllocator32 {
299297
}
300298

301299
SizeClassInfo *GetSizeClassInfo(uptr class_id) {
302-
CHECK_LT(class_id, kNumClasses);
300+
DCHECK_LT(class_id, kNumClasses);
303301
return &size_class_info_array[class_id];
304302
}
305303

compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class SizeClassAllocator64 {
8080
}
8181
SetReleaseToOSIntervalMs(release_to_os_interval_ms);
8282
MapWithCallbackOrDie(SpaceEnd(), AdditionalSize());
83+
// Check that the RegionInfo array is aligned on the CacheLine size.
84+
DCHECK_EQ(SpaceEnd() & (kCacheLineSize - 1), 0);
8385
}
8486

8587
s32 ReleaseToOSIntervalMs() const {
@@ -302,7 +304,7 @@ class SizeClassAllocator64 {
302304

303305
static uptr AdditionalSize() {
304306
return RoundUpTo(sizeof(RegionInfo) * kNumClassesRounded,
305-
GetPageSizeCached());
307+
GetPageSizeCached());
306308
}
307309

308310
typedef SizeClassMap SizeClassMapT;
@@ -584,7 +586,7 @@ class SizeClassAllocator64 {
584586
u64 last_released_bytes;
585587
};
586588

587-
struct RegionInfo {
589+
struct ALIGNED(kCacheLineSize) RegionInfo {
588590
BlockingMutex mutex;
589591
uptr num_freed_chunks; // Number of elements in the freearray.
590592
uptr mapped_free_array; // Bytes mapped for freearray.
@@ -597,12 +599,11 @@ class SizeClassAllocator64 {
597599
Stats stats;
598600
ReleaseToOsInfo rtoi;
599601
};
600-
COMPILER_CHECK(sizeof(RegionInfo) >= kCacheLineSize);
602+
COMPILER_CHECK(sizeof(RegionInfo) % kCacheLineSize == 0);
601603

602604
RegionInfo *GetRegionInfo(uptr class_id) const {
603-
CHECK_LT(class_id, kNumClasses);
604-
RegionInfo *regions =
605-
reinterpret_cast<RegionInfo *>(SpaceBeg() + kSpaceSize);
605+
DCHECK_LT(class_id, kNumClasses);
606+
RegionInfo *regions = reinterpret_cast<RegionInfo *>(SpaceEnd());
606607
return &regions[class_id];
607608
}
608609

compiler-rt/lib/sanitizer_common/sanitizer_common.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ const uptr kWordSize = SANITIZER_WORDSIZE / 8;
4040
const uptr kWordSizeInBits = 8 * kWordSize;
4141

4242
#if defined(__powerpc__) || defined(__powerpc64__)
43-
const uptr kCacheLineSize = 128;
43+
constexpr uptr kCacheLineSize = 128;
4444
#else
45-
const uptr kCacheLineSize = 64;
45+
constexpr uptr kCacheLineSize = 64;
4646
#endif
47+
// Check that the CacheLine size is a power-of-two.
48+
COMPILER_CHECK((kCacheLineSize & (kCacheLineSize - 1)) == 0);
4749

4850
const uptr kMaxPathLength = 4096;
4951

0 commit comments

Comments
 (0)