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 mutexes
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 SYNC_BUF_FLUSH_STATE,
227 SYNC_BUF_ZIP_HASH,
228 SYNC_BUF_FREE_LIST,
229 SYNC_BUF_ZIP_FREE,
230 SYNC_BUF_BLOCK,
231 SYNC_BUF_PAGE_HASH,
232 SYNC_BUF_LRU_LIST,
233 SYNC_BUF_CHUNKS,
234
235 SYNC_POOL,
236 SYNC_POOL_MANAGER,
237
238 SYNC_SEARCH_SYS,
239
240 SYNC_WORK_QUEUE,
241
242 SYNC_FTS_TOKENIZE,
243 SYNC_FTS_OPTIMIZE,
244 SYNC_FTS_BG_THREADS,
245 SYNC_FTS_CACHE_INIT,
246 SYNC_RECV,
247 SYNC_LOG_FLUSH_ORDER,
248 SYNC_LOG,
249 SYNC_LOG_ONLINE,
250 SYNC_LOG_WRITE,
251 SYNC_PAGE_CLEANER,
252 SYNC_PURGE_QUEUE,
253 SYNC_TRX_SYS_HEADER,
254 SYNC_REC_LOCK,
255 SYNC_THREADS,
256 SYNC_TRX,
257 SYNC_TRX_SYS,
258 SYNC_LOCK_SYS,
259 SYNC_LOCK_WAIT_SYS,
260
261 SYNC_INDEX_ONLINE_LOG,
262
263 SYNC_IBUF_BITMAP,
264 SYNC_IBUF_BITMAP_MUTEX,
265 SYNC_IBUF_TREE_NODE,
266 SYNC_IBUF_TREE_NODE_NEW,
267 SYNC_IBUF_INDEX_TREE,
268
269 SYNC_IBUF_MUTEX,
270
271 SYNC_FSP_PAGE,
272 SYNC_FSP,
273 SYNC_EXTERN_STORAGE,
274 SYNC_TRX_UNDO_PAGE,
275 SYNC_RSEG_HEADER,
276 SYNC_RSEG_HEADER_NEW,
277 SYNC_NOREDO_RSEG,
278 SYNC_REDO_RSEG,
279 SYNC_TRX_UNDO,
280 SYNC_PURGE_LATCH,
281 SYNC_TREE_NODE,
282 SYNC_TREE_NODE_FROM_HASH,
283 SYNC_TREE_NODE_NEW,
284 SYNC_INDEX_TREE,
285 SYNC_ANALYZE_INDEX,
286
287 SYNC_IBUF_PESS_INSERT_MUTEX,
288 SYNC_IBUF_HEADER,
289 SYNC_DICT_HEADER,
290 SYNC_STATS_AUTO_RECALC,
291 SYNC_DICT_AUTOINC_MUTEX,
292 SYNC_DICT,
293 SYNC_FTS_CACHE,
294
295 SYNC_DICT_OPERATION,
296
297 SYNC_FILE_FORMAT_TAG,
298
299 SYNC_TRX_I_S_LAST_READ,
300
301 SYNC_TRX_I_S_RWLOCK,
302
303 /** Level is varying. Only used with buffer pool page locks, which
304 do not have a fixed level, but instead have their level set after
305 the page is locked; see e.g. ibuf_bitmap_get_map_page(). */
306
307 SYNC_LEVEL_VARYING,
308
309 /** This can be used to suppress order checking. */
310 SYNC_NO_ORDER_CHECK,
311
312 /** Maximum level value */
313 SYNC_LEVEL_MAX = SYNC_NO_ORDER_CHECK
314 };
315
316 /** Each latch has an ID. This id is used for creating the latch and to look
317 up its meta-data. See sync0debug.c. */
318 enum latch_id_t {
319 LATCH_ID_NONE = 0,
320 LATCH_ID_AUTOINC,
321 LATCH_ID_BUF_BLOCK_MUTEX,
322 LATCH_ID_BUF_POOL_CHUNKS,
323 LATCH_ID_BUF_POOL_LRU_LIST,
324 LATCH_ID_BUF_POOL_FREE_LIST,
325 LATCH_ID_BUF_POOL_ZIP_FREE,
326 LATCH_ID_BUF_POOL_ZIP_HASH,
327 LATCH_ID_BUF_POOL_FLUSH_STATE,
328 LATCH_ID_BUF_POOL_ZIP,
329 LATCH_ID_CACHE_LAST_READ,
330 LATCH_ID_DICT_FOREIGN_ERR,
331 LATCH_ID_DICT_SYS,
332 LATCH_ID_FILE_FORMAT_MAX,
333 LATCH_ID_FIL_SYSTEM,
334 LATCH_ID_FLUSH_LIST,
335 LATCH_ID_FTS_BG_THREADS,
336 LATCH_ID_FTS_DELETE,
337 LATCH_ID_FTS_OPTIMIZE,
338 LATCH_ID_FTS_DOC_ID,
339 LATCH_ID_FTS_PLL_TOKENIZE,
340 LATCH_ID_HASH_TABLE_MUTEX,
341 LATCH_ID_IBUF_BITMAP,
342 LATCH_ID_IBUF,
343 LATCH_ID_IBUF_PESSIMISTIC_INSERT,
344 LATCH_ID_LOG_SYS,
345 LATCH_ID_LOG_ONLINE,
346 LATCH_ID_LOG_WRITE,
347 LATCH_ID_LOG_FLUSH_ORDER,
348 LATCH_ID_LIST,
349 LATCH_ID_MUTEX_LIST,
350 LATCH_ID_PAGE_CLEANER,
351 LATCH_ID_PURGE_SYS_PQ,
352 LATCH_ID_RECALC_POOL,
353 LATCH_ID_RECV_SYS,
354 LATCH_ID_REDO_RSEG,
355 LATCH_ID_NOREDO_RSEG,
356 LATCH_ID_RW_LOCK_DEBUG,
357 LATCH_ID_RTR_SSN_MUTEX,
358 LATCH_ID_RTR_ACTIVE_MUTEX,
359 LATCH_ID_RTR_MATCH_MUTEX,
360 LATCH_ID_RTR_PATH_MUTEX,
361 LATCH_ID_RW_LOCK_LIST,
362 LATCH_ID_RW_LOCK_MUTEX,
363 LATCH_ID_SRV_DICT_TMPFILE,
364 LATCH_ID_SRV_INNODB_MONITOR,
365 LATCH_ID_SRV_MISC_TMPFILE,
366 LATCH_ID_SRV_MONITOR_FILE,
367 LATCH_ID_SYNC_THREAD,
368 LATCH_ID_BUF_DBLWR,
369 LATCH_ID_TRX_UNDO,
370 LATCH_ID_TRX_POOL,
371 LATCH_ID_TRX_POOL_MANAGER,
372 LATCH_ID_TRX,
373 LATCH_ID_LOCK_SYS,
374 LATCH_ID_LOCK_SYS_WAIT,
375 LATCH_ID_TRX_SYS,
376 LATCH_ID_SRV_SYS,
377 LATCH_ID_SRV_SYS_TASKS,
378 LATCH_ID_PAGE_ZIP_STAT_PER_INDEX,
379 LATCH_ID_EVENT_MANAGER,
380 LATCH_ID_EVENT_MUTEX,
381 LATCH_ID_SYNC_ARRAY_MUTEX,
382 #ifdef _WIN32
383 LATCH_ID_THREAD_MUTEX,
384 #endif
385 LATCH_ID_ZIP_PAD_MUTEX,
386 LATCH_ID_OS_AIO_READ_MUTEX,
387 LATCH_ID_OS_AIO_WRITE_MUTEX,
388 LATCH_ID_OS_AIO_LOG_MUTEX,
389 LATCH_ID_OS_AIO_IBUF_MUTEX,
390 LATCH_ID_OS_AIO_SYNC_MUTEX,
391 LATCH_ID_ROW_DROP_LIST,
392 LATCH_ID_INDEX_ONLINE_LOG,
393 LATCH_ID_WORK_QUEUE,
394 LATCH_ID_BTR_SEARCH,
395 LATCH_ID_BUF_BLOCK_LOCK,
396 LATCH_ID_BUF_BLOCK_DEBUG,
397 LATCH_ID_DICT_OPERATION,
398 LATCH_ID_CHECKPOINT,
399 LATCH_ID_FIL_SPACE,
400 LATCH_ID_FTS_CACHE,
401 LATCH_ID_FTS_CACHE_INIT,
402 LATCH_ID_TRX_I_S_CACHE,
403 LATCH_ID_TRX_PURGE,
404 LATCH_ID_IBUF_INDEX_TREE,
405 LATCH_ID_INDEX_TREE,
406 LATCH_ID_DICT_TABLE_STATS,
407 LATCH_ID_HASH_TABLE_RW_LOCK,
408 LATCH_ID_BUF_CHUNK_MAP_LATCH,
409 LATCH_ID_SYNC_DEBUG_MUTEX,
410 LATCH_ID_SCRUB_STAT_MUTEX,
411 LATCH_ID_MASTER_KEY_ID_MUTEX,
412 LATCH_ID_FIL_CRYPT_MUTEX,
413 LATCH_ID_FIL_CRYPT_STAT_MUTEX,
414 LATCH_ID_FIL_CRYPT_DATA_MUTEX,
415 LATCH_ID_FIL_CRYPT_THREADS_MUTEX,
416 LATCH_ID_FIL_CRYPT_START_ROTATE_MUTEX,
417 LATCH_ID_ANALYZE_INDEX_MUTEX,
418 LATCH_ID_TEST_MUTEX,
419 LATCH_ID_MAX = LATCH_ID_TEST_MUTEX
420 };
421
422 #ifndef UNIV_INNOCHECKSUM
423 /** OS mutex, without any policy. It is a thin wrapper around the
424 system mutexes. The interface is different from the policy mutexes,
425 to ensure that it is called directly and not confused with the
426 policy mutexes. */
427 struct OSMutex {
428
429 /** Constructor */
OSMutexOSMutex430 OSMutex()
431 UNIV_NOTHROW
432 {
433 ut_d(m_freed = true);
434 }
435
436 /** Create the mutex by calling the system functions. */
initOSMutex437 void init()
438 UNIV_NOTHROW
439 {
440 ut_ad(m_freed);
441
442 #ifdef _WIN32
443 InitializeCriticalSection((LPCRITICAL_SECTION) &m_mutex);
444 #else
445 {
446 int ret = pthread_mutex_init(&m_mutex, NULL);
447 ut_a(ret == 0);
448 }
449 #endif /* _WIN32 */
450
451 ut_d(m_freed = false);
452 }
453
454 /** Destructor */
~OSMutexOSMutex455 ~OSMutex() { }
456
457 /** Destroy the mutex */
destroyOSMutex458 void destroy()
459 UNIV_NOTHROW
460 {
461 ut_ad(innodb_calling_exit || !m_freed);
462 #ifdef _WIN32
463 DeleteCriticalSection((LPCRITICAL_SECTION) &m_mutex);
464 #else
465 int ret;
466
467 ret = pthread_mutex_destroy(&m_mutex);
468
469 if (ret != 0) {
470
471 ib::error()
472 << "Return value " << ret << " when calling "
473 << "pthread_mutex_destroy().";
474 }
475 #endif /* _WIN32 */
476 ut_d(m_freed = true);
477 }
478
479 /** Release the mutex. */
exitOSMutex480 void exit()
481 UNIV_NOTHROW
482 {
483 ut_ad(innodb_calling_exit || !m_freed);
484 #ifdef _WIN32
485 LeaveCriticalSection(&m_mutex);
486 #else
487 int ret = pthread_mutex_unlock(&m_mutex);
488 ut_a(ret == 0);
489 #endif /* _WIN32 */
490 }
491
492 /** Acquire the mutex. */
enterOSMutex493 void enter()
494 UNIV_NOTHROW
495 {
496 ut_ad(innodb_calling_exit || !m_freed);
497 #ifdef _WIN32
498 EnterCriticalSection((LPCRITICAL_SECTION) &m_mutex);
499 #else
500 int ret = pthread_mutex_lock(&m_mutex);
501 ut_a(ret == 0);
502 #endif /* _WIN32 */
503 }
504
505 /** @return true if locking succeeded */
try_lockOSMutex506 bool try_lock()
507 UNIV_NOTHROW
508 {
509 ut_ad(innodb_calling_exit || !m_freed);
510 #ifdef _WIN32
511 return(TryEnterCriticalSection(&m_mutex) != 0);
512 #else
513 return(pthread_mutex_trylock(&m_mutex) == 0);
514 #endif /* _WIN32 */
515 }
516
517 /** Required for os_event_t */
518 operator sys_mutex_t*()
519 UNIV_NOTHROW
520 {
521 return(&m_mutex);
522 }
523
524 private:
525 #ifdef UNIV_DEBUG
526 /** true if the mutex has been freed/destroyed. */
527 bool m_freed;
528 #endif /* UNIV_DEBUG */
529
530 sys_mutex_t m_mutex;
531 };
532
533 #ifdef UNIV_PFS_MUTEX
534 /** Latch element.
535 Used for mutexes which have PFS keys defined under UNIV_PFS_MUTEX.
536 @param[in] id Latch id
537 @param[in] level Latch level
538 @param[in] key PFS key */
539 # define LATCH_ADD_MUTEX(id, level, key) latch_meta[LATCH_ID_ ## id] =\
540 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, key))
541
542 #ifdef UNIV_PFS_RWLOCK
543 /** Latch element.
544 Used for rwlocks which have PFS keys defined under UNIV_PFS_RWLOCK.
545 @param[in] id Latch id
546 @param[in] level Latch level
547 @param[in] key PFS key */
548 # define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
549 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, key))
550 #else
551 # define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
552 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, \
553 PSI_NOT_INSTRUMENTED))
554 #endif /* UNIV_PFS_RWLOCK */
555
556 #else
557 # define LATCH_ADD_MUTEX(id, level, key) latch_meta[LATCH_ID_ ## id] =\
558 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level))
559 # define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
560 UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level))
561 #endif /* UNIV_PFS_MUTEX */
562
563 /** Default latch counter */
564 class LatchCounter {
565
566 public:
567 /** The counts we collect for a mutex */
568 struct Count {
569
570 /** Constructor */
CountCount571 Count()
572 UNIV_NOTHROW
573 :
574 m_spins(),
575 m_waits(),
576 m_calls(),
577 m_enabled()
578 {
579 /* No op */
580 }
581
582 /** Rest the values to zero */
resetCount583 void reset()
584 UNIV_NOTHROW
585 {
586 m_spins = 0;
587 m_waits = 0;
588 m_calls = 0;
589 }
590
591 /** Number of spins trying to acquire the latch. */
592 uint32_t m_spins;
593
594 /** Number of waits trying to acquire the latch */
595 uint32_t m_waits;
596
597 /** Number of times it was called */
598 uint32_t m_calls;
599
600 /** true if enabled */
601 bool m_enabled;
602 };
603
604 /** Constructor */
LatchCounter()605 LatchCounter()
606 UNIV_NOTHROW
607 :
608 m_active(false)
609 {
610 m_mutex.init();
611 }
612
613 /** Destructor */
~LatchCounter()614 ~LatchCounter()
615 UNIV_NOTHROW
616 {
617 m_mutex.destroy();
618
619 for (Counters::iterator it = m_counters.begin();
620 it != m_counters.end();
621 ++it) {
622
623 Count* count = *it;
624
625 UT_DELETE(count);
626 }
627 }
628
629 /** Reset all counters to zero. It is not protected by any
630 mutex and we don't care about atomicity. Unless it is a
631 demonstrated problem. The information collected is not
632 required for the correct functioning of the server. */
reset()633 void reset()
634 UNIV_NOTHROW
635 {
636 m_mutex.enter();
637
638 Counters::iterator end = m_counters.end();
639
640 for (Counters::iterator it = m_counters.begin();
641 it != end;
642 ++it) {
643
644 (*it)->reset();
645 }
646
647 m_mutex.exit();
648 }
649
650 /** @return the aggregate counter */
sum_register()651 Count* sum_register()
652 UNIV_NOTHROW
653 {
654 m_mutex.enter();
655
656 Count* count;
657
658 if (m_counters.empty()) {
659 count = UT_NEW_NOKEY(Count());
660 m_counters.push_back(count);
661 } else {
662 ut_a(m_counters.size() == 1);
663 count = m_counters[0];
664 }
665
666 m_mutex.exit();
667
668 return(count);
669 }
670
671 /** Deregister the count. We don't do anything
672 @param[in] count The count instance to deregister */
sum_deregister(Count * count)673 void sum_deregister(Count* count)
674 UNIV_NOTHROW
675 {
676 /* Do nothing */
677 }
678
679 /** Register a single instance counter */
single_register(Count * count)680 void single_register(Count* count)
681 UNIV_NOTHROW
682 {
683 m_mutex.enter();
684
685 m_counters.push_back(count);
686
687 m_mutex.exit();
688 }
689
690 /** Deregister a single instance counter
691 @param[in] count The count instance to deregister */
single_deregister(Count * count)692 void single_deregister(Count* count)
693 UNIV_NOTHROW
694 {
695 m_mutex.enter();
696
697 m_counters.erase(
698 std::remove(
699 m_counters.begin(),
700 m_counters.end(), count),
701 m_counters.end());
702
703 m_mutex.exit();
704 }
705
706 /** Iterate over the counters */
707 template <typename Callback>
iterate(Callback & callback)708 void iterate(Callback& callback) const
709 UNIV_NOTHROW
710 {
711 m_mutex.enter();
712 Counters::const_iterator end = m_counters.end();
713
714 for (Counters::const_iterator it = m_counters.begin();
715 it != end;
716 ++it) {
717
718 callback(*it);
719 }
720 m_mutex.exit();
721 }
722
723 /** Disable the monitoring */
enable()724 void enable()
725 UNIV_NOTHROW
726 {
727 m_mutex.enter();
728
729 Counters::const_iterator end = m_counters.end();
730
731 for (Counters::const_iterator it = m_counters.begin();
732 it != end;
733 ++it) {
734
735 (*it)->m_enabled = true;
736 }
737
738 m_active = true;
739
740 m_mutex.exit();
741 }
742
743 /** Disable the monitoring */
disable()744 void disable()
745 UNIV_NOTHROW
746 {
747 m_mutex.enter();
748
749 Counters::const_iterator end = m_counters.end();
750
751 for (Counters::const_iterator it = m_counters.begin();
752 it != end;
753 ++it) {
754
755 (*it)->m_enabled = false;
756 }
757
758 m_active = false;
759
760 m_mutex.exit();
761 }
762
763 /** @return if monitoring is active */
is_enabled()764 bool is_enabled() const
765 UNIV_NOTHROW
766 {
767 return(m_active);
768 }
769
770 private:
771 /* Disable copying */
772 LatchCounter(const LatchCounter&);
773 LatchCounter& operator=(const LatchCounter&);
774
775 private:
776 typedef OSMutex Mutex;
777 typedef std::vector<Count*> Counters;
778
779 /** Mutex protecting m_counters */
780 mutable Mutex m_mutex;
781
782 /** Counters for the latches */
783 Counters m_counters;
784
785 /** if true then we collect the data */
786 bool m_active;
787 };
788
789 /** Latch meta data */
790 template <typename Counter = LatchCounter>
791 class LatchMeta {
792
793 public:
794 typedef Counter CounterType;
795
796 #ifdef UNIV_PFS_MUTEX
797 typedef mysql_pfs_key_t pfs_key_t;
798 #endif /* UNIV_PFS_MUTEX */
799
800 /** Constructor */
LatchMeta()801 LatchMeta()
802 :
803 m_id(LATCH_ID_NONE),
804 m_name(),
805 m_level(SYNC_UNKNOWN),
806 m_level_name()
807 #ifdef UNIV_PFS_MUTEX
808 ,m_pfs_key()
809 #endif /* UNIV_PFS_MUTEX */
810 {
811 }
812
813 /** Destructor */
~LatchMeta()814 ~LatchMeta() { }
815
816 /** Constructor
817 @param[in] id Latch id
818 @param[in] name Latch name
819 @param[in] level Latch level
820 @param[in] level_name Latch level text representation
821 @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)822 LatchMeta(
823 latch_id_t id,
824 const char* name,
825 latch_level_t level,
826 const char* level_name
827 #ifdef UNIV_PFS_MUTEX
828 ,pfs_key_t key
829 #endif /* UNIV_PFS_MUTEX */
830 )
831 :
832 m_id(id),
833 m_name(name),
834 m_level(level),
835 m_level_name(level_name)
836 #ifdef UNIV_PFS_MUTEX
837 ,m_pfs_key(key)
838 #endif /* UNIV_PFS_MUTEX */
839 {
840 /* No op */
841 }
842
843 /* Less than operator.
844 @param[in] rhs Instance to compare against
845 @return true if this.get_id() < rhs.get_id() */
846 bool operator<(const LatchMeta& rhs) const
847 {
848 return(get_id() < rhs.get_id());
849 }
850
851 /** @return the latch id */
get_id()852 latch_id_t get_id() const
853 {
854 return(m_id);
855 }
856
857 /** @return the latch name */
get_name()858 const char* get_name() const
859 {
860 return(m_name);
861 }
862
863 /** @return the latch level */
get_level()864 latch_level_t get_level() const
865 {
866 return(m_level);
867 }
868
869 /** @return the latch level name */
get_level_name()870 const char* get_level_name() const
871 {
872 return(m_level_name);
873 }
874
875 #ifdef UNIV_PFS_MUTEX
876 /** @return the PFS key for the latch */
get_pfs_key()877 pfs_key_t get_pfs_key() const
878 {
879 return(m_pfs_key);
880 }
881 #endif /* UNIV_PFS_MUTEX */
882
883 /** @return the counter instance */
get_counter()884 Counter* get_counter()
885 {
886 return(&m_counter);
887 }
888
889 private:
890 /** Latch id */
891 latch_id_t m_id;
892
893 /** Latch name */
894 const char* m_name;
895
896 /** Latch level in the ordering */
897 latch_level_t m_level;
898
899 /** Latch level text representation */
900 const char* m_level_name;
901
902 #ifdef UNIV_PFS_MUTEX
903 /** PFS key */
904 pfs_key_t m_pfs_key;
905 #endif /* UNIV_PFS_MUTEX */
906
907 /** For gathering latch statistics */
908 Counter m_counter;
909 };
910
911 typedef LatchMeta<LatchCounter> latch_meta_t;
912 typedef std::vector<latch_meta_t*, ut_allocator<latch_meta_t*> > LatchMetaData;
913
914 /** Note: This is accessed without any mutex protection. It is initialised
915 at startup and elements should not be added to or removed from it after
916 that. See sync_latch_meta_init() */
917 extern LatchMetaData latch_meta;
918
919 /** Get the latch meta-data from the latch ID
920 @param[in] id Latch ID
921 @return the latch meta data */
922 inline
923 latch_meta_t&
sync_latch_get_meta(latch_id_t id)924 sync_latch_get_meta(latch_id_t id)
925 {
926 ut_ad(static_cast<size_t>(id) < latch_meta.size());
927 ut_ad(id == latch_meta[id]->get_id());
928
929 return(*latch_meta[id]);
930 }
931
932 /** Fetch the counter for the latch
933 @param[in] id Latch ID
934 @return the latch counter */
935 inline
936 latch_meta_t::CounterType*
sync_latch_get_counter(latch_id_t id)937 sync_latch_get_counter(latch_id_t id)
938 {
939 latch_meta_t& meta = sync_latch_get_meta(id);
940
941 return(meta.get_counter());
942 }
943
944 /** Get the latch name from the latch ID
945 @param[in] id Latch ID
946 @return the name, will assert if not found */
947 inline
948 const char*
sync_latch_get_name(latch_id_t id)949 sync_latch_get_name(latch_id_t id)
950 {
951 const latch_meta_t& meta = sync_latch_get_meta(id);
952
953 return(meta.get_name());
954 }
955
956 /** Get the latch ordering level
957 @param[in] id Latch id to lookup
958 @return the latch level */
959 inline
960 latch_level_t
sync_latch_get_level(latch_id_t id)961 sync_latch_get_level(latch_id_t id)
962 {
963 const latch_meta_t& meta = sync_latch_get_meta(id);
964
965 return(meta.get_level());
966 }
967
968 #ifdef UNIV_PFS_MUTEX
969 /** Get the latch PFS key from the latch ID
970 @param[in] id Latch ID
971 @return the PFS key */
972 inline
973 mysql_pfs_key_t
sync_latch_get_pfs_key(latch_id_t id)974 sync_latch_get_pfs_key(latch_id_t id)
975 {
976 const latch_meta_t& meta = sync_latch_get_meta(id);
977
978 return(meta.get_pfs_key());
979 }
980 #endif
981
982 /** String representation of the filename and line number where the
983 latch was created
984 @param[in] id Latch ID
985 @param[in] created Filename and line number where it was crated
986 @return the string representation */
987 std::string
988 sync_mutex_to_string(
989 latch_id_t id,
990 const std::string& created);
991
992 /** Get the latch name from a sync level
993 @param[in] level Latch level to lookup
994 @return 0 if not found. */
995 const char*
996 sync_latch_get_name(latch_level_t level);
997
998 /** Print the filename "basename"
999 @return the basename */
1000 const char*
1001 sync_basename(const char* filename);
1002
1003 /** Register a latch, called when it is created
1004 @param[in] ptr Latch instance that was created
1005 @param[in] filename Filename where it was created
1006 @param[in] line Line number in filename */
1007 void
1008 sync_file_created_register(
1009 const void* ptr,
1010 const char* filename,
1011 uint16_t line);
1012
1013 /** Deregister a latch, called when it is destroyed
1014 @param[in] ptr Latch to be destroyed */
1015 void
1016 sync_file_created_deregister(const void* ptr);
1017
1018 /** Get the string where the file was created. Its format is "name:line"
1019 @param[in] ptr Latch instance
1020 @return created information or "" if can't be found */
1021 std::string
1022 sync_file_created_get(const void* ptr);
1023
1024 #ifdef UNIV_DEBUG
1025
1026 /** All (ordered) latches, used in debugging, must derive from this class. */
1027 struct latch_t {
1028
1029 /** Constructor
1030 @param[in] id The latch ID */
1031 explicit latch_t(latch_id_t id = LATCH_ID_NONE)
1032 UNIV_NOTHROW
1033 :
m_idlatch_t1034 m_id(id),
1035 m_rw_lock(),
1036 m_temp_fsp() { }
1037
1038 /** Destructor */
~latch_tlatch_t1039 virtual ~latch_t() UNIV_NOTHROW { }
1040
1041 /** @return the latch ID */
get_idlatch_t1042 latch_id_t get_id() const
1043 {
1044 return(m_id);
1045 }
1046
1047 /** @return true if it is a rw-lock */
is_rw_locklatch_t1048 bool is_rw_lock() const
1049 UNIV_NOTHROW
1050 {
1051 return(m_rw_lock);
1052 }
1053
1054 /** Print the latch context
1055 @return the string representation */
1056 virtual std::string to_string() const = 0;
1057
1058 /** @return "filename:line" from where the latch was last locked */
1059 virtual std::string locked_from() const = 0;
1060
1061 /** @return the latch level */
get_levellatch_t1062 latch_level_t get_level() const
1063 UNIV_NOTHROW
1064 {
1065 ut_a(m_id != LATCH_ID_NONE);
1066
1067 return(sync_latch_get_level(m_id));
1068 }
1069
1070 /** @return true if the latch is for a temporary file space*/
is_temp_fsplatch_t1071 bool is_temp_fsp() const
1072 UNIV_NOTHROW
1073 {
1074 return(m_temp_fsp);
1075 }
1076
1077 /** Set the temporary tablespace flag. The latch order constraints
1078 are different for intrinsic tables. We don't always acquire the
1079 index->lock. We need to figure out the context and add some special
1080 rules during the checks. */
set_temp_fsplatch_t1081 void set_temp_fsp()
1082 UNIV_NOTHROW
1083 {
1084 ut_ad(get_id() == LATCH_ID_FIL_SPACE);
1085 m_temp_fsp = true;
1086 }
1087
1088 /** @return the latch name, m_id must be set */
get_namelatch_t1089 const char* get_name() const
1090 UNIV_NOTHROW
1091 {
1092 ut_a(m_id != LATCH_ID_NONE);
1093
1094 return(sync_latch_get_name(m_id));
1095 }
1096
1097 /** Latch ID */
1098 latch_id_t m_id;
1099
1100 /** true if it is a rw-lock. In debug mode, rw_lock_t derives from
1101 this class and sets this variable. */
1102 bool m_rw_lock;
1103
1104 /** true if it is an temporary space latch */
1105 bool m_temp_fsp;
1106 };
1107
1108 /** Subclass this to iterate over a thread's acquired latch levels. */
1109 struct sync_check_functor_t {
~sync_check_functor_tsync_check_functor_t1110 virtual ~sync_check_functor_t() { }
1111 virtual bool operator()(const latch_level_t) = 0;
1112 virtual bool result() const = 0;
1113 };
1114
1115 /** Functor to check whether the calling thread owns the btr search mutex. */
1116 struct btrsea_sync_check : public sync_check_functor_t {
1117
1118 /** Constructor
1119 @param[in] has_search_latch true if owns the latch */
btrsea_sync_checkbtrsea_sync_check1120 explicit btrsea_sync_check(bool has_search_latch)
1121 :
1122 m_result(),
1123 m_has_search_latch(has_search_latch) { }
1124
1125 /** Destructor */
~btrsea_sync_checkbtrsea_sync_check1126 virtual ~btrsea_sync_check() { }
1127
1128 /** Called for every latch owned by the calling thread.
1129 @param[in] level Level of the existing latch
1130 @return true if the predicate check is successful */
operatorbtrsea_sync_check1131 virtual bool operator()(const latch_level_t level)
1132 {
1133 /* If calling thread doesn't hold search latch then
1134 check if there are latch level exception provided.
1135
1136 Note: Optimizer has added InnoDB intrinsic table as an
1137 alternative to MyISAM intrinsic table. With this a new
1138 control flow comes into existence, it is:
1139
1140 Server -> Plugin -> SE
1141
1142 Plugin in this case is I_S which is sharing the latch vector
1143 of InnoDB and so there could be lock conflicts. Ideally
1144 the Plugin should use a difference namespace latch vector
1145 as it doesn't have any depedency with SE latching protocol.
1146
1147 Added check that will allow thread to hold I_S latches */
1148
1149 if (!m_has_search_latch
1150 && (level != SYNC_SEARCH_SYS
1151 && level != SYNC_FTS_CACHE
1152 && level != SYNC_TRX_I_S_RWLOCK
1153 && level != SYNC_TRX_I_S_LAST_READ)) {
1154
1155 m_result = true;
1156
1157 return(m_result);
1158 }
1159
1160 return(false);
1161 }
1162
1163 /** @return result from the check */
resultbtrsea_sync_check1164 virtual bool result() const
1165 {
1166 return(m_result);
1167 }
1168
1169 private:
1170 /** True if all OK */
1171 bool m_result;
1172
1173 /** If the caller owns the search latch */
1174 const bool m_has_search_latch;
1175 };
1176
1177 /** Functor to check for dictionay latching constraints. */
1178 struct dict_sync_check : public sync_check_functor_t {
1179
1180 /** Constructor
1181 @param[in] dict_mutex_allow true if the dict mutex
1182 is allowed */
dict_sync_checkdict_sync_check1183 explicit dict_sync_check(bool dict_mutex_allowed)
1184 :
1185 m_result(),
1186 m_dict_mutex_allowed(dict_mutex_allowed) { }
1187
1188 /** Destructor */
~dict_sync_checkdict_sync_check1189 virtual ~dict_sync_check() { }
1190
1191 /** Check the latching constraints
1192 @param[in] level The level held by the thread */
operatordict_sync_check1193 virtual bool operator()(const latch_level_t level)
1194 {
1195 if (!m_dict_mutex_allowed
1196 || (level != SYNC_DICT
1197 && level != SYNC_DICT_OPERATION
1198 && level != SYNC_FTS_CACHE
1199 && level != SYNC_NO_ORDER_CHECK)) {
1200
1201 m_result = true;
1202
1203 return(true);
1204 }
1205
1206 return(false);
1207 }
1208
1209 /** @return the result of the check */
resultdict_sync_check1210 virtual bool result() const
1211 {
1212 return(m_result);
1213 }
1214
1215 private:
1216 /** True if all OK */
1217 bool m_result;
1218
1219 /** True if it is OK to hold the dict mutex */
1220 const bool m_dict_mutex_allowed;
1221 };
1222
1223 /** Functor to check for given latching constraints. */
1224 struct sync_allowed_latches : public sync_check_functor_t {
1225
1226 /** Constructor
1227 @param[in] from first element in an array of latch_level_t
1228 @param[in] to last element in an array of latch_level_t */
sync_allowed_latchessync_allowed_latches1229 sync_allowed_latches(
1230 const latch_level_t* from,
1231 const latch_level_t* to)
1232 :
1233 m_result(),
1234 m_latches(from, to) { }
1235
1236 /** Checks whether the given latch_t violates the latch constraint.
1237 This object maintains a list of allowed latch levels, and if the given
1238 latch belongs to a latch level that is not there in the allowed list,
1239 then it is a violation.
1240
1241 @param[in] latch The latch level to check
1242 @return true if there is a latch ordering violation */
operatorsync_allowed_latches1243 virtual bool operator()(const latch_level_t level)
1244 {
1245 for (latches_t::const_iterator it = m_latches.begin();
1246 it != m_latches.end();
1247 ++it) {
1248
1249 if (level == *it) {
1250
1251 m_result = false;
1252
1253 /* No violation */
1254 return(false);
1255 }
1256 }
1257
1258 return(true);
1259 }
1260
1261 /** @return the result of the check */
resultsync_allowed_latches1262 virtual bool result() const
1263 {
1264 return(m_result);
1265 }
1266
1267 private:
1268 /** Save the result of validation check here
1269 True if all OK */
1270 bool m_result;
1271
1272 typedef std::vector<latch_level_t, ut_allocator<latch_level_t> >
1273 latches_t;
1274
1275 /** List of latch levels that are allowed to be held */
1276 latches_t m_latches;
1277 };
1278
1279 /** Get the latch id from a latch name.
1280 @param[in] id Latch name
1281 @return LATCH_ID_NONE. */
1282 latch_id_t
1283 sync_latch_get_id(const char* name);
1284
1285 typedef ulint rw_lock_flags_t;
1286
1287 /* Flags to specify lock types for rw_lock_own_flagged() */
1288 enum rw_lock_flag_t {
1289 RW_LOCK_FLAG_S = 1 << 0,
1290 RW_LOCK_FLAG_X = 1 << 1,
1291 RW_LOCK_FLAG_SX = 1 << 2
1292 };
1293
1294 #endif /* UNIV_DBEUG */
1295
1296 #endif /* UNIV_INNOCHECKSUM */
1297
1298 #endif /* sync0types_h */
1299