summaryrefslogtreecommitdiff
path: root/storage/innobase/include/srw_lock.h
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-12-03 10:42:18 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-12-03 15:17:16 +0200
commitd46b42489a62124a672e7abea1d393f519979828 (patch)
treeabe2ae52595e64723d4940a3753fec6574138f29 /storage/innobase/include/srw_lock.h
parent3872e585f3ed566c91abd131cb7000871107de64 (diff)
downloadmariadb-git-d46b42489a62124a672e7abea1d393f519979828.tar.gz
MDEV-24142 preparation: Add srw_mutex and srw_lock::u_lock()
The PERFORMANCE_SCHEMA insists on distinguishing read-update-write locks from read-write locks, so we must add template<bool support_u_lock> in rd_lock() and wr_lock() operations. rd_lock::read_trylock(): Add template<bool prioritize_updater=false> which is used by the srw_lock_low::read_lock() loop. As long as an UPDATE lock has already been granted to some thread, we will grant subsequent READ lock requests even if a waiting WRITE lock request exists. This will be necessary to be compatible with existing usage pattern of InnoDB rw_lock_t where the holder of SX-latch (which we will rename to UPDATE latch) may acquire an additional S-latch on the same object. For normal read-write locks without update operations this should make no difference at all, because the rw_lock::UPDATER flag would never be set.
Diffstat (limited to 'storage/innobase/include/srw_lock.h')
-rw-r--r--storage/innobase/include/srw_lock.h63
1 files changed, 58 insertions, 5 deletions
diff --git a/storage/innobase/include/srw_lock.h b/storage/innobase/include/srw_lock.h
index 34105636e2e..c876204daab 100644
--- a/storage/innobase/include/srw_lock.h
+++ b/storage/innobase/include/srw_lock.h
@@ -25,6 +25,22 @@ this program; if not, write to the Free Software Foundation, Inc.,
# define SRW_LOCK_DUMMY /* Use dummy implementation for debugging purposes */
#endif
+#ifdef SRW_LOCK_DUMMY
+/** An exclusive-only variant of srw_lock */
+class srw_mutex
+{
+ pthread_mutex_t lock;
+public:
+ void init() { pthread_mutex_init(&lock, nullptr); }
+ void destroy() { pthread_mutex_destroy(&lock); }
+ void wr_lock() { pthread_mutex_lock(&lock); }
+ void wr_unlock() { pthread_mutex_unlock(&lock); }
+ bool wr_lock_try() { return !pthread_mutex_trylock(&lock); }
+};
+#else
+# define srw_mutex srw_lock_low
+#endif
+
#include "rw_lock.h"
/** Slim reader-writer lock with no recursion */
@@ -43,8 +59,12 @@ class srw_lock_low final : private rw_lock
/** Wait for a read lock.
@param l lock word from a failed read_trylock() */
void read_lock(uint32_t l);
- /** Wait for a write lock after a failed write_trylock() */
- void write_lock();
+ /** Wait for an update lock.
+ @param l lock word from a failed update_trylock() */
+ void update_lock(uint32_t l);
+ /** Wait for a write lock after a failed write_trylock() or upgrade_trylock()
+ @param holding_u whether we already hold u_lock() */
+ void write_lock(bool holding_u);
/** Wait for signal
@param l lock word from a failed acquisition */
inline void writer_wait(uint32_t l);
@@ -65,9 +85,15 @@ public:
#endif
bool rd_lock_try() { uint32_t l; return read_trylock(l); }
bool wr_lock_try() { return write_trylock(); }
+ template<bool support_u_lock= false>
void rd_lock() { uint32_t l; if (!read_trylock(l)) read_lock(l); }
- void wr_lock() { if (!write_trylock()) write_lock(); }
+ void u_lock() { uint32_t l; if (!update_trylock(l)) update_lock(l); }
+ bool u_lock_try() { uint32_t l; return update_trylock(l); }
+ void u_wr_upgrade() { if (!upgrade_trylock()) write_lock(true); }
+ template<bool support_u_lock= false>
+ void wr_lock() { if (!write_trylock()) write_lock(false); }
void rd_unlock();
+ void u_unlock();
void wr_unlock();
};
@@ -87,8 +113,12 @@ class srw_lock
srw_lock_low lock;
PSI_rwlock *pfs_psi;
+ template<bool support_u_lock>
ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line);
+ template<bool support_u_lock>
ATTRIBUTE_NOINLINE void psi_wr_lock(const char *file, unsigned line);
+ ATTRIBUTE_NOINLINE void psi_u_lock(const char *file, unsigned line);
+ ATTRIBUTE_NOINLINE void psi_u_wr_upgrade(const char *file, unsigned line);
public:
void init(mysql_pfs_key_t key)
{
@@ -104,10 +134,11 @@ public:
}
lock.destroy();
}
+ template<bool support_u_lock= false>
void rd_lock(const char *file, unsigned line)
{
if (psi_likely(pfs_psi != nullptr))
- psi_rd_lock(file, line);
+ psi_rd_lock<support_u_lock>(file, line);
else
lock.rd_lock();
}
@@ -117,10 +148,24 @@ public:
PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
lock.rd_unlock();
}
+ void u_lock(const char *file, unsigned line)
+ {
+ if (psi_likely(pfs_psi != nullptr))
+ psi_u_lock(file, line);
+ else
+ lock.u_lock();
+ }
+ void u_unlock()
+ {
+ if (pfs_psi)
+ PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
+ lock.u_unlock();
+ }
+ template<bool support_u_lock= false>
void wr_lock(const char *file, unsigned line)
{
if (psi_likely(pfs_psi != nullptr))
- psi_wr_lock(file, line);
+ psi_wr_lock<support_u_lock>(file, line);
else
lock.wr_lock();
}
@@ -130,7 +175,15 @@ public:
PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
lock.wr_unlock();
}
+ void u_wr_upgrade(const char *file, unsigned line)
+ {
+ if (psi_likely(pfs_psi != nullptr))
+ psi_u_wr_upgrade(file, line);
+ else
+ lock.u_wr_upgrade();
+ }
bool rd_lock_try() { return lock.rd_lock_try(); }
+ bool u_lock_try() { return lock.u_lock_try(); }
bool wr_lock_try() { return lock.wr_lock_try(); }
};
#endif