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