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