summaryrefslogtreecommitdiff
path: root/storage/innobase/include/rw_lock.h
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/rw_lock.h')
-rw-r--r--storage/innobase/include/rw_lock.h23
1 files changed, 20 insertions, 3 deletions
diff --git a/storage/innobase/include/rw_lock.h b/storage/innobase/include/rw_lock.h
index cd176f0b35b..ba380b77261 100644
--- a/storage/innobase/include/rw_lock.h
+++ b/storage/innobase/include/rw_lock.h
@@ -50,9 +50,22 @@ protected:
static constexpr uint32_t UPDATER= 1U << 29;
#endif /* SUX_LOCK_GENERIC */
+ /** Start waiting for an exclusive lock. */
+ void write_lock_wait_start()
+ {
+#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
+ static_assert(WRITER_WAITING == 1U << 30, "compatibility");
+ __asm__ __volatile__("lock btsl $30, %0" : "+m" (lock));
+#elif defined _MSC_VER && (defined _M_IX86 || defined _M_IX64)
+ static_assert(WRITER_WAITING == 1U << 30, "compatibility");
+ _interlockedbittestandset(reinterpret_cast<volatile long*>(&lock), 30);
+#else
+ lock.fetch_or(WRITER_WAITING, std::memory_order_relaxed);
+#endif
+ }
/** Start waiting for an exclusive lock.
@return current value of the lock word */
- uint32_t write_lock_wait_start()
+ uint32_t write_lock_wait_start_read()
{ return lock.fetch_or(WRITER_WAITING, std::memory_order_relaxed); }
/** Wait for an exclusive lock.
@param l the value of the lock word
@@ -183,8 +196,12 @@ public:
/** Release an exclusive lock */
void write_unlock()
{
- IF_DBUG_ASSERT(auto l=,)
- lock.fetch_and(~WRITER, std::memory_order_release);
+ /* Below, we use fetch_sub(WRITER) instead of fetch_and(~WRITER).
+ The reason is that on IA-32 and AMD64 it translates into the 80486
+ instruction LOCK XADD, while fetch_and() translates into a loop
+ around LOCK CMPXCHG. For other ISA either form should be fine. */
+ static_assert(WRITER == 1U << 31, "compatibility");
+ IF_DBUG_ASSERT(auto l=,) lock.fetch_sub(WRITER, std::memory_order_release);
/* the write lock must have existed */
#ifdef SUX_LOCK_GENERIC
DBUG_ASSERT((l & (WRITER | UPDATER)) == WRITER);