Skip to content

Commit

Permalink
[folly] Use allocateOverAligned to allocate over-aligned ConcurrentHa…
Browse files Browse the repository at this point in the history
…shMap nodes

Summary:
ConcurrentHashMap uses alignment to ensure that there is sufficient
paddint to avoid false sharing, but doesn't ensure that the alignment
condition is actually met.  This causes problems under UBSAN.

Test Plan:
* existing unit tests
* no UBSAN failures
  • Loading branch information
nithinv13 authored and nbronson committed May 26, 2023
1 parent 984accc commit 884ba04
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions folly/concurrency/ConcurrentHashMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ class ConcurrentHashMap {
using EnableHeterogeneousFind = std::enable_if_t<
detail::EligibleForHeterogeneousFind<KeyType, HashFn, KeyEqual, K>::value,
T>;
using SegAlloc = typename std::allocator_traits<Allocator>::template rebind_alloc<SegmentT>;

float load_factor_ = SegmentT::kDefaultLoadFactor;

Expand Down Expand Up @@ -235,7 +236,7 @@ class ConcurrentHashMap {
auto seg = segments_[i].load(std::memory_order_relaxed);
if (seg) {
seg->~SegmentT();
Allocator().deallocate((uint8_t*)seg, sizeof(SegmentT));
deallocateOverAligned(SegAlloc(), seg, 1);
}
segments_[i].store(
o.segments_[i].load(std::memory_order_relaxed),
Expand Down Expand Up @@ -263,7 +264,7 @@ class ConcurrentHashMap {
auto seg = segments_[i].load(std::memory_order_relaxed);
if (seg) {
seg->~SegmentT();
Allocator().deallocate((uint8_t*)seg, sizeof(SegmentT));
deallocateOverAligned(SegAlloc(), seg, 1);
}
}
cohort_shutdown_cleanup();
Expand Down Expand Up @@ -727,13 +728,13 @@ class ConcurrentHashMap {
SegmentT* seg = segments_[i].load(std::memory_order_acquire);
if (!seg) {
auto b = ensureCohort();
SegmentT* newseg = (SegmentT*)Allocator().allocate(sizeof(SegmentT));
SegmentT* newseg = allocateOverAligned(SegAlloc(), 1);
newseg = new (newseg)
SegmentT(size_ >> ShardBits, load_factor_, max_size_ >> ShardBits, b);
if (!segments_[i].compare_exchange_strong(seg, newseg)) {
// seg is updated with new value, delete ours.
newseg->~SegmentT();
Allocator().deallocate((uint8_t*)newseg, sizeof(SegmentT));
deallocateOverAligned(SegAlloc(), newseg, 1);
} else {
seg = newseg;
updateBeginAndEndSegments(i);
Expand Down

0 comments on commit 884ba04

Please sign in to comment.