MySQL 9.1.0
Source Code Documentation
ib0mutex.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2013, 2024, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26*****************************************************************************/
27
28/** @file include/ib0mutex.h
29 Policy based mutexes.
30
31 Created 2013-03-26 Sunny Bains.
32 ***********************************************************************/
33
34#ifndef ib0mutex_h
35#define ib0mutex_h
36
37#include "os0atomic.h"
38#include "os0event.h"
39#include "sync0policy.h"
40#include "ut0rnd.h"
41#include "ut0ut.h"
42
43#include <atomic>
44
45/** OS mutex for tracking lock/unlock for debugging */
46template <template <typename> class Policy = NoPolicy>
48 typedef Policy<OSTrackMutex> MutexPolicy;
49
50 explicit OSTrackMutex(bool destroy_mutex_at_exit = true) UNIV_NOTHROW {
51 ut_d(m_freed = true);
52 ut_d(m_locked = false);
53 ut_d(m_destroy_at_exit = destroy_mutex_at_exit);
54 }
55
57
58 /** Initialise the mutex.
59 @param[in] id Mutex ID
60 @param[in] filename File where mutex was created
61 @param[in] line Line in filename */
62 void init(latch_id_t id, const char *filename, uint32_t line) UNIV_NOTHROW {
65
66 m_mutex.init();
67
68 ut_d(m_freed = false);
69
70 m_policy.init(*this, id, filename, line);
71 }
72
73 /** Destroy the mutex */
77
79
80 ut_d(m_freed = true);
81
82 m_policy.destroy();
83 }
84
85 /** Release the mutex. */
88 ut_d(m_locked = false);
90
91 m_mutex.exit();
92 }
93
94 /** Acquire the mutex.
95 @param[in] max_spins max number of spins
96 @param[in] max_delay max delay per spin
97 @param[in] filename from where called
98 @param[in] line within filename */
99 void enter(uint32_t max_spins [[maybe_unused]],
100 uint32_t max_delay [[maybe_unused]],
101 const char *filename [[maybe_unused]],
102 uint32_t line [[maybe_unused]]) UNIV_NOTHROW {
104
105 m_mutex.enter();
106
107 ut_ad(!m_locked);
108 ut_d(m_locked = true);
109 }
110
111 void lock() { enter(); }
112 void unlock() { exit(); }
113
114 /** @return true if locking succeeded */
117
118 bool locked = m_mutex.try_lock();
119
120 if (locked) {
121 ut_ad(!m_locked);
122 ut_d(m_locked = locked);
123 }
124
125 return (locked);
126 }
127
128#ifdef UNIV_DEBUG
129 /** @return true if the thread owns the mutex. */
130 bool is_owned() const UNIV_NOTHROW {
131 return (m_locked && m_policy.is_owned());
132 }
133#endif /* UNIV_DEBUG */
134
135 /** @return non-const version of the policy */
137
138 /** @return the const version of the policy */
139 const MutexPolicy &policy() const UNIV_NOTHROW { return (m_policy); }
140
141 private:
142#ifdef UNIV_DEBUG
143 /** true if the mutex has not be initialized */
145
146 /** true if the mutex has been locked. */
148
149 /** Do/Dont destroy mutex at exit */
151#endif /* UNIV_DEBUG */
152
153 /** OS Mutex instance */
155
156 /** Policy data */
158};
159
160#ifdef HAVE_IB_LINUX_FUTEX
161
162#include <linux/futex.h>
163#include <sys/syscall.h>
164
165/** Mutex implementation that used the Linux futex. */
166template <template <typename> class Policy = NoPolicy>
167struct TTASFutexMutex {
168 typedef Policy<TTASFutexMutex> MutexPolicy;
169
170 /** The type of second argument to syscall(SYS_futex, uint32_t *uaddr,...)*/
171 using futex_word_t = uint32_t;
172 /** Mutex states. */
173 enum class mutex_state_t : futex_word_t {
174 /** Mutex is free */
175 UNLOCKED = 0,
176
177 /** Mutex is acquired by some thread. */
178 LOCKED = 1,
179
180 /** Mutex is contended and there are threads waiting on the lock. */
181 LOCKED_WITH_WAITERS = 2
182 };
183 using lock_word_t = mutex_state_t;
184
185 TTASFutexMutex() UNIV_NOTHROW : m_lock_word(mutex_state_t::UNLOCKED) {
186 /* The futex API operates on uint32_t futex words, aligned to 4 byte
187 boundaries. OTOH we want the luxury of accessing it via std::atomic<>.
188 Thus we need to verify that std::atomic doesn't add any extra fluff,
189 and is properly aligned */
190 using m_lock_word_t = decltype(m_lock_word);
191 static_assert(m_lock_word_t::is_always_lock_free);
192 static_assert(sizeof(m_lock_word_t) == sizeof(futex_word_t));
193#ifdef UNIV_DEBUG
194 const auto addr = reinterpret_cast<std::uintptr_t>(&m_lock_word);
195 ut_a(addr % alignof(m_lock_word_t) == 0);
196 ut_a(addr % 4 == 0);
197#endif
198 }
199
200 ~TTASFutexMutex() { ut_a(m_lock_word == mutex_state_t::UNLOCKED); }
201
202 /** Called when the mutex is "created". Note: Not from the constructor
203 but when the mutex is initialised.
204 @param[in] id Mutex ID
205 @param[in] filename File where mutex was created
206 @param[in] line Line in filename */
207 void init(latch_id_t id, const char *filename, uint32_t line) UNIV_NOTHROW {
208 ut_a(m_lock_word == mutex_state_t::UNLOCKED);
209 m_policy.init(*this, id, filename, line);
210 }
211
212 /** Destroy the mutex. */
213 void destroy() UNIV_NOTHROW {
214 /* The destructor can be called at shutdown. */
215 ut_a(m_lock_word == mutex_state_t::UNLOCKED);
216 m_policy.destroy();
217 }
218
219 /** Acquire the mutex.
220 @param[in] max_spins max number of spins
221 @param[in] max_delay max delay per spin
222 @param[in] filename from where called
223 @param[in] line within filename */
224 void enter(uint32_t max_spins, uint32_t max_delay, const char *filename,
225 uint32_t line) UNIV_NOTHROW {
226 uint32_t n_spins;
227 lock_word_t lock = ttas(max_spins, max_delay, n_spins);
228
229 /* If there were no waiters when this thread tried
230 to acquire the mutex then set the waiters flag now.
231 Additionally, when this thread set the waiters flag it is
232 possible that the mutex had already been released
233 by then. In this case the thread can assume it
234 was granted the mutex. */
235
236 const uint32_t n_waits = (lock == mutex_state_t::LOCKED_WITH_WAITERS ||
237 (lock == mutex_state_t::LOCKED && !set_waiters()))
238 ? wait()
239 : 0;
240
241 m_policy.add(n_spins, n_waits);
242 }
243
244 /** Release the mutex. */
245 void exit() UNIV_NOTHROW {
246 /* If there are threads waiting then we have to wake
247 them up. Reset the lock state to unlocked so that waiting
248 threads can test for success. */
249
250 std::atomic_thread_fence(std::memory_order_acquire);
251
252 if (state() == mutex_state_t::LOCKED_WITH_WAITERS) {
253 m_lock_word = mutex_state_t::UNLOCKED;
254
255 } else if (unlock() == mutex_state_t::LOCKED) {
256 /* No threads waiting, no need to signal a wakeup. */
257 return;
258 }
259
260 signal();
261 }
262
263 /** Try and lock the mutex.
264 @return the old state of the mutex */
265 lock_word_t trylock() UNIV_NOTHROW {
266 lock_word_t unlocked = mutex_state_t::UNLOCKED;
267 m_lock_word.compare_exchange_strong(unlocked, mutex_state_t::LOCKED);
268 return unlocked;
269 }
270
271 /** Try and lock the mutex.
272 @return true if successful */
273 bool try_lock() UNIV_NOTHROW {
274 lock_word_t unlocked = mutex_state_t::UNLOCKED;
275 return m_lock_word.compare_exchange_strong(unlocked, mutex_state_t::LOCKED);
276 }
277
278 /** @return true if mutex is unlocked */
279 bool is_locked() const UNIV_NOTHROW {
280 return (state() != mutex_state_t::UNLOCKED);
281 }
282
283#ifdef UNIV_DEBUG
284 /** @return true if the thread owns the mutex. */
285 bool is_owned() const UNIV_NOTHROW {
286 return (is_locked() && m_policy.is_owned());
287 }
288#endif /* UNIV_DEBUG */
289
290 /** @return non-const version of the policy */
291 MutexPolicy &policy() UNIV_NOTHROW { return (m_policy); }
292
293 /** @return const version of the policy */
294 const MutexPolicy &policy() const UNIV_NOTHROW { return (m_policy); }
295
296 private:
297 /** @return the lock state. */
298 lock_word_t state() const UNIV_NOTHROW { return (m_lock_word); }
299
300 /** Release the mutex.
301 @return the old state of the mutex */
302 lock_word_t unlock() UNIV_NOTHROW {
303 return m_lock_word.exchange(mutex_state_t::UNLOCKED);
304 }
305
306 /** Note that there are threads waiting and need to be woken up.
307 @return true if state was mutex_state_t::UNLOCKED (ie. granted) */
308 bool set_waiters() UNIV_NOTHROW {
309 return m_lock_word.exchange(mutex_state_t::LOCKED_WITH_WAITERS) ==
310 mutex_state_t::UNLOCKED;
311 }
312
313 /** Wait if the lock is contended.
314 @return the number of waits */
315 uint32_t wait() UNIV_NOTHROW {
316 uint32_t n_waits = 0;
317
318 /* Use FUTEX_WAIT_PRIVATE because our mutexes are
319 not shared between processes. */
320
321 do {
322 ++n_waits;
323
324 syscall(SYS_futex, &m_lock_word, FUTEX_WAIT_PRIVATE,
325 mutex_state_t::LOCKED_WITH_WAITERS, 0, 0, 0);
326
327 // Since we are retrying the operation the return
328 // value doesn't matter.
329
330 } while (!set_waiters());
331
332 return (n_waits);
333 }
334
335 /** Wakeup a waiting thread */
336 void signal() UNIV_NOTHROW {
337 syscall(SYS_futex, &m_lock_word, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0);
338 }
339
340 /** Poll waiting for mutex to be unlocked.
341 @param[in] max_spins max spins
342 @param[in] max_delay max delay per spin
343 @param[out] n_spins retries before acquire
344 @return value of lock word before locking. */
345 lock_word_t ttas(uint32_t max_spins, uint32_t max_delay,
346 uint32_t &n_spins) UNIV_NOTHROW {
347 std::atomic_thread_fence(std::memory_order_acquire);
348
349 for (n_spins = 0; n_spins < max_spins; ++n_spins) {
350 if (!is_locked()) {
351 lock_word_t lock = trylock();
352
353 if (lock == mutex_state_t::UNLOCKED) {
354 /* Lock successful */
355 return (lock);
356 }
357 }
358
360 }
361
362 return (trylock());
363 }
364
365 private:
366 /** Policy data */
367 MutexPolicy m_policy;
368
369 alignas(4) std::atomic<lock_word_t> m_lock_word;
370};
371
372#endif /* HAVE_IB_LINUX_FUTEX */
373
374template <template <typename> class Policy = NoPolicy>
376 typedef Policy<TTASEventMutex> MutexPolicy;
377
379 /* Check that m_owner is aligned. */
380 using m_owner_t = decltype(m_owner);
381 ut_ad(reinterpret_cast<std::uintptr_t>(&m_owner) % alignof(m_owner_t) == 0);
382 static_assert(m_owner_t::is_always_lock_free);
383 }
384
386
387 /** If the lock is locked, returns the current owner of the lock, otherwise
388 returns the default std::thread::id{} */
390
391 /** Called when the mutex is "created". Note: Not from the constructor
392 but when the mutex is initialised.
393 @param[in] id Mutex ID
394 @param[in] filename File where mutex was created
395 @param[in] line Line in filename */
396 void init(latch_id_t id, const char *filename, uint32_t line) UNIV_NOTHROW {
397 ut_a(m_event == nullptr);
398 ut_a(!is_locked());
399
401
402 m_policy.init(*this, id, filename, line);
403 }
404
405 /** This is the real destructor. This mutex can be created in BSS and
406 its destructor will be called on exit(). We can't call
407 os_event_destroy() at that stage. */
409 ut_ad(!is_locked());
410
411 /* We have to free the event before InnoDB shuts down. */
413 m_event = nullptr;
414
415 m_policy.destroy();
416 }
417
418 /** Try and lock the mutex. Note: POSIX returns 0 on success.
419 @return true on success */
421 auto expected = std::thread::id{};
422 return m_owner.compare_exchange_strong(expected,
424 }
425
426 /** Release the mutex. */
428 m_owner.store(std::thread::id{});
429
430 if (m_waiters.load()) {
431 signal();
432 }
433 }
434
435 /** Acquire the mutex.
436 @param[in] max_spins max number of spins
437 @param[in] max_delay max delay per spin
438 @param[in] filename from where called
439 @param[in] line within filename */
440 void enter(uint32_t max_spins, uint32_t max_delay, const char *filename,
441 uint32_t line) UNIV_NOTHROW {
442 if (!try_lock()) {
443 spin_and_try_lock(max_spins, max_delay, filename, line);
444 }
445 }
446
447 /** The event that the mutex will wait in sync0arr.cc
448 @return even instance */
450
451 /** @return true if locked by some thread */
452 bool is_locked() const UNIV_NOTHROW {
453 return peek_owner() != std::thread::id{};
454 }
455
456 /** @return true if the calling thread owns the mutex. */
457 bool is_owned() const UNIV_NOTHROW {
459 }
460
461 /** @return non-const version of the policy */
463
464 /** @return const version of the policy */
465 const MutexPolicy &policy() const UNIV_NOTHROW { return (m_policy); }
466
467 private:
468 /** Wait in the sync array.
469 @param[in] filename from where it was called
470 @param[in] line line number in file
471 @param[in] spin retry this many times again
472 @return true if the mutex acquisition was successful. */
473 bool wait(const char *filename, uint32_t line, uint32_t spin) UNIV_NOTHROW;
474
475 /** Spin and wait for the mutex to become free.
476 @param[in] max_spins max spins
477 @param[in] max_delay max delay per spin
478 @param[in,out] n_spins spin start index
479 @return true if unlocked */
480 bool is_free(uint32_t max_spins, uint32_t max_delay,
481 uint32_t &n_spins) const UNIV_NOTHROW {
482 ut_ad(n_spins <= max_spins);
483
484 /* Spin waiting for the lock word to become zero. Note
485 that we do not have to assume that the read access to
486 the lock word is atomic, as the actual locking is always
487 committed with atomic test-and-set. In reality, however,
488 all processors probably have an atomic read of a memory word. */
489
490 do {
491 if (!is_locked()) {
492 return (true);
493 }
494
496
497 ++n_spins;
498
499 } while (n_spins < max_spins);
500
501 return (false);
502 }
503
504 /** Spin while trying to acquire the mutex
505 @param[in] max_spins max number of spins
506 @param[in] max_delay max delay per spin
507 @param[in] filename from where called
508 @param[in] line within filename */
509 void spin_and_try_lock(uint32_t max_spins, uint32_t max_delay,
510 const char *filename, uint32_t line) UNIV_NOTHROW {
511 uint32_t n_spins = 0;
512 uint32_t n_waits = 0;
513 const uint32_t step = max_spins;
514
515 for (;;) {
516 /* If the lock was free then try and acquire it. */
517
518 if (is_free(max_spins, max_delay, n_spins)) {
519 if (try_lock()) {
520 break;
521 } else {
522 continue;
523 }
524
525 } else {
526 max_spins = n_spins + step;
527 }
528
529 ++n_waits;
530
531 std::this_thread::yield();
532
533 /* The 4 below is a heuristic that has existed for a
534 very long time now. It is unclear if changing this
535 value will make a difference.
536
537 NOTE: There is a delay that happens before the retry,
538 finding a free slot in the sync arary and the yield
539 above. Otherwise we could have simply done the extra
540 spin above. */
541
542 if (wait(filename, line, 4)) {
543 n_spins += 4;
544
545 break;
546 }
547 }
548
549 /* Waits and yields will be the same number in our
550 mutex design */
551
552 m_policy.add(n_spins, n_waits);
553 }
554
555 /** Note that there are threads waiting on the mutex */
556 void set_waiters() UNIV_NOTHROW { m_waiters.store(true); }
557
558 /** Note that there are no threads waiting on the mutex */
559 void clear_waiters() UNIV_NOTHROW { m_waiters.store(false); }
560
561 /** Wakeup any waiting thread(s). */
562 void signal() UNIV_NOTHROW;
563
564 private:
565 /** Disable copying */
568 TTASEventMutex &operator=(TTASEventMutex &&) = delete;
569 TTASEventMutex &operator=(const TTASEventMutex &) = delete;
570
571 /** Set to owner's thread's id when locked, and reset to the default
572 std::thread::id{} when unlocked. */
573 std::atomic<std::thread::id> m_owner{std::thread::id{}};
574
575 /** Used by sync0arr.cc for the wait queue */
577
578 /** Policy data */
580
581 /** true if there are (or may be) threads waiting
582 in the global wait array for this mutex to be released. */
583 std::atomic_bool m_waiters{false};
584};
585
586/** Mutex interface for all policy mutexes. This class handles the interfacing
587with the Performance Schema instrumentation. */
588template <typename MutexImpl>
590 typedef MutexImpl MutexType;
591 typedef typename MutexImpl::MutexPolicy Policy;
592
594#ifdef UNIV_PFS_MUTEX
595 m_ptr = nullptr;
596#endif /* UNIV_PFS_MUTEX */
597 }
598
599 ~PolicyMutex() = default;
600
601 /** @return non-const version of the policy */
602 Policy &policy() UNIV_NOTHROW { return (m_impl.policy()); }
603
604 /** @return const version of the policy */
605 const Policy &policy() const UNIV_NOTHROW { return (m_impl.policy()); }
606
607 /** Release the mutex. */
609#ifdef UNIV_PFS_MUTEX
610 pfs_exit();
611#endif /* UNIV_PFS_MUTEX */
612
613 policy().release(m_impl);
614
615 m_impl.exit();
616 }
617
618 /** Acquire the mutex.
619 @param n_spins max number of spins
620 @param n_delay max delay per spin
621 @param name filename where locked
622 @param line line number where locked */
623 void enter(uint32_t n_spins, uint32_t n_delay, const char *name,
624 uint32_t line) UNIV_NOTHROW {
625#ifdef UNIV_PFS_MUTEX
626 /* Note: locker is really an alias for state. That's why
627 it has to be in the same scope during pfs_end(). */
628
630 PSI_mutex_locker *locker;
631
632 locker = pfs_begin_lock(&state, name, line);
633#endif /* UNIV_PFS_MUTEX */
634
635 policy().enter(m_impl, name, line);
636
637 m_impl.enter(n_spins, n_delay, name, line);
638
639 policy().locked(m_impl, name, line);
640#ifdef UNIV_PFS_MUTEX
641 pfs_end(locker, 0);
642#endif /* UNIV_PFS_MUTEX */
643 }
644
645 /** Try and lock the mutex, return 0 on SUCCESS and 1 otherwise.
646 @param name filename where locked
647 @param line line number where locked */
648 int trylock(const char *name, uint32_t line) UNIV_NOTHROW {
649#ifdef UNIV_PFS_MUTEX
650 /* Note: locker is really an alias for state. That's why
651 it has to be in the same scope during pfs_end(). */
652
654 PSI_mutex_locker *locker;
655
656 locker = pfs_begin_trylock(&state, name, line);
657#endif /* UNIV_PFS_MUTEX */
658
659 /* There is a subtlety here, we check the mutex ordering
660 after locking here. This is only done to avoid add and
661 then remove if the trylock was unsuccessful. */
662
663 int ret = m_impl.try_lock() ? 0 : 1;
664
665 if (ret == 0) {
666 policy().enter(m_impl, name, line);
667
668 policy().locked(m_impl, name, line);
669 }
670
671#ifdef UNIV_PFS_MUTEX
672 pfs_end(locker, ret);
673#endif /* UNIV_PFS_MUTEX */
674
675 return (ret);
676 }
677
678#ifdef UNIV_DEBUG
679 /** @return true if the thread owns the mutex. */
680 bool is_owned() const UNIV_NOTHROW { return (m_impl.is_owned()); }
681#endif /* UNIV_DEBUG */
682
683 /**
684 Initialise the mutex.
685
686 @param[in] id Mutex ID
687 @param[in] filename file where created
688 @param[in] line line number in file where created */
689 void init(latch_id_t id, const char *filename, uint32_t line) UNIV_NOTHROW {
690#ifdef UNIV_PFS_MUTEX
692#endif /* UNIV_PFS_MUTEX */
693
694 m_impl.init(id, filename, line);
695 }
696
697 /** Free resources (if any) */
699#ifdef UNIV_PFS_MUTEX
700 pfs_del();
701#endif /* UNIV_PFS_MUTEX */
702 m_impl.destroy();
703 }
704
705 /** Required for os_event_t */
707 return (m_impl.operator sys_mutex_t *());
708 }
709
710#ifdef UNIV_PFS_MUTEX
711 /** Performance schema monitoring - register mutex with PFS.
712
713 Note: This is public only because we want to get around an issue
714 with registering a subset of buffer pool pages with PFS when
715 PFS_GROUP_BUFFER_SYNC is defined. Therefore this has to then
716 be called by external code (see buf0buf.cc).
717
718 @param key - Performance Schema key. */
720 ut_ad(m_ptr == nullptr);
721 m_ptr = PSI_MUTEX_CALL(init_mutex)(key.m_value, this);
722 }
723
724 private:
725 /** Performance schema monitoring.
726 @param state - PFS locker state
727 @param name - file name where locked
728 @param line - line number in file where locked */
730 const char *name,
731 uint32_t line) UNIV_NOTHROW {
732 if (m_ptr != nullptr) {
733 if (m_ptr->m_enabled) {
734 return (PSI_MUTEX_CALL(start_mutex_wait)(state, m_ptr, PSI_MUTEX_LOCK,
735 name, (uint)line));
736 }
737 }
738
739 return (nullptr);
740 }
741
742 /** Performance schema monitoring.
743 @param state - PFS locker state
744 @param name - file name where locked
745 @param line - line number in file where locked */
747 const char *name,
748 uint32_t line) UNIV_NOTHROW {
749 if (m_ptr != nullptr) {
750 if (m_ptr->m_enabled) {
751 return (PSI_MUTEX_CALL(start_mutex_wait)(
752 state, m_ptr, PSI_MUTEX_TRYLOCK, name, (uint)line));
753 }
754 }
755
756 return (nullptr);
757 }
758
759 /** Performance schema monitoring
760 @param locker - PFS identifier
761 @param ret - 0 for success and 1 for failure */
762 void pfs_end(PSI_mutex_locker *locker, int ret) UNIV_NOTHROW {
763 if (locker != nullptr) {
764 PSI_MUTEX_CALL(end_mutex_wait)(locker, ret);
765 }
766 }
767
768 /** Performance schema monitoring - register mutex release */
769 void pfs_exit() {
770 if (m_ptr != nullptr) {
771 if (m_ptr->m_enabled) {
772 PSI_MUTEX_CALL(unlock_mutex)(m_ptr);
773 }
774 }
775 }
776
777 /** Performance schema monitoring - deregister */
778 void pfs_del() {
779 if (m_ptr != nullptr) {
781 m_ptr = nullptr;
782 }
783 }
784#endif /* UNIV_PFS_MUTEX */
785
786 private:
787 /** The mutex implementation */
788 MutexImpl m_impl;
789
790#ifdef UNIV_PFS_MUTEX
791 /** The performance schema instrumentation hook. */
793#endif /* UNIV_PFS_MUTEX */
794};
795
796#endif /* ib0mutex_h */
static mysql_service_status_t init()
Component initialization.
Definition: audit_api_message_emit.cc:571
int destroy(azio_stream *s)
Definition: azio.cc:371
#define PSI_MUTEX_CALL(M)
Definition: psi_mutex.h:36
void destroy_mutex(PFS_mutex *pfs)
Destroy instrumentation for a mutex instance.
Definition: pfs_instr.cc:381
struct PSI_mutex_locker PSI_mutex_locker
Definition: psi_mutex_bits.h:105
@ PSI_MUTEX_TRYLOCK
Lock attempt.
Definition: psi_mutex_bits.h:112
@ PSI_MUTEX_LOCK
Lock.
Definition: psi_mutex_bits.h:110
#define exit(A)
Definition: lexyy.cc:917
native_mutex_t init_mutex
Definition: mysqlimport.cc:59
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:79
static int signal(mysql_cond_t *that, const char *, unsigned int)
Definition: mysql_cond_v1_native.cc:90
static int wait(mysql_cond_t *that, mysql_mutex_t *mutex_arg, const char *, unsigned int)
Definition: mysql_cond_v1_native.cc:63
Definition: gcs_xcom_synode.h:64
pid_type get_id()
Definition: process.h:48
static uint64_t random_from_interval_fast(uint64_t low, uint64_t high)
Generates a light-weight pseudo-random integer from a given interval.
Definition: ut0rnd.h:185
Macros for using atomics.
The interface to the operating system condition variables.
os_event_t os_event_create()
Creates an event semaphore, i.e., a semaphore which may just have two states: signaled and nonsignale...
Definition: os0event.cc:528
void os_event_destroy(os_event_t &event)
Frees an event object.
Definition: os0event.cc:595
const char * filename
Definition: pfs_example_component_population.cc:67
required string key
Definition: replication_asynchronous_connection_failover.proto:60
case opt name
Definition: sslopt-case.h:29
Definition: sync0policy.h:199
OS mutex, without any policy.
Definition: sync0types.h:476
void exit() 1
Release the mutex.
Definition: sync0types.h:522
bool try_lock() 1
Definition: sync0types.h:547
void enter() 1
Acquire the mutex.
Definition: sync0types.h:533
void init() 1
Create the mutex by calling the system functions.
Definition: sync0types.h:481
void destroy() 1
Destroy the mutex.
Definition: sync0types.h:500
OS mutex for tracking lock/unlock for debugging.
Definition: ib0mutex.h:47
bool is_owned() const 1
Definition: ib0mutex.h:130
void exit() 1
Release the mutex.
Definition: ib0mutex.h:86
void init(latch_id_t id, const char *filename, uint32_t line) 1
Initialise the mutex.
Definition: ib0mutex.h:62
bool m_freed
true if the mutex has not be initialized
Definition: ib0mutex.h:144
const MutexPolicy & policy() const 1
Definition: ib0mutex.h:139
void enter(uint32_t max_spins, uint32_t max_delay, const char *filename, uint32_t line) 1
Acquire the mutex.
Definition: ib0mutex.h:99
bool m_locked
true if the mutex has been locked.
Definition: ib0mutex.h:147
MutexPolicy m_policy
Policy data.
Definition: ib0mutex.h:157
void lock()
Definition: ib0mutex.h:111
~OSTrackMutex() 1
Definition: ib0mutex.h:56
MutexPolicy & policy() 1
Definition: ib0mutex.h:136
OSMutex m_mutex
OS Mutex instance.
Definition: ib0mutex.h:154
bool try_lock() 1
Definition: ib0mutex.h:115
Policy< OSTrackMutex > MutexPolicy
Definition: ib0mutex.h:48
void destroy() 1
Destroy the mutex.
Definition: ib0mutex.h:74
bool m_destroy_at_exit
Do/Dont destroy mutex at exit.
Definition: ib0mutex.h:150
OSTrackMutex(bool destroy_mutex_at_exit=true) 1
Definition: ib0mutex.h:50
void unlock()
Definition: ib0mutex.h:112
bool m_enabled
Instrumentation is enabled.
Definition: psi_bits.h:191
State data storage for start_mutex_wait_v1_t.
Definition: psi_mutex_bits.h:125
Interface for an instrumented mutex.
Definition: psi_mutex_bits.h:97
Mutex interface for all policy mutexes.
Definition: ib0mutex.h:589
void destroy() 1
Free resources (if any)
Definition: ib0mutex.h:698
MutexImpl m_impl
The mutex implementation.
Definition: ib0mutex.h:788
PolicyMutex() 1
Definition: ib0mutex.h:593
PSI_mutex * m_ptr
The performance schema instrumentation hook.
Definition: ib0mutex.h:792
~PolicyMutex()=default
MutexImpl::MutexPolicy Policy
Definition: ib0mutex.h:591
const Policy & policy() const 1
Definition: ib0mutex.h:605
void enter(uint32_t n_spins, uint32_t n_delay, const char *name, uint32_t line) 1
Acquire the mutex.
Definition: ib0mutex.h:623
bool is_owned() const 1
Definition: ib0mutex.h:680
PSI_mutex_locker * pfs_begin_trylock(PSI_mutex_locker_state *state, const char *name, uint32_t line) 1
Performance schema monitoring.
Definition: ib0mutex.h:746
PSI_mutex_locker * pfs_begin_lock(PSI_mutex_locker_state *state, const char *name, uint32_t line) 1
Performance schema monitoring.
Definition: ib0mutex.h:729
void pfs_del()
Performance schema monitoring - deregister.
Definition: ib0mutex.h:778
void pfs_exit()
Performance schema monitoring - register mutex release.
Definition: ib0mutex.h:769
Policy & policy() 1
Definition: ib0mutex.h:602
void init(latch_id_t id, const char *filename, uint32_t line) 1
Initialise the mutex.
Definition: ib0mutex.h:689
int trylock(const char *name, uint32_t line) 1
Try and lock the mutex, return 0 on SUCCESS and 1 otherwise.
Definition: ib0mutex.h:648
void pfs_end(PSI_mutex_locker *locker, int ret) 1
Performance schema monitoring.
Definition: ib0mutex.h:762
void pfs_add(mysql_pfs_key_t key) 1
Performance schema monitoring - register mutex with PFS.
Definition: ib0mutex.h:719
void exit() 1
Release the mutex.
Definition: ib0mutex.h:608
MutexImpl MutexType
Definition: ib0mutex.h:590
Definition: ib0mutex.h:375
void set_waiters() 1
Note that there are threads waiting on the mutex.
Definition: ib0mutex.h:556
void signal() 1
Wakeup any waiting thread(s).
Definition: ut0mutex.ic:219
os_event_t event() 1
The event that the mutex will wait in sync0arr.cc.
Definition: ib0mutex.h:449
os_event_t m_event
Used by sync0arr.cc for the wait queue.
Definition: ib0mutex.h:576
std::thread::id peek_owner() const 1
If the lock is locked, returns the current owner of the lock, otherwise returns the default std::thre...
Definition: ib0mutex.h:389
void destroy() 1
This is the real destructor.
Definition: ib0mutex.h:408
void enter(uint32_t max_spins, uint32_t max_delay, const char *filename, uint32_t line) 1
Acquire the mutex.
Definition: ib0mutex.h:440
void init(latch_id_t id, const char *filename, uint32_t line) 1
Called when the mutex is "created".
Definition: ib0mutex.h:396
MutexPolicy & policy() 1
Definition: ib0mutex.h:462
~TTASEventMutex() 1
Definition: ib0mutex.h:385
bool is_locked() const 1
Definition: ib0mutex.h:452
MutexPolicy m_policy
Policy data.
Definition: ib0mutex.h:579
bool try_lock() 1
Try and lock the mutex.
Definition: ib0mutex.h:420
void exit() 1
Release the mutex.
Definition: ib0mutex.h:427
std::atomic_bool m_waiters
true if there are (or may be) threads waiting in the global wait array for this mutex to be released.
Definition: ib0mutex.h:583
bool is_free(uint32_t max_spins, uint32_t max_delay, uint32_t &n_spins) const 1
Spin and wait for the mutex to become free.
Definition: ib0mutex.h:480
const MutexPolicy & policy() const 1
Definition: ib0mutex.h:465
void spin_and_try_lock(uint32_t max_spins, uint32_t max_delay, const char *filename, uint32_t line) 1
Spin while trying to acquire the mutex.
Definition: ib0mutex.h:509
void clear_waiters() 1
Note that there are no threads waiting on the mutex.
Definition: ib0mutex.h:559
Policy< TTASEventMutex > MutexPolicy
Definition: ib0mutex.h:376
TTASEventMutex() 1
Definition: ib0mutex.h:378
std::atomic< std::thread::id > m_owner
Set to owner's thread's id when locked, and reset to the default std::thread::id{} when unlocked.
Definition: ib0mutex.h:573
bool is_owned() const 1
Definition: ib0mutex.h:457
bool wait(const char *filename, uint32_t line, uint32_t spin) 1
Wait in the sync array.
Definition: ut0mutex.ic:48
Define for performance schema registration key.
Definition: sync0sync.h:51
InnoDB condition variable.
Definition: os0event.cc:63
Policies for mutexes.
pthread_mutex_t sys_mutex_t
Native mutex.
Definition: sync0types.h:56
latch_id_t
Each latch has an ID.
Definition: sync0types.h:345
mysql_pfs_key_t sync_latch_get_pfs_key(latch_id_t id)
Get the latch PFS key from the latch ID.
Definition: sync0types.h:924
bool innodb_calling_exit
Set when InnoDB has invoked exit().
Definition: srv0srv.cc:228
int is_locked(int fd)
#define UNIV_NOTHROW
Definition: univ.i:456
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:105
#define ut_d(EXPR)
Debug statement.
Definition: ut0dbg.h:107
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:93
Random numbers and hashing.
Various utilities.
ulint ut_delay(ulint delay)
Runs an idle loop on CPU.
Definition: ut0ut.cc:99
unsigned long id[MAX_DEAD]
Definition: xcom_base.cc:510