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