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