Skip to content

Commit 43d3dad

Browse files
committed
MDEV-24142/MDEV-24167 fixup: Split ssux_lock and srw_lock
This conceptually reverts commit 1fdc161 and reintroduces an option for srw_lock to wrap a native implementation. The srw_lock and srw_lock_low differ from ssux_lock and ssux_lock_low in that Slim SUX locks support three modes (Shared, Update, eXclusive) while Slim RW locks support only two (Read, Write). On Microsoft Windows, the srw_lock will be implemented by SRWLOCK. On Linux and OpenBSD, it will be implemented by rw_lock and the futex system call, just like earlier. On other systems or if SRW_LOCK_DUMMY is defined on anything else than Microsoft Windows, rw_lock_t will be used. ssux_lock_low::read_lock(), ssux_lock_low::update_lock(): Correct the SRW_LOCK_DUMMY implementation to prevent hangs. The intention of commit 1fdc161 seems to have been do ... while loops, but the 'do' keyword was missing. This total breakage was missed in commit 260161f which did reduce the probability of the hangs. ssux_lock_low::u_unlock(): In the SRW_LOCK_DUMMY implementation (based on a mutex and two condition variables), always invoke writer_wake() in order to ensure that a waiting update_lock() will be woken up. ssux_lock_low::writer_wait(), ssux_lock_low::readers_wait(): In the SRW_LOCK_DUMMY implementation, keep waiting for the signal until the lock word has changed. The "while" had been changed to "if" in order to avoid hangs.
1 parent 1c66021 commit 43d3dad

File tree

3 files changed

+205
-78
lines changed

3 files changed

+205
-78
lines changed

storage/innobase/include/srw_lock.h

Lines changed: 99 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,15 @@ class srw_mutex
4343

4444
#include "rw_lock.h"
4545

46-
/** Slim reader-writer lock with no recursion */
47-
class srw_lock_low final : private rw_lock
46+
/** Slim shared-update-exclusive lock with no recursion */
47+
class ssux_lock_low final : private rw_lock
4848
{
4949
#ifdef UNIV_PFS_RWLOCK
50+
friend class ssux_lock;
51+
# if defined SRW_LOCK_DUMMY || defined _WIN32
52+
# else
5053
friend class srw_lock;
54+
# endif
5155
#endif
5256
#ifdef SRW_LOCK_DUMMY
5357
pthread_mutex_t mutex;
@@ -85,14 +89,10 @@ class srw_lock_low final : private rw_lock
8589
#endif
8690
bool rd_lock_try() { uint32_t l; return read_trylock(l); }
8791
bool wr_lock_try() { return write_trylock(); }
88-
/** @tparam support_u_lock dummy parameter for UNIV_PFS_RWLOCK */
89-
template<bool support_u_lock= false>
9092
void rd_lock() { uint32_t l; if (!read_trylock(l)) read_lock(l); }
9193
void u_lock() { uint32_t l; if (!update_trylock(l)) update_lock(l); }
9294
bool u_lock_try() { uint32_t l; return update_trylock(l); }
9395
void u_wr_upgrade() { if (!upgrade_trylock()) write_lock(true); }
94-
/** @tparam support_u_lock dummy parameter for UNIV_PFS_RWLOCK */
95-
template<bool support_u_lock= false>
9696
void wr_lock() { if (!write_trylock()) write_lock(false); }
9797
void rd_unlock();
9898
void u_unlock();
@@ -101,25 +101,58 @@ class srw_lock_low final : private rw_lock
101101
bool is_waiting() const { return value() & WRITER_WAITING; }
102102
};
103103

