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