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