104+
#if defined SRW_LOCK_DUMMY || defined _WIN32
105+
/** Slim read-write lock */
106+
class srw_lock_low
107+
{
108+
# ifdef UNIV_PFS_RWLOCK
109+
friend class srw_lock;
110+
# endif
111+
# ifdef _WIN32
112+
SRWLOCK lock;
113+
public:
114+
void init() {}
115+
void destroy() {}
116+
void rd_lock() { AcquireSRWLockShared(&lock); }
117+
bool rd_lock_try() { return TryAcquireSRWLockShared(&lock); }
118+
void rd_unlock() { ReleaseSRWLockShared(&lock); }
119+
void wr_lock() { AcquireSRWLockExclusive(&lock); }
120+
bool wr_lock_try() { return TryAcquireSRWLockExclusive(&lock); }
121+
void wr_unlock() { ReleaseSRWLockExclusive(&lock); }
122+
# else
123+
rw_lock_t lock;
124+
void init() { my_rwlock_init(&lock, nullptr); }
125+
void destroy() { rwlock_destroy(&lock); }
126+
void rd_lock() { rw_rdlock(&lock); }
127+
bool rd_lock_try() { return rw_tryrdlock(&lock); }
128+
void rd_unlock() { rw_unlock(&lock); }
129+
void wr_lock() { rw_wrlock(&lock); }
130+
bool wr_lock_try() { return rw_trywrlock(&lock); }
131+
void wr_unlock() { rw_unlock(&lock); }
132+
# endif
133+
};
134+
#else
135+
typedef ssux_lock_low srw_lock_low;
136+
#endif
137+
104138
#ifndef UNIV_PFS_RWLOCK
105139
# define SRW_LOCK_INIT(key) init()
106140
# define SRW_LOCK_ARGS(file, line) /* nothing */
107141
# define SRW_LOCK_CALL /* nothing */
108142
typedef srw_lock_low srw_lock;
143+
typedef ssux_lock_low ssux_lock;
109144
#else
110145
# define SRW_LOCK_INIT(key) init(key)
111146
# define SRW_LOCK_ARGS(file, line) file, line
112147
# define SRW_LOCK_CALL __FILE__, __LINE__
113148

114-
/** Slim reader-writer lock with PERFORMANCE_SCHEMA instrumentation */
115-
class srw_lock
149+
/** Slim shared-update-exclusive lock with PERFORMANCE_SCHEMA instrumentation */
150+
class ssux_lock
116151
{
117152
PSI_rwlock *pfs_psi;
118-
srw_lock_low lock;
153+
ssux_lock_low lock;
119154

120-
template<bool support_u_lock>
121155
ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line);
122-
template<bool support_u_lock>
123156
ATTRIBUTE_NOINLINE void psi_wr_lock(const char *file, unsigned line);
124157
ATTRIBUTE_NOINLINE void psi_u_lock(const char *file, unsigned line);
125158
ATTRIBUTE_NOINLINE void psi_u_wr_upgrade(const char *file, unsigned line);
@@ -138,11 +171,10 @@ class srw_lock
138171
}
139172
lock.destroy();
140173
}
141-
template<bool support_u_lock= false>
142174
void rd_lock(const char *file, unsigned line)
143175
{
144176
if (psi_likely(pfs_psi != nullptr))
145-
psi_rd_lock<support_u_lock>(file, line);
177+
psi_rd_lock(file, line);
146178
else
147179
lock.rd_lock();
148180
}
@@ -165,11 +197,10 @@ class srw_lock
165197
PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
166198
lock.u_unlock();
167199
}
168-
template<bool support_u_lock= false>
169200
void wr_lock(const char *file, unsigned line)
170201
{
171202
if (psi_likely(pfs_psi != nullptr))
172-
psi_wr_lock<support_u_lock>(file, line);
203+
psi_wr_lock(file, line);
173204
else
174205
lock.wr_lock();
175206
}
@@ -191,4 +222,57 @@ class srw_lock
191222
bool wr_lock_try() { return lock.wr_lock_try(); }
192223
bool is_waiting() const { return lock.is_waiting(); }
193224
};
225+
226+
/** Slim reader-writer lock with PERFORMANCE_SCHEMA instrumentation */
227+
class srw_lock
228+
{
229+
PSI_rwlock *pfs_psi;
230+
srw_lock_low lock;
231+
232+
ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line);
233+
ATTRIBUTE_NOINLINE void psi_wr_lock(const char *file, unsigned line);
234+
public:
235+
void init(mysql_pfs_key_t key)
236+
{
237+
pfs_psi= PSI_RWLOCK_CALL(init_rwlock)(key, this);
238+
lock.init();
239+
}
240+
void destroy()
241+
{
242+
if (psi_likely(pfs_psi != nullptr))
243+
{
244+
PSI_RWLOCK_CALL(destroy_rwlock)(pfs_psi);
245+
pfs_psi= nullptr;
246+
}
247+
lock.destroy();
248+
}
249+
void rd_lock(const char *file, unsigned line)
250+
{
251+
if (psi_likely(pfs_psi != nullptr))
252+
psi_rd_lock(file, line);
253+
else
254+
lock.rd_lock();
255+
}
256+
void rd_unlock()
257+
{
258+
if (psi_likely(pfs_psi != nullptr))
259+
PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
260+
lock.rd_unlock();
261+
}
262+
void wr_lock(const char *file, unsigned line)
263+
{
264+
if (psi_likely(pfs_psi != nullptr))
265+
psi_wr_lock(file, line);
266+
else
267+
lock.wr_lock();
268+
}
269+
void wr_unlock()
270+
{
271+
if (psi_likely(pfs_psi != nullptr))
272+
PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
273+
lock.wr_unlock();
274+
}
275+
bool rd_lock_try() { return lock.rd_lock_try(); }
276+
bool wr_lock_try() { return lock.wr_lock_try(); }
277+
};
194278
#endif

