1/*****************************************************************************
2
3Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/******************************************************************//**
21@file include/ut0mutex.h
22Policy based mutexes.
23
24Created 2012-03-24 Sunny Bains.
25***********************************************************************/
26
27#ifndef UNIV_INNOCHECKSUM
28
29#ifndef ut0mutex_h
30#define ut0mutex_h
31
32extern uint srv_spin_wait_delay;
33extern ulong srv_n_spin_wait_rounds;
34
35#include "sync0policy.h"
36#include "ib0mutex.h"
37#include <set>
38
39/** Create a typedef using the MutexType<PolicyType>
40@param[in] M Mutex type
41@param[in[ P Policy type
42@param[in] T The resulting typedef alias */
43#define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T;
44
45typedef OSMutex EventMutex;
46
47# ifdef HAVE_IB_LINUX_FUTEX
48UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
49UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
50# endif /* HAVE_IB_LINUX_FUTEX */
51
52UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex);
53UT_MUTEX_TYPE(TTASMutex, BlockMutexPolicy, BlockSpinMutex);
54
55UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex);
56UT_MUTEX_TYPE(OSTrackMutex, BlockMutexPolicy, BlockSysMutex);
57
58UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex);
59UT_MUTEX_TYPE(TTASEventMutex, BlockMutexPolicy, BlockSyncArrayMutex);
60
61#ifdef MUTEX_FUTEX
62/** The default mutex type. */
63typedef FutexMutex ib_mutex_t;
64typedef BlockFutexMutex ib_bpmutex_t;
65#define MUTEX_TYPE "Uses futexes"
66#elif defined(MUTEX_SYS)
67typedef SysMutex ib_mutex_t;
68typedef BlockSysMutex ib_bpmutex_t;
69#define MUTEX_TYPE "Uses system mutexes"
70#elif defined(MUTEX_EVENT)
71typedef SyncArrayMutex ib_mutex_t;
72typedef BlockSyncArrayMutex ib_bpmutex_t;
73#define MUTEX_TYPE "Uses event mutexes"
74#else
75#error "ib_mutex_t type is unknown"
76#endif /* MUTEX_FUTEX */
77
78extern uint srv_spin_wait_delay;
79extern ulong srv_n_spin_wait_rounds;
80
81#define mutex_create(I, M) mutex_init((M), (I), \
82 __FILE__, __LINE__)
83
84#define mutex_enter_loc(M,file,line) (M)->enter( \
85 uint32_t(srv_n_spin_wait_rounds), \
86 uint32_t(srv_spin_wait_delay), \
87 file, line)
88#define mutex_enter(M) mutex_enter_loc(M, __FILE__, __LINE__)
89
90#define mutex_enter_nospin(M) (M)->enter( \
91 0, \
92 0, \
93 __FILE__, uint32_t(__LINE__))
94
95#define mutex_enter_nowait(M) (M)->trylock(__FILE__, \
96 uint32_t(__LINE__))
97
98#define mutex_exit(M) (M)->exit()
99
100#define mutex_free(M) mutex_destroy(M)
101
102#ifdef UNIV_DEBUG
103/**
104Checks that the mutex has been initialized. */
105#define mutex_validate(M) (M)->validate()
106
107/**
108Checks that the current thread owns the mutex. Works only
109in the debug version. */
110#define mutex_own(M) (M)->is_owned()
111#else
112#define mutex_own(M) /* No op */
113#define mutex_validate(M) /* No op */
114#endif /* UNIV_DEBUG */
115
116/** Iterate over the mutex meta data */
117class MutexMonitor {
118public:
119 /** Constructor */
120 MutexMonitor() { }
121
122 /** Destructor */
123 ~MutexMonitor() { }
124
125 /** Enable the mutex monitoring */
126 void enable();
127
128 /** Disable the mutex monitoring */
129 void disable();
130
131 /** Reset the mutex monitoring values */
132 void reset();
133
134 /** Invoke the callback for each active mutex collection
135 @param[in,out] callback Functor to call
136 @return false if callback returned false */
137 template<typename Callback>
138 bool iterate(Callback& callback) const
139 UNIV_NOTHROW
140 {
141 LatchMetaData::iterator end = latch_meta.end();
142
143 for (LatchMetaData::iterator it = latch_meta.begin();
144 it != end;
145 ++it) {
146
147 /* Some of the slots will be null in non-debug mode */
148
149 if (*it == NULL) {
150 continue;
151 }
152
153 latch_meta_t* latch_meta = *it;
154
155 bool ret = callback(*latch_meta);
156
157 if (!ret) {
158 return(ret);
159 }
160 }
161
162 return(true);
163 }
164};
165
166/** Defined in sync0sync.cc */
167extern MutexMonitor mutex_monitor;
168
169/**
170Creates, or rather, initializes a mutex object in a specified memory
171location (which must be appropriately aligned). The mutex is initialized
172in the reset state. Explicit freeing of the mutex with mutex_free is
173necessary only if the memory block containing it is freed.
174Add the mutex instance to the global mutex list.
175@param[in,out] mutex mutex to initialise
176@param[in] id The mutex ID (Latch ID)
177@param[in] filename Filename from where it was called
178@param[in] line Line number in filename from where called */
179template <typename Mutex>
180void mutex_init(
181 Mutex* mutex,
182 latch_id_t id,
183 const char* file_name,
184 uint32_t line)
185{
186 new(mutex) Mutex();
187
188 mutex->init(id, file_name, line);
189}
190
191/**
192Removes a mutex instance from the mutex list. The mutex is checked to
193be in the reset state.
194@param[in,out] mutex mutex instance to destroy */
195template <typename Mutex>
196void mutex_destroy(
197 Mutex* mutex)
198{
199 mutex->destroy();
200}
201
202#endif /* ut0mutex_h */
203
204#endif /* UNIV_INNOCHECKSUM */
205