1 /*****************************************************************************
2 
3 Copyright (c) 2012, 2015, 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/ut0mutex.h
22 Policy based mutexes.
23 
24 Created 2012-03-24 Sunny Bains.
25 ***********************************************************************/
26 
27 #ifndef UNIV_INNOCHECKSUM
28 
29 #ifndef ut0mutex_h
30 #define ut0mutex_h
31 
32 #include "sync0policy.h"
33 #include "ib0mutex.h"
34 
35 /** Create a typedef using the MutexType<PolicyType>
36 @param[in]	M		Mutex type
37 @param[in[	P		Policy type
38 @param[in]	T		The resulting typedef alias */
39 #define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T;
40 
41 # ifdef HAVE_IB_LINUX_FUTEX
42 UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
43 UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
44 # endif /* HAVE_IB_LINUX_FUTEX */
45 
46 UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex);
47 UT_MUTEX_TYPE(TTASMutex, BlockMutexPolicy, BlockSpinMutex);
48 
49 UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex);
50 UT_MUTEX_TYPE(OSTrackMutex, BlockMutexPolicy, BlockSysMutex);
51 
52 UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex);
53 UT_MUTEX_TYPE(TTASEventMutex, BlockMutexPolicy, BlockSyncArrayMutex);
54 
55 #ifdef MUTEX_FUTEX
56 /** The default mutex type. */
57 typedef FutexMutex ib_mutex_t;
58 typedef BlockFutexMutex ib_bpmutex_t;
59 #define MUTEX_TYPE	"Uses futexes"
60 #elif defined(MUTEX_SYS)
61 typedef SysMutex ib_mutex_t;
62 typedef BlockSysMutex ib_bpmutex_t;
63 #define MUTEX_TYPE	"Uses system mutexes"
64 #elif defined(MUTEX_EVENT)
65 typedef SyncArrayMutex ib_mutex_t;
66 typedef BlockSyncArrayMutex ib_bpmutex_t;
67 #define MUTEX_TYPE	"Uses event mutexes"
68 #else
69 #error "ib_mutex_t type is unknown"
70 #endif /* MUTEX_FUTEX */
71 
72 extern uint	srv_spin_wait_delay;
73 extern ulong	srv_n_spin_wait_rounds;
74 
75 #define mutex_create(I, M)		mutex_init((M), (I),		\
76 						   __FILE__, __LINE__)
77 
78 #define mutex_enter_loc(M,file,line)	(M)->enter(			\
79 					uint32_t(srv_n_spin_wait_rounds), \
80 					uint32_t(srv_spin_wait_delay),	\
81 					file, line)
82 #define mutex_enter(M)			mutex_enter_loc(M, __FILE__, __LINE__)
83 
84 #define mutex_enter_nospin(M)		(M)->enter(			\
85 					0,				\
86 					0,				\
87 					__FILE__, uint32_t(__LINE__))
88 
89 #define mutex_enter_nowait(M)		(M)->trylock(__FILE__,		\
90 						     uint32_t(__LINE__))
91 
92 #define mutex_exit(M)			(M)->exit()
93 
94 #define mutex_free(M)			mutex_destroy(M)
95 
96 #ifdef UNIV_DEBUG
97 /**
98 Checks that the mutex has been initialized. */
99 #define mutex_validate(M)		(M)->validate()
100 
101 /**
102 Checks that the current thread owns the mutex. Works only
103 in the debug version. */
104 #define mutex_own(M)			(M)->is_owned()
105 #else
106 #define mutex_own(M)			/* No op */
107 #define mutex_validate(M)		/* No op */
108 #endif /* UNIV_DEBUG */
109 
110 /** Iterate over the mutex meta data */
111 class MutexMonitor {
112 public:
113 	/** Constructor */
MutexMonitor()114 	MutexMonitor() { }
115 
116 	/** Destructor */
~MutexMonitor()117 	~MutexMonitor() { }
118 
119 	/** Enable the mutex monitoring */
120 	void enable();
121 
122 	/** Disable the mutex monitoring */
123 	void disable();
124 
125 	/** Reset the mutex monitoring values */
126 	void reset();
127 
128 	/** Invoke the callback for each active mutex collection
129 	@param[in,out]	callback	Functor to call
130 	@return false if callback returned false */
131 	template<typename Callback>
iterate(Callback & callback)132 	bool iterate(Callback& callback) const
133 		UNIV_NOTHROW
134 	{
135 		LatchMetaData::iterator	end = latch_meta.end();
136 
137 		for (LatchMetaData::iterator it = latch_meta.begin();
138 		     it != end;
139 		     ++it) {
140 
141 			/* Some of the slots will be null in non-debug mode */
142 
143 			if (latch_meta_t* l= *it) {
144 				if (!callback(*l)) {
145 					return false;
146 				}
147 			}
148 		}
149 
150 		return(true);
151 	}
152 };
153 
154 /** Defined in sync0sync.cc */
155 extern MutexMonitor	mutex_monitor;
156 
157 /**
158 Creates, or rather, initializes a mutex object in a specified memory
159 location (which must be appropriately aligned). The mutex is initialized
160 in the reset state. Explicit freeing of the mutex with mutex_free is
161 necessary only if the memory block containing it is freed.
162 Add the mutex instance to the global mutex list.
163 @param[in,out]	mutex		mutex to initialise
164 @param[in]	id		The mutex ID (Latch ID)
165 @param[in]	filename	Filename from where it was called
166 @param[in]	line		Line number in filename from where called */
167 template <typename Mutex>
mutex_init(Mutex * mutex,latch_id_t id,const char * file_name,uint32_t line)168 void mutex_init(
169 	Mutex*		mutex,
170 	latch_id_t	id,
171 	const char*	file_name,
172 	uint32_t	line)
173 {
174 	new(mutex) Mutex();
175 
176 	mutex->init(id, file_name, line);
177 }
178 
179 /**
180 Removes a mutex instance from the mutex list. The mutex is checked to
181 be in the reset state.
182 @param[in,out]	 mutex		mutex instance to destroy */
183 template <typename Mutex>
mutex_destroy(Mutex * mutex)184 void mutex_destroy(
185 	Mutex*		mutex)
186 {
187 	mutex->destroy();
188 }
189 
190 #endif /* ut0mutex_h */
191 
192 #endif /* UNIV_INNOCHECKSUM */
193