MySQL  8.0.24
Source Code Documentation
sync0rw.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1995, 2021, Oracle and/or its affiliates.
4 Copyright (c) 2008, Google Inc.
5 
6 Portions of this file contain modifications contributed and copyrighted by
7 Google, Inc. Those modifications are gratefully acknowledged and are described
8 briefly in the InnoDB documentation. The contributions by Google are
9 incorporated with their permission, and subject to the conditions contained in
10 the file COPYING.Google.
11 
12 This program is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License, version 2.0, as published by the
14 Free Software Foundation.
15 
16 This program is also distributed with certain software (including but not
17 limited to OpenSSL) that is licensed under separate terms, as designated in a
18 particular file or component or in included license documentation. The authors
19 of MySQL hereby grant you an additional permission to link the program and
20 your derivative works with the separately licensed software that they have
21 included with MySQL.
22 
23 This program is distributed in the hope that it will be useful, but WITHOUT
24 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
25 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
26 for more details.
27 
28 You should have received a copy of the GNU General Public License along with
29 this program; if not, write to the Free Software Foundation, Inc.,
30 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 
32 *****************************************************************************/
33 
34 /** @file include/sync0rw.h
35  The read-write lock (for threads, not for database transactions)
36 
37  Created 9/11/1995 Heikki Tuuri
38  *******************************************************/
39 
40 #ifndef sync0rw_h
41 #define sync0rw_h
42 
43 #include "univ.i"
44 #ifndef UNIV_HOTBACKUP
45 #include "os0event.h"
46 #include "ut0counter.h"
47 #endif /* !UNIV_HOTBACKUP */
48 #include <atomic>
49 #include "ut0mutex.h"
50 
51 struct rw_lock_t;
52 
53 #ifndef UNIV_HOTBACKUP
54 
55 #ifdef UNIV_LIBRARY
56 
57 #ifdef UNIV_DEBUG
58 
59 /**
60 Pass-through version of rw_lock_own(), which normally checks that the
61 thread has locked the rw-lock in the specified mode.
62 @param[in] lock pointer to rw-lock
63 @param[in] lock_type lock type: RW_LOCK_S, RW_LOCK_X
64 @return true if success */
65 UNIV_INLINE
66 bool rw_lock_own(rw_lock_t *lock, ulint lock_type) { return (lock != nullptr); }
67 
68 #define sync_check_iterate(A) true
69 #endif /* UNIV_DEBUG */
70 
71 #define rw_lock_s_lock(L) ((void)0)
72 #define rw_lock_s_unlock(L) ((void)0)
73 #define rw_lock_x_lock(L) ((void)0)
74 #define rw_lock_x_lock_nowait(L) true
75 #define rw_lock_x_unlock(L) ((void)0)
76 #define rw_lock_sx_lock(L) ((void)0)
77 #define rw_lock_sx_unlock(L) ((void)0)
78 #define rw_lock_s_lock_inline(M, P, F, L) ((void)0)
79 #define rw_lock_s_unlock_inline(M, P, F, L) ((void)0)
80 #define rw_lock_x_lock_inline(M, P, F, L) ((void)0)
81 #define rw_lock_x_unlock_inline(M, P, F, L) ((void)0)
82 #define rw_lock_sx_lock_inline(M, P, F, L) ((void)0)
83 #define rw_lock_sx_unlock_inline(M, P, F, L) ((void)0)
84 #define sync_check_lock(A, B) ((void)0)
85 #define rw_lock_s_lock_nowait(M, F, L) true
86 #define rw_lock_own_flagged(A, B) true
87 #endif /* UNIV_LIBRARY */
88 
89 #endif /* !UNIV_HOTBACKUP */
90 
91 /* Latch types; these are used also in btr0btr.h and mtr0mtr.h: keep the
92 numerical values smaller than 30 (smaller than BTR_MODIFY_TREE and
93 MTR_MEMO_MODIFY) and the order of the numerical values like below! and they
94 should be 2pow value to be used also as ORed combination of flag. */
99  RW_NO_LATCH = 8
100 };
101 
102 /* We decrement lock_word by X_LOCK_DECR for each x_lock. It is also the
103 start value for the lock_word, meaning that it limits the maximum number
104 of concurrent read locks before the rw_lock breaks. */
105 /* We decrement lock_word by X_LOCK_HALF_DECR for sx_lock. */
106 #define X_LOCK_DECR 0x20000000
107 #define X_LOCK_HALF_DECR 0x10000000
108 
109 #ifdef UNIV_DEBUG
110 struct rw_lock_debug_t;
111 #endif /* UNIV_DEBUG */
112 
113 typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t;
114 
115 extern rw_lock_list_t rw_lock_list;
116 extern ib_mutex_t rw_lock_list_mutex;
117 
118 #ifndef UNIV_LIBRARY
119 #ifndef UNIV_HOTBACKUP
120 #ifndef UNIV_PFS_RWLOCK
121 /** Creates, or rather, initializes an rw-lock object in a specified memory
122  location (which must be appropriately aligned). The rw-lock is initialized
123  to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
124  is necessary only if the memory block containing it is freed.
125  if MySQL performance schema is enabled and "UNIV_PFS_RWLOCK" is
126  defined, the rwlock are instrumented with performance schema probes. */
127 #ifdef UNIV_DEBUG
128 #define rw_lock_create(K, L, level) \
129  rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
130 #else /* UNIV_DEBUG */
131 #define rw_lock_create(K, L, level) rw_lock_create_func((L), __FILE__, __LINE__)
132 #endif /* UNIV_DEBUG */
133 
134 /** NOTE! The following macros should be used in rw locking and
135  unlocking, not the corresponding function. */
136 
137 #define rw_lock_s_lock(M) rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
138 
139 #define rw_lock_s_lock_inline(M, P, F, L) \
140  rw_lock_s_lock_func((M), (P), (F), (L))
141 
142 #define rw_lock_s_lock_gen(M, P) \
143  rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
144 
145 #define rw_lock_s_lock_nowait(M, F, L) rw_lock_s_lock_low((M), 0, (F), (L))
146 
147 #ifdef UNIV_DEBUG
148 #define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(P, L)
149 #else
150 #define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
151 #endif /* UNIV_DEBUG */
152 
153 #define rw_lock_sx_lock(L) rw_lock_sx_lock_func((L), 0, __FILE__, __LINE__)
154 
155 #define rw_lock_sx_lock_inline(M, P, F, L) \
156  rw_lock_sx_lock_func((M), (P), (F), (L))
157 
158 #define rw_lock_sx_lock_gen(M, P) \
159  rw_lock_sx_lock_func((M), (P), __FILE__, __LINE__)
160 
161 #define rw_lock_sx_lock_nowait(M, P) \
162  rw_lock_sx_lock_low((M), (P), __FILE__, __LINE__)
163 
164 #ifdef UNIV_DEBUG
165 #define rw_lock_sx_unlock(L) rw_lock_sx_unlock_func(0, L)
166 #define rw_lock_sx_unlock_gen(L, P) rw_lock_sx_unlock_func(P, L)
167 #else /* UNIV_DEBUG */
168 #define rw_lock_sx_unlock(L) rw_lock_sx_unlock_func(L)
169 #define rw_lock_sx_unlock_gen(L, P) rw_lock_sx_unlock_func(L)
170 #endif /* UNIV_DEBUG */
171 
172 #define rw_lock_x_lock(M) rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
173 
174 #define rw_lock_x_lock_inline(M, P, F, L) \
175  rw_lock_x_lock_func((M), (P), (F), (L))
176 
177 #define rw_lock_x_lock_gen(M, P) \
178  rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
179 
180 #define rw_lock_x_lock_nowait(M) \
181  rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
182 
183 #define rw_lock_x_lock_func_nowait_inline(M, F, L) \
184  rw_lock_x_lock_func_nowait((M), (F), (L))
185 
186 #ifdef UNIV_DEBUG
187 #define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(P, L)
188 #else
189 #define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
190 #endif
191 
192 #define rw_lock_free(M) rw_lock_free_func(M)
193 
194 #else /* !UNIV_PFS_RWLOCK */
195 
196 /* Following macros point to Performance Schema instrumented functions. */
197 #ifdef UNIV_DEBUG
198 #define rw_lock_create(K, L, level) \
199  pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
200 #else /* UNIV_DEBUG */
201 #define rw_lock_create(K, L, level) \
202  pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
203 #endif /* UNIV_DEBUG */
204 
205 /******************************************************************
206 NOTE! The following macros should be used in rw locking and
207 unlocking, not the corresponding function. */
208 
209 #define rw_lock_s_lock(M) pfs_rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
210 
211 #define rw_lock_s_lock_inline(M, P, F, L) \
212  pfs_rw_lock_s_lock_func((M), (P), (F), (L))
213 
214 #define rw_lock_s_lock_gen(M, P) \
215  pfs_rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
216 
217 #define rw_lock_s_lock_nowait(M, F, L) pfs_rw_lock_s_lock_low((M), 0, (F), (L))
218 
219 #ifdef UNIV_DEBUG
220 #define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(P, L)
221 #else
222 #define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(L)
223 #endif
224 
225 #define rw_lock_sx_lock(M) pfs_rw_lock_sx_lock_func((M), 0, __FILE__, __LINE__)
226 
227 #define rw_lock_sx_lock_inline(M, P, F, L) \
228  pfs_rw_lock_sx_lock_func((M), (P), (F), (L))
229 
230 #define rw_lock_sx_lock_gen(M, P) \
231  pfs_rw_lock_sx_lock_func((M), (P), __FILE__, __LINE__)
232 
233 #define rw_lock_sx_lock_nowait(M, P) \
234  pfs_rw_lock_sx_lock_low((M), (P), __FILE__, __LINE__)
235 
236 #ifdef UNIV_DEBUG
237 #define rw_lock_sx_unlock(L) pfs_rw_lock_sx_unlock_func(0, L)
238 #define rw_lock_sx_unlock_gen(L, P) pfs_rw_lock_sx_unlock_func(P, L)
239 #else
240 #define rw_lock_sx_unlock(L) pfs_rw_lock_sx_unlock_func(L)
241 #define rw_lock_sx_unlock_gen(L, P) pfs_rw_lock_sx_unlock_func(L)
242 #endif
243 
244 #define rw_lock_x_lock(M) pfs_rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
245 
246 #define rw_lock_x_lock_inline(M, P, F, L) \
247  pfs_rw_lock_x_lock_func((M), (P), (F), (L))
248 
249 #define rw_lock_x_lock_gen(M, P) \
250  pfs_rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
251 
252 #define rw_lock_x_lock_nowait(M) \
253  pfs_rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
254 
255 #define rw_lock_x_lock_func_nowait_inline(M, F, L) \
256  pfs_rw_lock_x_lock_func_nowait((M), (F), (L))
257 
258 #ifdef UNIV_DEBUG
259 #define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(P, L)
260 #else
261 #define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(L)
262 #endif
263 
264 #define rw_lock_free(M) pfs_rw_lock_free_func(M)
265 
266 #endif /* !UNIV_PFS_RWLOCK */
267 
268 #define rw_lock_s_unlock(L) rw_lock_s_unlock_gen(L, 0)
269 #define rw_lock_x_unlock(L) rw_lock_x_unlock_gen(L, 0)
270 
271 /** Creates, or rather, initializes an rw-lock object in a specified memory
272  location (which must be appropriately aligned). The rw-lock is initialized
273  to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
274  is necessary only if the memory block containing it is freed. */
276  rw_lock_t *lock, /*!< in: pointer to memory */
277 #ifdef UNIV_DEBUG
278  latch_level_t level, /*!< in: level */
279  const char *cmutex_name, /*!< in: mutex name */
280 #endif /* UNIV_DEBUG */
281  const char *cfile_name, /*!< in: file name where created */
282  ulint cline); /*!< in: file line where created */
283 /** Calling this function is obligatory only if the memory buffer containing
284  the rw-lock is freed. Removes an rw-lock object from the global list. The
285  rw-lock is checked to be in the non-locked state. */
286 void rw_lock_free_func(rw_lock_t *lock); /*!< in/out: rw-lock */
287 #ifdef UNIV_DEBUG
288 /** Checks that the rw-lock has been initialized and that there are no
289  simultaneous shared and exclusive locks.
290  @return true */
291 bool rw_lock_validate(const rw_lock_t *lock); /*!< in: rw-lock */
292 #endif /* UNIV_DEBUG */
293 
294 /** Low-level function which tries to lock an rw-lock in s-mode. Performs no
295 spinning.
296 @param[in] lock pointer to rw-lock
297 @param[in] pass pass value; != 0, if the lock will be passed
298  to another thread to unlock
299 @param[in] file_name file name where lock requested
300 @param[in] line line where requested
301 @return true if success */
302 UNIV_INLINE
303 bool rw_lock_s_lock_low(rw_lock_t *lock, ulint pass MY_ATTRIBUTE((unused)),
304  const char *file_name, ulint line);
305 
306 /** NOTE! Use the corresponding macro, not directly this function, except if
307 you supply the file name and line number. Lock an rw-lock in shared mode for
308 the current thread. If the rw-lock is locked in exclusive mode, or there is an
309 exclusive lock request waiting, the function spins a preset time (controlled
310 by srv_n_spin_wait_rounds), waiting for the lock, before suspending the thread.
311 @param[in] lock pointer to rw-lock
312 @param[in] pass pass value; != 0, if the lock will be passed
313  to another thread to unlock
314 @param[in] file_name file name where lock requested
315 @param[in] line line where requested */
316 UNIV_INLINE
317 void rw_lock_s_lock_func(rw_lock_t *lock, ulint pass, const char *file_name,
318  ulint line);
319 
320 /** NOTE! Use the corresponding macro, not directly this function! Lock an
321 rw-lock in exclusive mode for the current thread if the lock can be obtained
322 immediately.
323 @param[in] lock pointer to rw-lock
324 @param[in] file_name file name where lock requested
325 @param[in] line line where requested
326 @return true if success */
327 UNIV_INLINE
329  ulint line);
330 
331 /** Releases a shared mode lock. */
332 #ifdef UNIV_DEBUG
333 /** @param[in] pass pass value; != 0, if the lock will be passed
334  to another thread to unlock */
335 #endif
336 /** @param[in,out] lock rw-lock */
337 UNIV_INLINE
339 #ifdef UNIV_DEBUG
340  ulint pass,
341 #endif /* UNIV_DEBUG */
342  rw_lock_t *lock);
343 
344 /** NOTE! Use the corresponding macro, not directly this function! Lock an
345  rw-lock in exclusive mode for the current thread. If the rw-lock is locked
346  in shared or exclusive mode, or there is an exclusive lock request waiting,
347  the function spins a preset time (controlled by srv_n_spin_wait_rounds),
348  waiting for the lock, before suspending the thread. If the same thread has an
349  x-lock on the rw-lock, locking succeed, with the following exception: if pass
350  != 0, only a single x-lock may be taken on the lock. NOTE: If the same thread
351  has an s-lock, locking does not succeed! */
353  rw_lock_t *lock, /*!< in: pointer to rw-lock */
354  ulint pass, /*!< in: pass value; != 0, if the lock will
355  be passed to another thread to unlock */
356  const char *file_name, /*!< in: file name where lock requested */
357  ulint line); /*!< in: line where requested */
358 /** Low-level function for acquiring an sx lock.
359  @return false if did not succeed, true if success. */
361  rw_lock_t *lock, /*!< in: pointer to rw-lock */
362  ulint pass, /*!< in: pass value; != 0, if the lock will
363  be passed to another thread to unlock */
364  const char *file_name, /*!< in: file name where lock requested */
365  ulint line); /*!< in: line where requested */
366 /** NOTE! Use the corresponding macro, not directly this function! Lock an
367  rw-lock in SX mode for the current thread. If the rw-lock is locked
368  in exclusive mode, or there is an exclusive lock request waiting,
369  the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
370  for the lock, before suspending the thread. If the same thread has an x-lock
371  on the rw-lock, locking succeed, with the following exception: if pass != 0,
372  only a single sx-lock may be taken on the lock. NOTE: If the same thread has
373  an s-lock, locking does not succeed! */
375  rw_lock_t *lock, /*!< in: pointer to rw-lock */
376  ulint pass, /*!< in: pass value; != 0, if the lock will
377  be passed to another thread to unlock */
378  const char *file_name, /*!< in: file name where lock requested */
379  ulint line); /*!< in: line where requested */
380 
381 /** Releases an exclusive mode lock. */
382 #ifdef UNIV_DEBUG
383 /** @param[in] pass pass value; != 0, if the lock will be passed
384  to another thread to unlock */
385 #endif /* UNIV_DEBUG */
386 /** @param[in,out] lock rw-lock */
387 UNIV_INLINE
389 #ifdef UNIV_DEBUG
390  ulint pass,
391 #endif /* UNIV_DEBUG */
392  rw_lock_t *lock);
393 
394 /** Releases an sx mode lock. */
395 #ifdef UNIV_DEBUG
396 /** @param[in] pass pass value; != 0, if the lock will be passed
397  to another thread to unlock */
398 #endif /* UNIV_DEBUG */
399 /** @param[in,out] lock rw-lock */
400 UNIV_INLINE
402 #ifdef UNIV_DEBUG
403  ulint pass,
404 #endif /* UNIV_DEBUG */
405  rw_lock_t *lock);
406 
407 /** This function is used in the insert buffer to move the ownership of an
408  x-latch on a buffer frame to the current thread. The x-latch was set by
409  the buffer read operation and it protected the buffer frame while the
410  read was done. The ownership is moved because we want that the current
411  thread is able to acquire a second x-latch which is stored in an mtr.
412  This, in turn, is needed to pass the debug checks of index page
413  operations. */
415  rw_lock_t *lock); /*!< in: lock which was x-locked in the
416  buffer read */
417 #endif /* !UNIV_HOTBACKUP */
418 /** Returns the value of writer_count for the lock. Does not reserve the lock
419  mutex, so the caller must be sure it is not changed during the call.
420  @return value of writer_count */
421 UNIV_INLINE
422 ulint rw_lock_get_x_lock_count(const rw_lock_t *lock); /*!< in: rw-lock */
423 /** Returns the number of sx-lock for the lock. Does not reserve the lock
424  mutex, so the caller must be sure it is not changed during the call.
425  @return value of writer_count */
426 UNIV_INLINE
427 ulint rw_lock_get_sx_lock_count(const rw_lock_t *lock); /*!< in: rw-lock */
428 /** Check if there are threads waiting for the rw-lock.
429  @return true if waiters, false otherwise */
430 UNIV_INLINE
431 bool rw_lock_get_waiters(const rw_lock_t *lock); /*!< in: rw-lock */
432 /** Returns the write-status of the lock - this function made more sense
433  with the old rw_lock implementation.
434  @return RW_LOCK_NOT_LOCKED, RW_LOCK_X, RW_LOCK_X_WAIT, RW_LOCK_SX */
435 UNIV_INLINE
436 ulint rw_lock_get_writer(const rw_lock_t *lock); /*!< in: rw-lock */
437 /** Returns the number of readers (s-locks).
438  @return number of readers */
439 UNIV_INLINE
440 ulint rw_lock_get_reader_count(const rw_lock_t *lock); /*!< in: rw-lock */
441 
442 /** Decrements lock_word the specified amount if it is greater than 0.
443 This is used by both s_lock and x_lock operations.
444 @param[in,out] lock rw-lock
445 @param[in] amount amount to decrement
446 @param[in] threshold threshold of judgement
447 @return true if decr occurs */
448 UNIV_INLINE
449 bool rw_lock_lock_word_decr(rw_lock_t *lock, ulint amount, lint threshold);
450 
451 /** Increments lock_word the specified amount and returns new value.
452 @param[in,out] lock rw-lock
453 @param[in] amount amount to decrement
454 @return lock->lock_word after increment */
455 UNIV_INLINE
456 lint rw_lock_lock_word_incr(rw_lock_t *lock, ulint amount);
457 
458 /** This function sets the lock->writer_thread and lock->recursive fields. Sets
459 lock->recursive field using atomic release after setting lock->writer thread to
460 ensure proper memory ordering of the two.
461 Note that it is assumed that the caller of this function effectively owns
462 the lock i.e.: nobody else is allowed to modify lock->writer_thread at this
463 point in time. The protocol is that lock->writer_thread MUST be updated BEFORE
464 the lock->recursive flag is set.
465 @param[in,out] lock lock to work on
466 @param[in] recursive true if recursion allowed */
467 UNIV_INLINE
469 
470 #ifndef UNIV_HOTBACKUP
471 #ifdef UNIV_DEBUG
472 /** Checks if the thread has locked the rw-lock in the specified mode, with
473  the pass value == 0. */
474 ibool rw_lock_own(rw_lock_t *lock, /*!< in: rw-lock */
475  ulint lock_type) /*!< in: lock type: RW_LOCK_S,
476  RW_LOCK_X */
477  MY_ATTRIBUTE((warn_unused_result));
478 
479 /** Checks if the thread has locked the rw-lock in the specified mode, with
480  the pass value == 0. */
482  const rw_lock_t *lock, /*!< in: rw-lock */
483  rw_lock_flags_t flags) /*!< in: specify lock types with
484  OR of the rw_lock_flag_t values */
485  MY_ATTRIBUTE((warn_unused_result));
486 #endif /* UNIV_DEBUG */
487 #endif /* !UNIV_HOTBACKUP */
488 /** Checks if somebody has locked the rw-lock in the specified mode.
489  @return true if locked */
490 bool rw_lock_is_locked(rw_lock_t *lock, /*!< in: rw-lock */
491  ulint lock_type); /*!< in: lock type: RW_LOCK_S,
492  RW_LOCK_X or RW_LOCK_SX */
493 #ifdef UNIV_DEBUG
494 /** Prints debug info of currently locked rw-locks. */
495 void rw_lock_list_print_info(FILE *file); /*!< in: file where to print */
496 
497 /*#####################################################################*/
498 
499 /** Prints info of a debug struct.
500 @param[in] f Output stream
501 @param[in] info Debug struct */
503 
504 #endif /* UNIV_DEBUG */
505 
506 #endif /* !UNIV_LIBRARY */
507 
508 /* NOTE! The structure appears here only for the compiler to know its size.
509 Do not use its fields directly! */
510 
511 /** The structure used in the spin lock implementation of a read-write
512 lock. Several threads may have a shared lock simultaneously in this
513 lock, but only one writer may have an exclusive lock, in which case no
514 shared locks are allowed. To prevent starving of a writer blocked by
515 readers, a writer may queue for x-lock by decrementing lock_word: no
516 new readers will be let in while the thread waits for readers to
517 exit. */
518 
519 struct rw_lock_t
520 #ifdef UNIV_DEBUG
521  : public latch_t
522 #endif /* UNIV_DEBUG */
523 {
524  rw_lock_t() = default;
525 
526  /** rw_lock_t is not a copyable object, the reasoning
527  behind this is the same as the reasoning behind why
528  std::mutex is not copyable. It is supposed to represent
529  a synchronization primitive for which copying semantics
530  do not make sense. */
531  rw_lock_t(const rw_lock_t &) = delete;
532  rw_lock_t &operator=(const rw_lock_t &) = delete;
533 
534  /** Holds the state of the lock. */
535  std::atomic<int32_t> lock_word;
536 
537  /** 1: there are waiters */
538  std::atomic<bool> waiters;
539 
540  /** Default value FALSE which means the lock is non-recursive.
541  The value is typically set to TRUE making normal rw_locks recursive.
542  In case of asynchronous IO, when a non-zero value of 'pass' is
543  passed then we keep the lock non-recursive.
544 
545  This flag also tells us about the state of writer_thread field.
546  If this flag is set then writer_thread MUST contain the thread
547  id of the current x-holder or wait-x thread. This flag must be
548  reset in x_unlock functions before incrementing the lock_word */
549  std::atomic<bool> recursive;
550 
551  /** This is TRUE if the writer field is RW_LOCK_X_WAIT; this field
552  is located far from the memory update hotspot fields which are at
553  the start of this struct, thus we can peek this field without
554  causing much memory bus traffic */
556 
557  /** number of granted SX locks. */
558  volatile ulint sx_recursive;
559 
560  /** Thread id of writer thread. Is only guaranteed to have non-stale value if
561  recursive flag is set, otherwise it may contain native thread ID of a
562  thread which already released or passed the lock. */
563  std::atomic<std::thread::id> writer_thread;
564 
565  /** XOR of reader threads' IDs. If there is exactly one reader it should allow
566  to retrieve the thread ID of that reader. */
568 
569  /** Used by sync0arr.cc for thread queueing */
571 
572  /** Event for next-writer to wait on. A thread must decrement
573  lock_word before waiting. */
575 
576  /** File name where lock created */
577  const char *cfile_name;
578 
579  /** last s-lock file/line is not guaranteed to be correct */
580  const char *last_s_file_name;
581 
582  /** File name where last x-locked */
583  const char *last_x_file_name;
584 
585  /** Line where created */
586  uint16_t cline;
587 
588  /** If 1 then the rw-lock is a block lock */
590 
591  /** Line number where last time s-locked */
592  uint16_t last_s_line;
593 
594  /** Line number where last time x-locked */
595  uint16_t last_x_line;
596 
597  /** Count of os_waits. May not be accurate */
598  uint32_t count_os_wait;
599 
600  /** All allocated rw locks are put into a list */
602 
603 #ifdef UNIV_PFS_RWLOCK
604  /** The instrumentation hook */
606 #endif /* UNIV_PFS_RWLOCK */
607 
608 #ifdef UNIV_DEBUG
609  /** Destructor */
610  ~rw_lock_t() override {
611  ut_ad(magic_n == MAGIC_N);
612  magic_n = 0;
613  }
614 
615  virtual std::string to_string() const override;
616  virtual std::string locked_from() const override;
617 
618  /** For checking memory corruption. */
619  static const uint32_t MAGIC_N = 22643;
620  uint32_t magic_n = {MAGIC_N};
621 
622  /** In the debug version: pointer to the debug info list of the lock */
624 
625  /** Level in the global latching order. */
627 #endif /* UNIV_DEBUG */
628 };
629 #ifdef UNIV_DEBUG
630 /** The structure for storing debug info of an rw-lock. All access to this
631 structure must be protected by rw_lock_debug_mutex_enter(). */
633  std::thread::id thread_id; /*!< The thread id of the thread which
634  locked the rw-lock */
635  ulint pass; /*!< Pass value given in the lock operation */
636  ulint lock_type; /*!< Type of the lock: RW_LOCK_X,
637  RW_LOCK_S, RW_LOCK_X_WAIT */
638  const char *file_name; /*!< File name where the lock was obtained */
639  ulint line; /*!< Line where the rw-lock was locked */
641  /*!< Debug structs are linked in a two-way
642  list */
643 };
644 #endif /* UNIV_DEBUG */
645 
646 #ifndef UNIV_LIBRARY
647 #ifndef UNIV_HOTBACKUP
648 /* For performance schema instrumentation, a new set of rwlock
649 wrap functions are created if "UNIV_PFS_RWLOCK" is defined.
650 The instrumentations are not planted directly into original
651 functions, so that we keep the underlying function as they
652 are. And in case, user wants to "take out" some rwlock from
653 instrumentation even if performance schema (UNIV_PFS_RWLOCK)
654 is defined, they can do so by reinstating APIs directly link to
655 original underlying functions.
656 The instrumented function names have prefix of "pfs_rw_lock_" vs.
657 original name prefix of "rw_lock_". Following are list of functions
658 that have been instrumented:
659 
660 rw_lock_create()
661 rw_lock_x_lock()
662 rw_lock_x_lock_gen()
663 rw_lock_x_lock_nowait()
664 rw_lock_x_unlock_gen()
665 rw_lock_s_lock()
666 rw_lock_s_lock_gen()
667 rw_lock_s_lock_nowait()
668 rw_lock_s_unlock_gen()
669 rw_lock_sx_lock()
670 rw_lock_sx_unlock_gen()
671 rw_lock_free()
672 */
673 
674 #ifdef UNIV_PFS_RWLOCK
675 /** Performance schema instrumented wrap function for rw_lock_create_func()
676 NOTE! Please use the corresponding macro rw_lock_create(), not directly this
677 function!
678 @param[in] key key registered with performance schema
679 @param[in] lock rw lock */
680 #ifdef UNIV_DEBUG
681 /**
682 @param[in] level level
683 @param[in] cmutex_name mutex name */
684 #endif /* UNIV_DEBUG */
685 /**
686 @param[in] cline file line where created
687 @param[in] cfile_name file name where created */
688 UNIV_INLINE
690 #ifdef UNIV_DEBUG
691  latch_level_t level, const char *cmutex_name,
692 #endif /* UNIV_DEBUG */
693  const char *cfile_name, ulint cline);
694 
695 /** Performance schema instrumented wrap function for rw_lock_x_lock_func()
696 NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly this
697 function!
698 @param[in] lock pointer to rw-lock
699 @param[in] pass pass value; != 0, if the lock will be passed
700  to another thread to unlock
701 @param[in] file_name file name where lock requested
702 @param[in] line line where requested */
703 UNIV_INLINE
704 void pfs_rw_lock_x_lock_func(rw_lock_t *lock, ulint pass, const char *file_name,
705  ulint line);
706 
707 /** Performance schema instrumented wrap function for
708 rw_lock_x_lock_func_nowait()
709 NOTE! Please use the corresponding macro, not directly this function!
710 @param[in] lock pointer to rw-lock
711 @param[in] file_name file name where lock requested
712 @param[in] line line where requested
713 @return true if success */
714 UNIV_INLINE
715 bool pfs_rw_lock_x_lock_func_nowait(rw_lock_t *lock, const char *file_name,
716  ulint line);
717 
718 /** Performance schema instrumented wrap function for rw_lock_s_lock_func()
719 NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly this
720 function!
721 @param[in] lock pointer to rw-lock
722 @param[in] pass pass value; != 0, if the lock will be passed
723  to another thread to unlock
724 @param[in] file_name file name where lock requested
725 @param[in] line line where requested */
726 UNIV_INLINE
727 void pfs_rw_lock_s_lock_func(rw_lock_t *lock, ulint pass, const char *file_name,
728  ulint line);
729 
730 /** Performance schema instrumented wrap function for rw_lock_s_lock_func()
731 NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly this
732 function!
733 @param[in] lock pointer to rw-lock
734 @param[in] pass pass value; != 0, if the lock will be passed
735  to another thread to unlock
736 @param[in] file_name file name where lock requested
737 @param[in] line line where requested
738 @return true if success */
739 UNIV_INLINE
740 ibool pfs_rw_lock_s_lock_low(rw_lock_t *lock, ulint pass, const char *file_name,
741  ulint line);
742 
743 /** Performance schema instrumented wrap function for rw_lock_x_lock_func()
744 NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly this
745 function!
746 @param[in] lock pointer to rw-lock
747 @param[in] pass pass value; != 0, if the lock will be passed
748  to another thread to unlock
749 @param[in] file_name file name where lock requested
750 @param[in] line line where requested */
751 UNIV_INLINE
752 void pfs_rw_lock_x_lock_func(rw_lock_t *lock, ulint pass, const char *file_name,
753  ulint line);
754 
755 /** Performance schema instrumented wrap function for rw_lock_s_unlock_func()
756 NOTE! Please use the corresponding macro rw_lock_s_unlock(), not directly this
757 function! */
758 #ifdef UNIV_DEBUG
759 /** @param[in] pass pass value; != 0, if the lock may have been passed to
760  another thread to unlock */
761 #endif /* UNIV_DEBUG */
762 /** @param[in,out] lock rw-lock */
763 UNIV_INLINE
765 #ifdef UNIV_DEBUG
766  ulint pass,
767 #endif /* UNIV_DEBUG */
768  rw_lock_t *lock);
769 
770 /** Performance schema instrumented wrap function for rw_lock_x_unlock_func()
771 NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly this
772 function! */
773 #ifdef UNIV_DEBUG
774 /** @param[in] pass pass value; != 0, if the lock may have been passed to
775  another thread to unlock */
776 #endif /* UNIV_DEBUG */
777 /** @param[in,out] lock rw-lock */
778 UNIV_INLINE
780 #ifdef UNIV_DEBUG
781  ulint pass,
782 #endif /* UNIV_DEBUG */
783  rw_lock_t *lock);
784 
785 /** Performance schema instrumented wrap function for rw_lock_sx_lock_func()
786 NOTE! Please use the corresponding macro rw_lock_sx_lock(), not directly this
787 function!
788 @param[in] lock pointer to rw-lock
789 @param[in] pass pass value; != 0, if the lock will be passed
790  to another thread to unlock
791 @param[in] file_name file name where lock requested
792 @param[in] line line where requested */
793 UNIV_INLINE
795  const char *file_name, ulint line);
796 
797 /** Performance schema instrumented wrap function for rw_lock_sx_lock_nowait()
798 NOTE! Please use the corresponding macro, not directly this function!
799 @param[in] lock pointer to rw-lock
800 @param[in] pass pass value; != 0, if the lock will be passed
801  to another thread to unlock
802 @param[in] file_name file name where lock requested
803 @param[in] line line where requested */
804 UNIV_INLINE
805 bool pfs_rw_lock_sx_lock_low(rw_lock_t *lock, ulint pass, const char *file_name,
806  ulint line);
807 
808 /** Performance schema instrumented wrap function for rw_lock_sx_unlock_func()
809 NOTE! Please use the corresponding macro rw_lock_sx_unlock(), not directly this
810 function!
811 @param[in,out] lock pointer to rw-lock */
812 #ifdef UNIV_DEBUG
813 /** @param[in] pass pass value; != 0, if the lock will be passed
814  to another thread to unlock */
815 #endif /* UNIV_DEBUG */
816 UNIV_INLINE
818 #ifdef UNIV_DEBUG
819  ulint pass,
820 #endif /* UNIV_DEBUG */
821  rw_lock_t *lock);
822 
823 /** Performance schema instrumented wrap function for rw_lock_free_func()
824  NOTE! Please use the corresponding macro rw_lock_free(), not directly
825  this function! */
826 UNIV_INLINE
827 void pfs_rw_lock_free_func(rw_lock_t *lock); /*!< in: rw-lock */
828 #endif /* UNIV_PFS_RWLOCK */
829 
830 #include "sync0rw.ic"
831 
832 #endif /* !UNIV_HOTBACKUP */
833 
834 #endif /* !UNIV_LIBRARY */
835 #endif /* sync0rw.h */
static int flags[50]
Definition: hp_test1.cc:39
static uchar key[100]
Definition: mi_test2.cc:58
Log info(cout, "NOTE")
const std::string FILE("FILE")
Definition: os0file.h:85
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:78
The interface to the operating system condition variables.
Interface for an instrumented rwlock.
Definition: psi_rwlock_bits.h:70
All (ordered) latches, used in debugging, must derive from this class.
Definition: sync0types.h:967
Define for performance schema registration key.
Definition: sync0sync.h:50
InnoDB condition variable.
Definition: os0event.cc:66
The structure for storing debug info of an rw-lock.
Definition: sync0rw.h:632
ulint lock_type
Type of the lock: RW_LOCK_X, RW_LOCK_S, RW_LOCK_X_WAIT.
Definition: sync0rw.h:636
ulint line
Line where the rw-lock was locked.
Definition: sync0rw.h:639
UT_LIST_NODE_T(rw_lock_debug_t) list
Debug structs are linked in a two-way list.
const char * file_name
File name where the lock was obtained.
Definition: sync0rw.h:638
std::thread::id thread_id
The thread id of the thread which locked the rw-lock.
Definition: sync0rw.h:633
ulint pass
Pass value given in the lock operation.
Definition: sync0rw.h:635
The structure used in the spin lock implementation of a read-write lock.
Definition: sync0rw.h:523
std::atomic< std::thread::id > writer_thread
Thread id of writer thread.
Definition: sync0rw.h:563
uint16_t last_x_line
Line number where last time x-locked.
Definition: sync0rw.h:595
static const uint32_t MAGIC_N
For checking memory corruption.
Definition: sync0rw.h:619
virtual std::string locked_from() const override
Print where it was locked from.
Definition: sync0rw.cc:1058
UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list
In the debug version: pointer to the debug info list of the lock.
std::atomic< bool > waiters
1: there are waiters
Definition: sync0rw.h:538
const char * cfile_name
File name where lock created.
Definition: sync0rw.h:577
rw_lock_t & operator=(const rw_lock_t &)=delete
const char * last_s_file_name
last s-lock file/line is not guaranteed to be correct
Definition: sync0rw.h:580
os_event_t wait_ex_event
Event for next-writer to wait on.
Definition: sync0rw.h:574
volatile ulint sx_recursive
number of granted SX locks.
Definition: sync0rw.h:558
bool is_block_lock
If 1 then the rw-lock is a block lock.
Definition: sync0rw.h:589
uint32_t count_os_wait
Count of os_waits.
Definition: sync0rw.h:598
rw_lock_t(const rw_lock_t &)=delete
rw_lock_t is not a copyable object, the reasoning behind this is the same as the reasoning behind why...
uint16_t last_s_line
Line number where last time s-locked.
Definition: sync0rw.h:592
struct PSI_rwlock * pfs_psi
The instrumentation hook.
Definition: sync0rw.h:605
rw_lock_t()=default
os_event_t event
Used by sync0arr.cc for thread queueing.
Definition: sync0rw.h:570
const char * last_x_file_name
File name where last x-locked.
Definition: sync0rw.h:583
latch_level_t level
Level in the global latching order.
Definition: sync0rw.h:626
Atomic_xor_of_thread_id reader_thread
XOR of reader threads' IDs.
Definition: sync0rw.h:567
virtual std::string to_string() const override
Print the rw-lock information.
Definition: sync0rw.cc:1087
~rw_lock_t() override
Destructor.
Definition: sync0rw.h:610
std::atomic< int32_t > lock_word
Holds the state of the lock.
Definition: sync0rw.h:535
UT_LIST_NODE_T(rw_lock_t) list
All allocated rw locks are put into a list.
bool writer_is_wait_ex
This is TRUE if the writer field is RW_LOCK_X_WAIT; this field is located far from the memory update ...
Definition: sync0rw.h:555
uint32_t magic_n
Definition: sync0rw.h:620
uint16_t cline
Line where created.
Definition: sync0rw.h:586
std::atomic< bool > recursive
Default value FALSE which means the lock is non-recursive.
Definition: sync0rw.h:549
UNIV_INLINE bool pfs_rw_lock_sx_lock_low(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
Performance schema instrumented wrap function for rw_lock_sx_lock_nowait() NOTE! Please use the corre...
bool rw_lock_is_locked(rw_lock_t *lock, ulint lock_type)
Checks if somebody has locked the rw-lock in the specified mode.
Definition: sync0rw.cc:784
void rw_lock_free_func(rw_lock_t *lock)
Calling this function is obligatory only if the memory buffer containing the rw-lock is freed.
Definition: sync0rw.cc:264
UNIV_INLINE bool rw_lock_get_waiters(const rw_lock_t *lock)
Check if there are threads waiting for the rw-lock.
void rw_lock_create_func(rw_lock_t *lock, latch_level_t level, const char *cmutex_name, const char *cfile_name, ulint cline)
Creates, or rather, initializes an rw-lock object in a specified memory location (which must be appro...
Definition: sync0rw.cc:193
void rw_lock_x_lock_func(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
NOTE! Use the corresponding macro, not directly this function! Lock an rw-lock in exclusive mode for ...
Definition: sync0rw.cc:602
UNIV_INLINE void pfs_rw_lock_sx_lock_func(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
Performance schema instrumented wrap function for rw_lock_sx_lock_func() NOTE! Please use the corresp...
UNIV_INLINE void rw_lock_s_lock_func(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
NOTE! Use the corresponding macro, not directly this function, except if you supply the file name and...
UNIV_INLINE void rw_lock_x_unlock_func(ulint pass, rw_lock_t *lock)
Releases an exclusive mode lock.
UNIV_INLINE void pfs_rw_lock_create_func(mysql_pfs_key_t key, rw_lock_t *lock, latch_level_t level, const char *cmutex_name, const char *cfile_name, ulint cline)
Performance schema instrumented wrap function for rw_lock_create_func() NOTE! Please use the correspo...
UNIV_INLINE bool rw_lock_x_lock_func_nowait(rw_lock_t *lock, const char *file_name, ulint line)
NOTE! Use the corresponding macro, not directly this function! Lock an rw-lock in exclusive mode for ...
typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t
UNIV_INLINE void pfs_rw_lock_sx_unlock_func(ulint pass, rw_lock_t *lock)
Performance schema instrumented wrap function for rw_lock_sx_unlock_func() NOTE! Please use the corre...
void rw_lock_debug_print(FILE *f, const rw_lock_debug_t *info)
Prints info of a debug struct.
Definition: sync0rw.cc:1025
UNIV_INLINE bool rw_lock_lock_word_decr(rw_lock_t *lock, ulint amount, lint threshold)
Decrements lock_word the specified amount if it is greater than 0.
ibool rw_lock_own(rw_lock_t *lock, ulint lock_type)
Checks if the thread has locked the rw-lock in the specified mode, with the pass value == 0.
Definition: sync0rw.cc:883
UNIV_INLINE void pfs_rw_lock_free_func(rw_lock_t *lock)
Performance schema instrumented wrap function for rw_lock_free_func() NOTE! Please use the correspond...
UNIV_INLINE void rw_lock_s_unlock_func(ulint pass, rw_lock_t *lock)
Releases a shared mode lock.
rw_lock_list_t rw_lock_list
Definition: sync0rw.cc:170
UNIV_INLINE bool pfs_rw_lock_x_lock_func_nowait(rw_lock_t *lock, const char *file_name, ulint line)
Performance schema instrumented wrap function for rw_lock_x_lock_func_nowait() NOTE!...
bool rw_lock_sx_lock_low(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
Low-level function for acquiring an sx lock.
Definition: sync0rw.cc:526
void rw_lock_sx_lock_func(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
NOTE! Use the corresponding macro, not directly this function! Lock an rw-lock in SX mode for the cur...
Definition: sync0rw.cc:687
UNIV_INLINE void pfs_rw_lock_x_unlock_func(ulint pass, rw_lock_t *lock)
Performance schema instrumented wrap function for rw_lock_x_unlock_func() NOTE! Please use the corres...
ib_mutex_t rw_lock_list_mutex
Definition: sync0rw.cc:171
bool rw_lock_validate(const rw_lock_t *lock)
Checks that the rw-lock has been initialized and that there are no simultaneous shared and exclusive ...
Definition: sync0rw.cc:768
void rw_lock_list_print_info(FILE *file)
Prints debug info of currently locked rw-locks.
Definition: sync0rw.cc:980
UNIV_INLINE void rw_lock_set_writer_id_and_recursion_flag(rw_lock_t *lock, bool recursive)
This function sets the lock->writer_thread and lock->recursive fields.
rw_lock_type_t
Definition: sync0rw.h:95
@ RW_SX_LATCH
Definition: sync0rw.h:98
@ RW_NO_LATCH
Definition: sync0rw.h:99
@ RW_X_LATCH
Definition: sync0rw.h:97
@ RW_S_LATCH
Definition: sync0rw.h:96
UNIV_INLINE void rw_lock_sx_unlock_func(ulint pass, rw_lock_t *lock)
Releases an sx mode lock.
UNIV_INLINE ulint rw_lock_get_writer(const rw_lock_t *lock)
Returns the write-status of the lock - this function made more sense with the old rw_lock implementat...
UNIV_INLINE void pfs_rw_lock_s_lock_func(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
Performance schema instrumented wrap function for rw_lock_s_lock_func() NOTE! Please use the correspo...
UNIV_INLINE ibool pfs_rw_lock_s_lock_low(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
Performance schema instrumented wrap function for rw_lock_s_lock_func() NOTE! Please use the correspo...
UNIV_INLINE bool rw_lock_s_lock_low(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
Low-level function which tries to lock an rw-lock in s-mode.
UNIV_INLINE ulint rw_lock_get_x_lock_count(const rw_lock_t *lock)
Returns the value of writer_count for the lock.
bool rw_lock_own_flagged(const rw_lock_t *lock, rw_lock_flags_t flags)
Checks if the thread has locked the rw-lock in the specified mode, with the pass value == 0.
Definition: sync0rw.cc:937
UNIV_INLINE lint rw_lock_lock_word_incr(rw_lock_t *lock, ulint amount)
Increments lock_word the specified amount and returns new value.
UNIV_INLINE ulint rw_lock_get_reader_count(const rw_lock_t *lock)
Returns the number of readers (s-locks).
UNIV_INLINE void pfs_rw_lock_s_unlock_func(ulint pass, rw_lock_t *lock)
Performance schema instrumented wrap function for rw_lock_s_unlock_func() NOTE! Please use the corres...
UNIV_INLINE ulint rw_lock_get_sx_lock_count(const rw_lock_t *lock)
Returns the number of sx-lock for the lock.
UNIV_INLINE void pfs_rw_lock_x_lock_func(rw_lock_t *lock, ulint pass, const char *file_name, ulint line)
Performance schema instrumented wrap function for rw_lock_x_lock_func() NOTE! Please use the correspo...
void rw_lock_x_lock_move_ownership(rw_lock_t *lock)
This function is used in the insert buffer to move the ownership of an x-latch on a buffer frame to t...
Definition: sync0rw.cc:376
latch_level_t
Latching order levels.
Definition: sync0types.h:217
ulint rw_lock_flags_t
Definition: sync0types.h:1215
Counter utility class.
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:66
Policy based mutexes.
unsigned long id[MAX_DEAD]
Definition: xcom_base.cc:446