From 1dd2a8784fc734a4ca68f312a646ba19b37a6ed7 Mon Sep 17 00:00:00 2001 From: Henrique Bucher Date: Tue, 14 Apr 2026 15:35:06 -0300 Subject: [PATCH] Use memory_order_acquire for spinlock, not acq_rel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The standard spinlock pattern is acquire on lock, release on unlock. The release semantics on the lock path (from acq_rel) are unnecessary — when acquiring a lock, you need to ensure subsequent operations stay after the acquisition (acquire), but there is nothing to release at that point. This restores the original behavior from the initial commit (e57758e, Jan 2014), which correctly used memory_order_acquire. The change to acq_rel was introduced in 8530b8a (Dec 2016). On x86 this is a no-op (test_and_set compiles to XCHG which is a full barrier regardless). On ARM and POWER, acq_rel generates an extra barrier instruction that acquire does not, making this a measurable improvement on those architectures. --- libcuckoo/cuckoohash_map.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcuckoo/cuckoohash_map.hh b/libcuckoo/cuckoohash_map.hh index 04f63f1..2824b67 100644 --- a/libcuckoo/cuckoohash_map.hh +++ b/libcuckoo/cuckoohash_map.hh @@ -833,14 +833,14 @@ private: } void lock() noexcept { - while (lock_.test_and_set(std::memory_order_acq_rel)) + while (lock_.test_and_set(std::memory_order_acquire)) ; } void unlock() noexcept { lock_.clear(std::memory_order_release); } bool try_lock() noexcept { - return !lock_.test_and_set(std::memory_order_acq_rel); + return !lock_.test_and_set(std::memory_order_acquire); } counter_type &elem_counter() noexcept { return elem_counter_; }