storage/innobase/include/sux_lock.h

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
2727
/** A "fat" rw-lock that supports
2828
S (shared), U (update, or shared-exclusive), and X (exclusive) modes
2929
as well as recursive U and X latch acquisition
30-
@tparam srw srw_lock_low or srw_lock */
30+
@tparam srw ssux_lock_low or ssux_lock */
3131
template<typename srw>
3232
class sux_lock final
3333
{
@@ -259,19 +259,19 @@ class sux_lock final
259259
};
260260

261261
/** needed for dict_index_t::clone() */
262-
template<> inline void sux_lock<srw_lock>::operator=(const sux_lock&)
262+
template<> inline void sux_lock<ssux_lock>::operator=(const sux_lock&)
263263
{
264264
memset((void*) this, 0, sizeof *this);
265265
}
266266

267-
typedef sux_lock<srw_lock_low> block_lock;
267+
typedef sux_lock<ssux_lock_low> block_lock;
268268

269269
#ifndef UNIV_PFS_RWLOCK
270270
typedef block_lock index_lock;
271271
#else
272-
typedef sux_lock<srw_lock> index_lock;
272+
typedef sux_lock<ssux_lock> index_lock;
273273

274-
template<> inline void sux_lock<srw_lock_low>::init()
274+
template<> inline void sux_lock<ssux_lock_low>::init()
275275
{
276276
lock.init();
277277
ut_ad(!writer.load(std::memory_order_relaxed));
@@ -281,16 +281,16 @@ template<> inline void sux_lock<srw_lock_low>::init()
281281
}
282282

283283
template<>
284-
inline void sux_lock<srw_lock>::s_lock(const char *file, unsigned line)
284+
inline void sux_lock<ssux_lock>::s_lock(const char *file, unsigned line)
285285
{
286286
ut_ad(!have_x());
287287
ut_ad(!have_s());
288-
lock.template rd_lock<true>(file, line);
288+
lock.rd_lock(file, line);
289289
ut_d(s_lock_register());
290290
}
291291

292292
template<>
293-
inline void sux_lock<srw_lock>::u_lock(const char *file, unsigned line)
293+
inline void sux_lock<ssux_lock>::u_lock(const char *file, unsigned line)
294294
{
295295
os_thread_id_t id= os_thread_get_curr_id();
296296
if (writer.load(std::memory_order_relaxed) == id)
@@ -305,22 +305,22 @@ inline void sux_lock<srw_lock>::u_lock(const char *file, unsigned line)
305305
}
306306

307307
template<>
308-
inline void sux_lock<srw_lock>::x_lock(const char *file, unsigned line)
308+
inline void sux_lock<ssux_lock>::x_lock(const char *file, unsigned line)
309309
{
310310
os_thread_id_t id= os_thread_get_curr_id();
311311
if (writer.load(std::memory_order_relaxed) == id)
312312
writer_recurse<false>();
313313
else
314314
{
315-
lock.template wr_lock<true>(file, line);
315+
lock.wr_lock(file, line);
316316
ut_ad(!recursive);
317317
recursive= RECURSIVE_X;
318318
set_first_owner(id);
319319
}
320320
}
321321

