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