summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-10-02 09:25:40 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-10-02 09:25:40 +0300
commitec619a1def69c175d9fa07201b2567c3478e9408 (patch)
tree562c8edace1f7d587df5340f0dd7048b3e0f2388
parenta49e394399859b23ba609d0058b498cfa876cac4 (diff)
downloadmariadb-git-ec619a1def69c175d9fa07201b2567c3478e9408.tar.gz
MDEV-26467 fixup: Prefer fetch_add() to fetch_or() on IA-32 and AMD64
-rw-r--r--storage/innobase/include/srw_lock.h10
1 files changed, 10 insertions, 0 deletions
diff --git a/storage/innobase/include/srw_lock.h b/storage/innobase/include/srw_lock.h
index 3d0d82b81df..9e2eac15df0 100644
--- a/storage/innobase/include/srw_lock.h
+++ b/storage/innobase/include/srw_lock.h
@@ -226,8 +226,18 @@ public:
void wr_lock()
{
writer.wr_lock();
+#if defined __i386__||defined __x86_64__||defined _M_IX86||defined _M_IX64
+ /* On IA-32 and AMD64, this type of fetch_or() can only be implemented
+ as a loop around LOCK CMPXCHG. In this particular case, setting the
+ most significant bit using fetch_add() is equivalent, and is
+ translated into a simple LOCK XADD. */
+ static_assert(WRITER == 1U << 31, "compatibility");
+ if (uint32_t lk= readers.fetch_add(WRITER, std::memory_order_acquire))
+ wr_wait(lk);
+#else
if (uint32_t lk= readers.fetch_or(WRITER, std::memory_order_acquire))
wr_wait(lk);
+#endif
}
void u_wr_upgrade()