322322
template<>
323-
inline void sux_lock<srw_lock>::u_x_upgrade(const char *file, unsigned line)
323+
inline void sux_lock<ssux_lock>::u_x_upgrade(const char *file, unsigned line)
324324
{
325325
ut_ad(have_u_not_x());
326326
lock.u_wr_upgrade(file, line);
@@ -329,16 +329,16 @@ inline void sux_lock<srw_lock>::u_x_upgrade(const char *file, unsigned line)
329329
#endif
330330

331331
template<>
332-
inline void sux_lock<srw_lock_low>::s_lock()
332+
inline void sux_lock<ssux_lock_low>::s_lock()
333333
{
334334
ut_ad(!have_x());
335335
ut_ad(!have_s());
336-
lock.template rd_lock<true>();
336+
lock.rd_lock();
337337
ut_d(s_lock_register());
338338
}
339339

340340
template<>
341-
inline void sux_lock<srw_lock_low>::u_lock()
341+
inline void sux_lock<ssux_lock_low>::u_lock()
342342
{
343343
os_thread_id_t id= os_thread_get_curr_id();
344344
if (writer.load(std::memory_order_relaxed) == id)
@@ -353,7 +353,7 @@ inline void sux_lock<srw_lock_low>::u_lock()
353353
}
354354

355355
template<>
356-
inline void sux_lock<srw_lock_low>::x_lock(bool for_io)
356+
inline void sux_lock<ssux_lock_low>::x_lock(bool for_io)
357357
{
358358
os_thread_id_t id= os_thread_get_curr_id();
359359
if (writer.load(std::memory_order_relaxed) == id)
@@ -363,22 +363,22 @@ inline void sux_lock<srw_lock_low>::x_lock(bool for_io)
363363
}
364364
else
365365
{
366-
lock.template wr_lock<true>();
366+
lock.wr_lock();
367367
ut_ad(!recursive);
368368
recursive= RECURSIVE_X;
369369
set_first_owner(for_io ? FOR_IO : id);
370370
}
371371
}
372372

373373
template<>
374-
inline void sux_lock<srw_lock_low>::u_x_upgrade()
374+
inline void sux_lock<ssux_lock_low>::u_x_upgrade()
375375
{
376376
ut_ad(have_u_not_x());
377377
lock.u_wr_upgrade();
378378
recursive/= RECURSIVE_U;
379379
}
380380

381-
template<> inline bool sux_lock<srw_lock_low>::x_lock_upgraded()
381+
template<> inline bool sux_lock<ssux_lock_low>::x_lock_upgraded()
382382
{
383383
os_thread_id_t id= os_thread_get_curr_id();
384384
if (writer.load(std::memory_order_relaxed) == id)
@@ -397,7 +397,7 @@ template<> inline bool sux_lock<srw_lock_low>::x_lock_upgraded()
397397
}
398398
else
399399
{
400-
lock.template wr_lock<true>();
400+
lock.wr_lock();
401401
ut_ad(!recursive);
402402
recursive= RECURSIVE_X;
403403
set_first_owner(id);
@@ -406,7 +406,7 @@ template<> inline bool sux_lock<srw_lock_low>::x_lock_upgraded()
406406
}
407407

408408
template<>
409-
inline bool sux_lock<srw_lock_low>::u_lock_try(bool for_io)
409+
inline bool sux_lock<ssux_lock_low>::u_lock_try(bool for_io)
410410
{
411411
os_thread_id_t id= os_thread_get_curr_id();
412412
if (writer.load(std::memory_order_relaxed) == id)
@@ -427,7 +427,7 @@ inline bool sux_lock<srw_lock_low>::u_lock_try(bool for_io)
427427
}
428428

429429
template<>
430-
inline bool sux_lock<srw_lock_low>::x_lock_try()
430+
inline bool sux_lock<ssux_lock_low>::x_lock_try()
431431
{
432432
os_thread_id_t id= os_thread_get_curr_id();
433433
if (writer.load(std::memory_order_relaxed) == id)

0 commit comments

Comments
 (0)