1 /*****************************************************************************
2
3 Copyright (c) 1995, 2021, Oracle and/or its affiliates.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation. The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License, version 2.0, for more details.
20
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24
25 *****************************************************************************/
26
27 /**************************************************//**
28 @file include/sync0types.h
29 Global types for sync
30
31 Created 9/5/1995 Heikki Tuuri
32 *******************************************************/
33
34 #ifndef sync0types_h
35 #define sync0types_h
36
37 #include <vector>
38 #include <iostream>
39
40 #include "ut0new.h"
41 #include "ut0counter.h"
42
43 #if defined(UNIV_DEBUG) && !defined(UNIV_INNOCHECKSUM)
44 /** Set when InnoDB has invoked exit(). */
45 extern bool innodb_calling_exit;
46 #endif /* UNIV_DEBUG && !UNIV_INNOCHECKSUM */
47
48 #ifdef _WIN32
49 /** Native mutex */
50 typedef CRITICAL_SECTION sys_mutex_t;
51 #else
52 /** Native mutex */
53 typedef pthread_mutex_t sys_mutex_t;
54 #endif /* _WIN32 */
55
56 /** The new (C++11) syntax allows the following and we should use it when it
57 is available on platforms that we support.
58
59 enum class mutex_state_t : lock_word_t { ... };
60 */
61
62 /** Mutex states. */
63 enum mutex_state_t {
64 /** Mutex is free */
65 MUTEX_STATE_UNLOCKED = 0,
66
67 /** Mutex is acquired by some thread. */
68 MUTEX_STATE_LOCKED = 1,
69
70 /** Mutex is contended and there are threads waiting on the lock. */
71 MUTEX_STATE_WAITERS = 2
72 };
73
74 /*
75 LATCHING ORDER WITHIN THE DATABASE
76 ==================================
77
78 The mutex or latch in the central memory object, for instance, a rollback
79 segment object, must be acquired before acquiring the latch or latches to
80 the corresponding file data structure. In the latching order below, these
81 file page object latches are placed immediately below the corresponding
82 central memory object latch or mutex.
83
84 Synchronization object Notes
85 ---------------------- -----
86
87 Dictionary mutex If we have a pointer to a dictionary
88 | object, e.g., a table, it can be
89 | accessed without reserving the
90 | dictionary mutex. We must have a
91 | reservation, a memoryfix, to the
92 | appropriate table object in this case,
93 | and the table must be explicitly
94 | released later.
95 V
96 Dictionary header
97 |
98 V
99 Secondary index tree latch The tree latch protects also all
100 | the B-tree non-leaf pages. These
101 V can be read with the page only
102 Secondary index non-leaf bufferfixed to save CPU time,
103 | no s-latch is needed on the page.
104 | Modification of a page requires an
105 | x-latch on the page, however. If a
106 | thread owns an x-latch to the tree,
107 | it is allowed to latch non-leaf pages
108 | even after it has acquired the fsp
109 | latch.
110 V
111 Secondary index leaf The latch on the secondary index leaf
112 | can be kept while accessing the
113 | clustered index, to save CPU time.
114 V
115 Clustered index tree latch To increase concurrency, the tree
116 | latch is usually released when the
117 | leaf page latch has been acquired.
118 V
119 Clustered index non-leaf
120 |
121 V
122 Clustered index leaf
123 |
124 V
125 Transaction system header
126 |
127 V
128 Transaction undo mutex The undo log entry must be written
129 | before any index page is modified.
130 | Transaction undo mutex is for the undo
131 | logs the analogue of the tree latch
132 | for a B-tree. If a thread has the
133 | trx undo mutex reserved, it is allowed
134 | to latch the undo log pages in any
135 | order, and also after it has acquired
136 | the fsp latch.
137 V
138 Rollback segment mutex The rollback segment mutex must be
139 | reserved, if, e.g., a new page must
140 | be added to an undo log. The rollback
141 | segment and the undo logs in its
142 | history list can be seen as an
143 | analogue of a B-tree, and the latches
144 | reserved similarly, using a version of
145 | lock-coupling. If an undo log must be
146 | extended by a page when inserting an
147 | undo log record, this corresponds to
148 | a pessimistic insert in a B-tree.
149 V
150 Rollback segment header
151 |
152 V
153 Purge system latch
154 |
155 V
156 Undo log pages If a thread owns the trx undo mutex,
157 | or for a log in the history list, the
158 | rseg mutex, it is allowed to latch
159 | undo log pages in any order, and even
160 | after it has acquired the fsp latch.
161 | If a thread does not have the
162 | appropriate mutex, it is allowed to
163 | latch only a single undo log page in
164 | a mini-transaction.
165 V
166 File space management latch If a mini-transaction must allocate
167 | several file pages, it can do that,
168 | because it keeps the x-latch to the
169 | file space management in its memo.
170 V
171 File system pages
172 |
173 V
174 lock_sys_wait_mutex Mutex protecting lock timeout data
175 |
176 V
177 lock_sys_mutex Mutex protecting lock_sys_t
178 |
179 V
180 trx_sys->mutex Mutex protecting trx_sys_t
181 |
182 V
183 Threads mutex Background thread scheduling mutex
184 |
185 V
186 query_thr_mutex Mutex protecting query threads
187 |
188 V
189 trx_mutex Mutex protecting trx_t fields
190 |
191 V
192 Search system mutex
193 |
194 V
195 Buffer pool mutex
196 |
197 V
198 Log mutex
199 |
200 Any other latch
201 |
202 V
203 Memory pool mutex */
204
205 /** Latching order levels. If you modify these, you have to also update
206 LatchDebug internals in sync0debug.cc */
207
208 enum latch_level_t {
209 SYNC_UNKNOWN = 0,
210
211 SYNC_MUTEX = 1,
212
213 RW_LOCK_SX,
214 RW_LOCK_X_WAIT,
215 RW_LOCK_S,
216 RW_LOCK_X,
217 RW_LOCK_NOT_LOCKED,
218
219 SYNC_MONITOR_MUTEX,
220
221 SYNC_ANY_LATCH,
222
223 SYNC_DOUBLEWRITE,
224
225 SYNC_BUF_FLUSH_LIST,
226
227 SYNC_BUF_BLOCK,
228 SYNC_BUF_PAGE_HASH,
229
230 SYNC_BUF_POOL,
231
232 SYNC_POOL,
233 SYNC_POOL_MANAGER,
234
235 SYNC_SEARCH_SYS,
236
237 SYNC_WORK_QUEUE,
238
239 SYNC_FTS_TOKENIZE,
240 SYNC_FTS_OPTIMIZE,
241 SYNC_FTS_BG_THREADS,
242 SYNC_FTS_CACHE_INIT,
243 SYNC_RECV,
244 SYNC_LOG_FLUSH_ORDER,
245 SYNC_LOG,
246 SYNC_LOG_WRITE,
247 SYNC_PAGE_CLEANER,
248 SYNC_PURGE_QUEUE,
249 SYNC_TRX_SYS_HEADER,
250 SYNC_REC_LOCK,
251 SYNC_THREADS,
252 SYNC_TRX,
253 SYNC_TRX_SYS,
254 SYNC_LOCK_SYS,
255 SYNC_LOCK_WAIT_SYS,
256
257 SYNC_INDEX_ONLINE_LOG,
258
259 SYNC_IBUF_BITMAP,
260 SYNC_IBUF_BITMAP_MUTEX,
261 SYNC_IBUF_TREE_NODE,
262 SYNC_IBUF_TREE_NODE_NEW,
263 SYNC_IBUF_INDEX_TREE,
264
265 SYNC_IBUF_MUTEX,
266
267 SYNC_FSP_PAGE,
268 SYNC_FSP,
269 SYNC_EXTERN_STORAGE,
270 SYNC_TRX_UNDO_PAGE,
271 SYNC_RSEG_HEADER,
272 SYNC_RSEG_HEADER_NEW,
273 SYNC_NOREDO_RSEG,
274 SYNC_REDO_RSEG,
275 SYNC_TRX_UNDO,
276 SYNC_PURGE_LATCH,
277 SYNC_TREE_NODE,
278 SYNC_TREE_NODE_FROM_HASH,
279 SYNC_TREE_NODE_NEW,
280 SYNC_INDEX_TREE,
281 SYNC_ANALYZE_INDEX,
282
283 SYNC_IBUF_PESS_INSERT_MUTEX,
284 SYNC_IBUF_HEADER,
285 SYNC_DICT_HEADER,
286 SYNC_STATS_AUTO_RECALC,
287 SYNC_DICT_AUTOINC_MUTEX,
288 SYNC_DICT,
289 SYNC_FTS_CACHE,
290
291 SYNC_DICT_OPERATION,
292
293 SYNC_FILE_FORMAT_TAG,
294
295 SYNC_TRX_I_S_LAST_READ,
296
297 SYNC_TRX_I_S_RWLOCK,
298
299 SYNC_RECV_WRITER,
300
301 /** Level is varying. Only used with buffer pool page locks, which
302 do not have a fixed level, but instead have their level set after
303 the page is locked; see e.g. ibuf_bitmap_get_map_page(). */
304
305 SYNC_LEVEL_VARYING,
306
307 /** This can be used to suppress order checking. */
308 SYNC_NO_ORDER_CHECK,
309
310 /** Maximum level value */
311 SYNC_LEVEL_MAX = SYNC_NO_ORDER_CHECK
312 };
313
314 /** Each latch has an ID. This id is used for creating the latch and to look
315 up its meta-data. See sync0debug.c. */
316 enum latch_id_t {
317 LATCH_ID_NONE = 0,
318 LATCH_ID_AUTOINC,
319 LATCH_ID_BUF_BLOCK_MUTEX,
320 LATCH_ID_BUF_POOL,
321 LATCH_ID_BUF_POOL_ZIP,
322 LATCH_ID_CACHE_LAST_READ,
323 LATCH_ID_DICT_FOREIGN_ERR,
324 LATCH_ID_DICT_SYS,
325 LATCH_ID_FILE_FORMAT_MAX,
326 LATCH_ID_FIL_SYSTEM,
327 LATCH_ID_FLUSH_LIST,
328 LATCH_ID_FTS_BG_THREADS,
329 LATCH_ID_FTS_DELETE,
330 LATCH_ID_FTS_OPTIMIZE,
331 LATCH_ID_FTS_DOC_ID,
332 LATCH_ID_FTS_PLL_TOKENIZE,
333 LATCH_ID_HASH_TABLE_MUTEX,
334 LATCH_ID_IBUF_BITMAP,
335 LATCH_ID_IBUF,
336 LATCH_ID_IBUF_PESSIMISTIC_INSERT,
337 LATCH_ID_LOG_SYS,
338 LATCH_ID_LOG_WRITE,
339 LATCH_ID_LOG_FLUSH_ORDER,
340 LATCH_ID_LIST,
341 LATCH_ID_MUTEX_LIST,
342 LATCH_ID_PAGE_CLEANER,
343 LATCH_ID_PURGE_SYS_PQ,
344 LATCH_ID_RECALC_POOL,
345 LATCH_ID_RECV_SYS,
346 LATCH_ID_RECV_WRITER,
347 LATCH_ID_REDO_RSEG,
348 LATCH_ID_NOREDO_RSEG,
349 LATCH_ID_RW_LOCK_DEBUG,
350 LATCH_ID_RTR_SSN_MUTEX,
351 LATCH_ID_RTR_ACTIVE_MUTEX,
352 LATCH_ID_RTR_MATCH_MUTEX,
353 LATCH_ID_RTR_PATH_MUTEX,
354 LATCH_ID_RW_LOCK_LIST,
355 LATCH_ID_RW_LOCK_MUTEX,
356 LATCH_ID_SRV_DICT_TMPFILE,
357 LATCH_ID_SRV_INNODB_MONITOR,
358 LATCH_ID_SRV_MISC_TMPFILE,
359 LATCH_ID_SRV_MONITOR_FILE,
360 LATCH_ID_SYNC_THREAD,
361 LATCH_ID_BUF_DBLWR,
362 LATCH_ID_TRX_UNDO,
363 LATCH_ID_TRX_POOL,
364 LATCH_ID_TRX_POOL_MANAGER,
365 LATCH_ID_TRX,
366 LATCH_ID_LOCK_SYS,
367 LATCH_ID_LOCK_SYS_WAIT,
368 LATCH_ID_TRX_SYS,
369 LATCH_ID_SRV_SYS,
370 LATCH_ID_SRV_SYS_TASKS,
371 LATCH_ID_PAGE_ZIP_STAT_PER_INDEX,
372 LATCH_ID_EVENT_MANAGER,
373 LATCH_ID_EVENT_MUTEX,
374 LATCH_ID_SYNC_ARRAY_MUTEX,
375 LATCH_ID_THREAD_MUTEX,
376 LATCH_ID_ZIP_PAD_MUTEX,
377 LATCH_ID_OS_AIO_READ_MUTEX,
378 LATCH_ID_OS_AIO_WRITE_MUTEX,
379 LATCH_ID_OS_AIO_LOG_MUTEX,
380 LATCH_ID_OS_AIO_IBUF_MUTEX,
381 LATCH_ID_OS_AIO_SYNC_MUTEX,
382 LATCH_ID_ROW_DROP_LIST,
383 LATCH_ID_INDEX_ONLINE_LOG,
384 LATCH_ID_WORK_QUEUE,
385 LATCH_ID_BTR_SEARCH,
386 LATCH_ID_BUF_BLOCK_LOCK,
387 LATCH_ID_BUF_BLOCK_DEBUG,
388 LATCH_ID_DICT_OPERATION,
389 LATCH_ID_CHECKPOINT,
390 LATCH_ID_FIL_SPACE,
391 LATCH_ID_FTS_CACHE,
392 LATCH_ID_FTS_CACHE_INIT,
393 LATCH_ID_TRX_I_S_CACHE,
394 LATCH_ID_TRX_PURGE,
395 LATCH_ID_IBUF_INDEX_TREE,
396 LATCH_ID_INDEX_TREE,
397 LATCH_ID_DICT_TABLE_STATS,
398 LATCH_ID_HASH_TABLE_RW_LOCK,
399 LATCH_ID_BUF_CHUNK_MAP_LATCH,
400 LATCH_ID_SYNC_DEBUG_MUTEX,
401 LATCH_ID_MASTER_KEY_ID_MUTEX,
402 LATCH_ID_ANALYZE_INDEX_MUTEX,
403 LATCH_ID_TEST_MUTEX,
404 LATCH_ID_MAX = LATCH_ID_TEST_MUTEX
405 };
406
407 #ifndef UNIV_INNOCHECKSUM
408 /** OS mutex, without any policy. It is a thin wrapper around the
409 system mutexes. The interface is different from the policy mutexes,
410 to ensure that it is called directly and not confused with the
411 policy mutexes. */
412 struct OSMutex {
413
414 /** Constructor */
OSMutexOSMutex415 OSMutex()
416 UNIV_NOTHROW
417 {
418 ut_d(m_freed = true);
419 }
420
421 /** Create the mutex by calling the system functions. */
initOSMutex422 void init()
423 UNIV_NOTHROW
424 {
425 ut_ad(m_freed);
426
427 #ifdef _WIN32
428 InitializeCriticalSection((LPCRITICAL_SECTION) &m_mutex);
429 #else
430 {
431 int ret = pthread_mutex_init(&m_mutex, NULL);
432 ut_a(ret == 0);
433 }
434 #endif /* _WIN32 */
435
436 ut_d(m_freed = false);
437 }
438
439 /** Destructor */
~OSMutexOSMutex440 ~OSMutex() { }
441
442 /** Destroy the mutex */
destroyOSMutex443 void destroy()
444 UNIV_NOTHROW
445 {
446 ut_ad(innodb_calling_exit || !m_freed);
447 #ifdef _WIN32
448 DeleteCriticalSection((LPCRITICAL_SECTION) &m_mutex);
449 #else
450 int ret;
451
452 ret = pthread_mutex_destroy(&m_mutex);
453
454 if (ret != 0) {
455
456 ib::error()
457 << "Return value " << ret << " when calling "
458 << "pthread_mutex_destroy().";
459 }
460 #endif /* _WIN32 */
461 ut_d(m_freed = true);
462 }
463
464 /** Release the mutex. */
exitOSMutex465 void exit()
466 UNIV_NOTHROW
467 {
468 ut_ad(innodb_calling_exit || !m_freed);
469 #ifdef _WIN32
470 LeaveCriticalSection(&m_mutex);
471 #else
472 int ret = pthread_mutex_unlock(&m_mutex);
473 ut_a(ret == 0);
474 #endif /* _WIN32 */
475 }
476
477 /** Acquire the mutex. */
enterOSMutex478 void enter()
479 UNIV_NOTHROW
480 {
481 ut_ad(innodb_calling_exit || !m_freed);
482 #ifdef _WIN32
483 EnterCriticalSection((LPCRITICAL_SECTION) &m_mutex);
484 #else
485 int ret = pthread_mutex_lock(&m_mutex);
486 ut_a(ret == 0);
487 #endif /* _WIN32 */
488 }
489
490 /** @return true if locking succeeded */
try_lockOSMutex491 bool try_lock()
492 UNIV_NOTHROW
493 {
494 ut_ad(innodb_calling_exit || !m_freed);
495 #ifdef _WIN32
496 return(TryEnterCriticalSection(&m_mutex) != 0);
497 #else
498 return(pthread_mutex_trylock(&m_mutex) == 0);
499 #endif /* _WIN32 */
500 }
501
502 /** Required for os_event_t */
503 operator sys_mutex_t*()
504 UNIV_NOTHROW
505 {
506 return(&m_mutex);
507 }
508
509 private:
510 #ifdef UNIV_DEBUG
511 /** true if the mutex has been freed/destroyed. */
512 bool m_freed;
513 #endif /* UNIV_DEBUG */
514
515 sys_mutex_t m_mutex;
516 };
517
518 #ifdef UNIV_PFS_MUTEX
519 /** Latch element.
520 Used for mutexes which have PFS keys defined under UNIV_PFS_MUTEX.
521 @param[in] id Latch id
522 @param[in] level Latch level
523 @param[in] key PFS key */
524 # define LATCH_ADD_MUTEX(id, level, key) latch_meta[LATCH_ID_ ## id] =\
525 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, key))
526
527 #ifdef UNIV_PFS_RWLOCK
528 /** Latch element.
529 Used for rwlocks which have PFS keys defined under UNIV_PFS_RWLOCK.
530 @param[in] id Latch id
531 @param[in] level Latch level
532 @param[in] key PFS key */
533 # define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
534 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, key))
535 #else
536 # define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
537 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, \
538 PSI_NOT_INSTRUMENTED))
539 #endif /* UNIV_PFS_RWLOCK */
540
541 #else
542 # define LATCH_ADD_MUTEX(id, level, key) latch_meta[LATCH_ID_ ## id] =\
543 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level))
544 # define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
545 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level))
546 #endif /* UNIV_PFS_MUTEX */
547
548 /** Default latch counter */
549 class LatchCounter {
550
551 public:
552 /** The counts we collect for a mutex */
553 struct Count {
554
555 /** Constructor */
CountCount556 Count()
557 UNIV_NOTHROW
558 :
559 m_spins(),
560 m_waits(),
561 m_calls(),
562 m_enabled()
563 {
564 /* No op */
565 }
566
567 /** Rest the values to zero */
resetCount568 void reset()
569 UNIV_NOTHROW
570 {
571 m_spins = 0;
572 m_waits = 0;
573 m_calls = 0;
574 }
575
576 /** Number of spins trying to acquire the latch. */
577 uint32_t m_spins;
578
579 /** Number of waits trying to acquire the latch */
580 uint32_t m_waits;
581
582 /** Number of times it was called */
583 uint32_t m_calls;
584
585 /** true if enabled */
586 bool m_enabled;
587 };
588
589 /** Constructor */
LatchCounter()590 LatchCounter()
591 UNIV_NOTHROW
592 :
593 m_active(false)
594 {
595 m_mutex.init();
596 }
597
598 /** Destructor */
~LatchCounter()599 ~LatchCounter()
600 UNIV_NOTHROW
601 {
602 m_mutex.destroy();
603
604 for (Counters::iterator it = m_counters.begin();
605 it != m_counters.end();
606 ++it) {
607
608 Count* count = *it;
609
610 UT_DELETE(count);
611 }
612 }
613
614 /** Reset all counters to zero. It is not protected by any
615 mutex and we don't care about atomicity. Unless it is a
616 demonstrated problem. The information collected is not
617 required for the correct functioning of the server. */
reset()618 void reset()
619 UNIV_NOTHROW
620 {
621 m_mutex.enter();
622
623 Counters::iterator end = m_counters.end();
624
625 for (Counters::iterator it = m_counters.begin();
626 it != end;
627 ++it) {
628
629 (*it)->reset();
630 }
631
632 m_mutex.exit();
633 }
634
635 /** @return the aggregate counter */
sum_register()636 Count* sum_register()
637 UNIV_NOTHROW
638 {
639 m_mutex.enter();
640
641 Count* count;
642
643 if (m_counters.empty()) {
644 count = UT_NEW_NOKEY(Count());
645 m_counters.push_back(count);
646 } else {
647 ut_a(m_counters.size() == 1);
648 count = m_counters[0];
649 }
650
651 m_mutex.exit();
652
653 return(count);
654 }
655
656 /** Deregister the count. We don't do anything
657 @param[in] count The count instance to deregister */
sum_deregister(Count * count)658 void sum_deregister(Count* count)
659 UNIV_NOTHROW
660 {
661 /* Do nothing */
662 }
663
664 /** Register a single instance counter */
single_register(Count * count)665 void single_register(Count* count)
666 UNIV_NOTHROW
667 {
668 m_mutex.enter();
669
670 m_counters.push_back(count);
671
672 m_mutex.exit();
673 }
674
675 /** Deregister a single instance counter
676 @param[in] count The count instance to deregister */
single_deregister(Count * count)677 void single_deregister(Count* count)
678 UNIV_NOTHROW
679 {
680 m_mutex.enter();
681
682 m_counters.erase(
683 std::remove(
684 m_counters.begin(),
685 m_counters.end(), count),
686 m_counters.end());
687
688 m_mutex.exit();
689 }
690
691 /** Iterate over the counters */
692 template <typename Callback>
iterate(Callback & callback)693 void iterate(Callback& callback) const
694 UNIV_NOTHROW
695 {
696 m_mutex.enter();
697 Counters::const_iterator end = m_counters.end();
698
699 for (Counters::const_iterator it = m_counters.begin();
700 it != end;
701 ++it) {
702
703 callback(*it);
704 }
705 m_mutex.exit();
706 }
707
708 /** Disable the monitoring */
enable()709 void enable()
710 UNIV_NOTHROW
711 {
712 m_mutex.enter();
713
714 Counters::const_iterator end = m_counters.end();
715
716 for (Counters::const_iterator it = m_counters.begin();
717 it != end;
718 ++it) {
719
720 (*it)->m_enabled = true;
721 }
722
723 m_active = true;
724
725 m_mutex.exit();
726 }
727
728 /** Disable the monitoring */
disable()729 void disable()
730 UNIV_NOTHROW
731 {
732 m_mutex.enter();
733
734 Counters::const_iterator end = m_counters.end();
735
736 for (Counters::const_iterator it = m_counters.begin();
737 it != end;
738 ++it) {
739
740 (*it)->m_enabled = false;
741 }
742
743 m_active = false;
744
745 m_mutex.exit();
746 }
747
748 /** @return if monitoring is active */
is_enabled()749 bool is_enabled() const
750 UNIV_NOTHROW
751 {
752 return(m_active);
753 }
754
755 private:
756 /* Disable copying */
757 LatchCounter(const LatchCounter&);
758 LatchCounter& operator=(const LatchCounter&);
759
760 private:
761 typedef OSMutex Mutex;
762 typedef std::vector<Count*> Counters;
763
764 /** Mutex protecting m_counters */
765 mutable Mutex m_mutex;
766
767 /** Counters for the latches */
768 Counters m_counters;
769
770 /** if true then we collect the data */
771 bool m_active;
772 };
773
774 /** Latch meta data */
775 template <typename Counter = LatchCounter>
776 class LatchMeta {
777
778 public:
779 typedef Counter CounterType;
780
781 #ifdef UNIV_PFS_MUTEX
782 typedef mysql_pfs_key_t pfs_key_t;
783 #endif /* UNIV_PFS_MUTEX */
784
785 /** Constructor */
LatchMeta()786 LatchMeta()
787 :
788 m_id(LATCH_ID_NONE),
789 m_name(),
790 m_level(SYNC_UNKNOWN),
791 m_level_name()
792 #ifdef UNIV_PFS_MUTEX
793 ,m_pfs_key()
794 #endif /* UNIV_PFS_MUTEX */
795 {
796 }
797
798 /** Destructor */
~LatchMeta()799 ~LatchMeta() { }
800
801 /** Constructor
802 @param[in] id Latch id
803 @param[in] name Latch name
804 @param[in] level Latch level
805 @param[in] level_name Latch level text representation
806 @param[in] key PFS key */
LatchMeta(latch_id_t id,const char * name,latch_level_t level,const char * level_name,pfs_key_t key)807 LatchMeta(
808 latch_id_t id,
809 const char* name,
810 latch_level_t level,
811 const char* level_name
812 #ifdef UNIV_PFS_MUTEX
813 ,pfs_key_t key
814 #endif /* UNIV_PFS_MUTEX */
815 )
816 :
817 m_id(id),
818 m_name(name),
819 m_level(level),
820 m_level_name(level_name)
821 #ifdef UNIV_PFS_MUTEX
822 ,m_pfs_key(key)
823 #endif /* UNIV_PFS_MUTEX */
824 {
825 /* No op */
826 }
827
828 /* Less than operator.
829 @param[in] rhs Instance to compare against
830 @return true if this.get_id() < rhs.get_id() */
831 bool operator<(const LatchMeta& rhs) const
832 {
833 return(get_id() < rhs.get_id());
834 }
835
836 /** @return the latch id */
get_id()837 latch_id_t get_id() const
838 {
839 return(m_id);
840 }
841
842 /** @return the latch name */
get_name()843 const char* get_name() const
844 {
845 return(m_name);
846 }
847
848 /** @return the latch level */
get_level()849 latch_level_t get_level() const
850 {
851 return(m_level);
852 }
853
854 /** @return the latch level name */
get_level_name()855 const char* get_level_name() const
856 {
857 return(m_level_name);
858 }
859
860 #ifdef UNIV_PFS_MUTEX
861 /** @return the PFS key for the latch */
get_pfs_key()862 pfs_key_t get_pfs_key() const
863 {
864 return(m_pfs_key);
865 }
866 #endif /* UNIV_PFS_MUTEX */
867
868 /** @return the counter instance */
get_counter()869 Counter* get_counter()
870 {
871 return(&m_counter);
872 }
873
874 private:
875 /** Latch id */
876 latch_id_t m_id;
877
878 /** Latch name */
879 const char* m_name;
880
881 /** Latch level in the ordering */
882 latch_level_t m_level;
883
884 /** Latch level text representation */
885 const char* m_level_name;
886
887 #ifdef UNIV_PFS_MUTEX
888 /** PFS key */
889 pfs_key_t m_pfs_key;
890 #endif /* UNIV_PFS_MUTEX */
891
892 /** For gathering latch statistics */
893 Counter m_counter;
894 };
895
896 typedef LatchMeta<LatchCounter> latch_meta_t;
897 typedef std::vector<latch_meta_t*, ut_allocator<latch_meta_t*> > LatchMetaData;
898
899 /** Note: This is accessed without any mutex protection. It is initialised
900 at startup and elements should not be added to or removed from it after
901 that. See sync_latch_meta_init() */
902 extern LatchMetaData latch_meta;
903
904 /** Get the latch meta-data from the latch ID
905 @param[in] id Latch ID
906 @return the latch meta data */
907 inline
908 latch_meta_t&
sync_latch_get_meta(latch_id_t id)909 sync_latch_get_meta(latch_id_t id)
910 {
911 ut_ad(static_cast<size_t>(id) < latch_meta.size());
912 ut_ad(id == latch_meta[id]->get_id());
913
914 return(*latch_meta[id]);
915 }
916
917 /** Fetch the counter for the latch
918 @param[in] id Latch ID
919 @return the latch counter */
920 inline
921 latch_meta_t::CounterType*
sync_latch_get_counter(latch_id_t id)922 sync_latch_get_counter(latch_id_t id)
923 {
924 latch_meta_t& meta = sync_latch_get_meta(id);
925
926 return(meta.get_counter());
927 }
928
929 /** Get the latch name from the latch ID
930 @param[in] id Latch ID
931 @return the name, will assert if not found */
932 inline
933 const char*
sync_latch_get_name(latch_id_t id)934 sync_latch_get_name(latch_id_t id)
935 {
936 const latch_meta_t& meta = sync_latch_get_meta(id);
937
938 return(meta.get_name());
939 }
940
941 /** Get the latch ordering level
942 @param[in] id Latch id to lookup
943 @return the latch level */
944 inline
945 latch_level_t
sync_latch_get_level(latch_id_t id)946 sync_latch_get_level(latch_id_t id)
947 {
948 const latch_meta_t& meta = sync_latch_get_meta(id);
949
950 return(meta.get_level());
951 }
952
953 #ifdef UNIV_PFS_MUTEX
954 /** Get the latch PFS key from the latch ID
955 @param[in] id Latch ID
956 @return the PFS key */
957 inline
958 mysql_pfs_key_t
sync_latch_get_pfs_key(latch_id_t id)959 sync_latch_get_pfs_key(latch_id_t id)
960 {
961 const latch_meta_t& meta = sync_latch_get_meta(id);
962
963 return(meta.get_pfs_key());
964 }
965 #endif
966
967 /** String representation of the filename and line number where the
968 latch was created
969 @param[in] id Latch ID
970 @param[in] created Filename and line number where it was crated
971 @return the string representation */
972 std::string
973 sync_mutex_to_string(
974 latch_id_t id,
975 const std::string& created);
976
977 /** Get the latch name from a sync level
978 @param[in] level Latch level to lookup
979 @return 0 if not found. */
980 const char*
981 sync_latch_get_name(latch_level_t level);
982
983 /** Print the filename "basename"
984 @return the basename */
985 const char*
986 sync_basename(const char* filename);
987
988 /** Register a latch, called when it is created
989 @param[in] ptr Latch instance that was created
990 @param[in] filename Filename where it was created
991 @param[in] line Line number in filename */
992 void
993 sync_file_created_register(
994 const void* ptr,
995 const char* filename,
996 uint16_t line);
997
998 /** Deregister a latch, called when it is destroyed
999 @param[in] ptr Latch to be destroyed */
1000 void
1001 sync_file_created_deregister(const void* ptr);
1002
1003 /** Get the string where the file was created. Its format is "name:line"
1004 @param[in] ptr Latch instance
1005 @return created information or "" if can't be found */
1006 std::string
1007 sync_file_created_get(const void* ptr);
1008
1009 #ifdef UNIV_DEBUG
1010
1011 /** All (ordered) latches, used in debugging, must derive from this class. */
1012 struct latch_t {
1013
1014 /** Constructor
1015 @param[in] id The latch ID */
1016 explicit latch_t(latch_id_t id = LATCH_ID_NONE)
1017 UNIV_NOTHROW
1018 :
m_idlatch_t1019 m_id(id),
1020 m_rw_lock(),
1021 m_temp_fsp() { }
1022
1023 /** Destructor */
~latch_tlatch_t1024 virtual ~latch_t() UNIV_NOTHROW { }
1025
1026 /** @return the latch ID */
get_idlatch_t1027 latch_id_t get_id() const
1028 {
1029 return(m_id);
1030 }
1031
1032 /** @return true if it is a rw-lock */
is_rw_locklatch_t1033 bool is_rw_lock() const
1034 UNIV_NOTHROW
1035 {
1036 return(m_rw_lock);
1037 }
1038
1039 /** Print the latch context
1040 @return the string representation */
1041 virtual std::string to_string() const = 0;
1042
1043 /** @return "filename:line" from where the latch was last locked */
1044 virtual std::string locked_from() const = 0;
1045
1046 /** @return the latch level */
get_levellatch_t1047 latch_level_t get_level() const
1048 UNIV_NOTHROW
1049 {
1050 ut_a(m_id != LATCH_ID_NONE);
1051
1052 return(sync_latch_get_level(m_id));
1053 }
1054
1055 /** @return true if the latch is for a temporary file space*/
is_temp_fsplatch_t1056 bool is_temp_fsp() const
1057 UNIV_NOTHROW
1058 {
1059 return(m_temp_fsp);
1060 }
1061
1062 /** Set the temporary tablespace flag. The latch order constraints
1063 are different for intrinsic tables. We don't always acquire the
1064 index->lock. We need to figure out the context and add some special
1065 rules during the checks. */
set_temp_fsplatch_t1066 void set_temp_fsp()
1067 UNIV_NOTHROW
1068 {
1069 ut_ad(get_id() == LATCH_ID_FIL_SPACE);
1070 m_temp_fsp = true;
1071 }
1072
1073 /** @return the latch name, m_id must be set */
get_namelatch_t1074 const char* get_name() const
1075 UNIV_NOTHROW
1076 {
1077 ut_a(m_id != LATCH_ID_NONE);
1078
1079 return(sync_latch_get_name(m_id));
1080 }
1081
1082 /** Latch ID */
1083 latch_id_t m_id;
1084
1085 /** true if it is a rw-lock. In debug mode, rw_lock_t derives from
1086 this class and sets this variable. */
1087 bool m_rw_lock;
1088
1089 /** true if it is an temporary space latch */
1090 bool m_temp_fsp;
1091 };
1092
1093 /** Subclass this to iterate over a thread's acquired latch levels. */
1094 struct sync_check_functor_t {
~sync_check_functor_tsync_check_functor_t1095 virtual ~sync_check_functor_t() { }
1096 virtual bool operator()(const latch_level_t) = 0;
1097 virtual bool result() const = 0;
1098 };
1099
1100 /** Functor to check whether the calling thread owns the btr search mutex. */
1101 struct btrsea_sync_check : public sync_check_functor_t {
1102
1103 /** Constructor
1104 @param[in] has_search_latch true if owns the latch */
btrsea_sync_checkbtrsea_sync_check1105 explicit btrsea_sync_check(bool has_search_latch)
1106 :
1107 m_result(),
1108 m_has_search_latch(has_search_latch) { }
1109
1110 /** Destructor */
~btrsea_sync_checkbtrsea_sync_check1111 virtual ~btrsea_sync_check() { }
1112
1113 /** Called for every latch owned by the calling thread.
1114 @param[in] level Level of the existing latch
1115 @return true if the predicate check is successful */
operatorbtrsea_sync_check1116 virtual bool operator()(const latch_level_t level)
1117 {
1118 /* If calling thread doesn't hold search latch then
1119 check if there are latch level exception provided.
1120
1121 Note: Optimizer has added InnoDB intrinsic table as an
1122 alternative to MyISAM intrinsic table. With this a new
1123 control flow comes into existence, it is:
1124
1125 Server -> Plugin -> SE
1126
1127 Plugin in this case is I_S which is sharing the latch vector
1128 of InnoDB and so there could be lock conflicts. Ideally
1129 the Plugin should use a difference namespace latch vector
1130 as it doesn't have any depedency with SE latching protocol.
1131
1132 Added check that will allow thread to hold I_S latches */
1133
1134 if (!m_has_search_latch
1135 && (level != SYNC_SEARCH_SYS
1136 && level != SYNC_FTS_CACHE
1137 && level != SYNC_TRX_I_S_RWLOCK
1138 && level != SYNC_TRX_I_S_LAST_READ)) {
1139
1140 m_result = true;
1141
1142 return(m_result);
1143 }
1144
1145 return(false);
1146 }
1147
1148 /** @return result from the check */
resultbtrsea_sync_check1149 virtual bool result() const
1150 {
1151 return(m_result);
1152 }
1153
1154 private:
1155 /** True if all OK */
1156 bool m_result;
1157
1158 /** If the caller owns the search latch */
1159 const bool m_has_search_latch;
1160 };
1161
1162 /** Functor to check for dictionay latching constraints. */
1163 struct dict_sync_check : public sync_check_functor_t {
1164
1165 /** Constructor
1166 @param[in] dict_mutex_allow true if the dict mutex
1167 is allowed */
dict_sync_checkdict_sync_check1168 explicit dict_sync_check(bool dict_mutex_allowed)
1169 :
1170 m_result(),
1171 m_dict_mutex_allowed(dict_mutex_allowed) { }
1172
1173 /** Destructor */
~dict_sync_checkdict_sync_check1174 virtual ~dict_sync_check() { }
1175
1176 /** Check the latching constraints
1177 @param[in] level The level held by the thread */
operatordict_sync_check1178 virtual bool operator()(const latch_level_t level)
1179 {
1180 if (!m_dict_mutex_allowed
1181 || (level != SYNC_DICT
1182 && level != SYNC_DICT_OPERATION
1183 && level != SYNC_FTS_CACHE
1184 /* This only happens in recv_apply_hashed_log_recs. */
1185 && level != SYNC_RECV_WRITER
1186 && level != SYNC_NO_ORDER_CHECK)) {
1187
1188 m_result = true;
1189
1190 return(true);
1191 }
1192
1193 return(false);
1194 }
1195
1196 /** @return the result of the check */
resultdict_sync_check1197 virtual bool result() const
1198 {
1199 return(m_result);
1200 }
1201
1202 private:
1203 /** True if all OK */
1204 bool m_result;
1205
1206 /** True if it is OK to hold the dict mutex */
1207 const bool m_dict_mutex_allowed;
1208 };
1209
1210 /** Functor to check for given latching constraints. */
1211 struct sync_allowed_latches : public sync_check_functor_t {
1212
1213 /** Constructor
1214 @param[in] from first element in an array of latch_level_t
1215 @param[in] to last element in an array of latch_level_t */
sync_allowed_latchessync_allowed_latches1216 sync_allowed_latches(
1217 const latch_level_t* from,
1218 const latch_level_t* to)
1219 :
1220 m_result(),
1221 m_latches(from, to) { }
1222
1223 /** Checks whether the given latch_t violates the latch constraint.
1224 This object maintains a list of allowed latch levels, and if the given
1225 latch belongs to a latch level that is not there in the allowed list,
1226 then it is a violation.
1227
1228 @param[in] latch The latch level to check
1229 @return true if there is a latch ordering violation */
operatorsync_allowed_latches1230 virtual bool operator()(const latch_level_t level)
1231 {
1232 for (latches_t::const_iterator it = m_latches.begin();
1233 it != m_latches.end();
1234 ++it) {
1235
1236 if (level == *it) {
1237
1238 m_result = false;
1239
1240 /* No violation */
1241 return(false);
1242 }
1243 }
1244
1245 return(true);
1246 }
1247
1248 /** @return the result of the check */
resultsync_allowed_latches1249 virtual bool result() const
1250 {
1251 return(m_result);
1252 }
1253
1254 private:
1255 /** Save the result of validation check here
1256 True if all OK */
1257 bool m_result;
1258
1259 typedef std::vector<latch_level_t, ut_allocator<latch_level_t> >
1260 latches_t;
1261
1262 /** List of latch levels that are allowed to be held */
1263 latches_t m_latches;
1264 };
1265
1266 /** Get the latch id from a latch name.
1267 @param[in] id Latch name
1268 @return LATCH_ID_NONE. */
1269 latch_id_t
1270 sync_latch_get_id(const char* name);
1271
1272 typedef ulint rw_lock_flags_t;
1273
1274 /* Flags to specify lock types for rw_lock_own_flagged() */
1275 enum rw_lock_flag_t {
1276 RW_LOCK_FLAG_S = 1 << 0,
1277 RW_LOCK_FLAG_X = 1 << 1,
1278 RW_LOCK_FLAG_SX = 1 << 2
1279 };
1280
1281 #endif /* UNIV_DBEUG */
1282
1283 #endif /* UNIV_INNOCHECKSUM */
1284
1285 #endif /* sync0types_h */
1286