MySQL 8.4.0
Source Code Documentation
thr_mutex.h
Go to the documentation of this file.
1#ifndef THR_MUTEX_INCLUDED
2#define THR_MUTEX_INCLUDED
3
4/* Copyright (c) 2014, 2024, Oracle and/or its affiliates.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is designed to work with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have either included with
16 the program or referenced in the documentation.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License, version 2.0, for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
26
27/**
28 @file include/thr_mutex.h
29 MySQL mutex implementation.
30
31 There are three "layers":
32 1) native_mutex_*()
33 Functions that map directly down to OS primitives.
34 Windows - CriticalSection
35 Other OSes - pthread
36 2) my_mutex_*()
37 Functions that implement SAFE_MUTEX (default for debug),
38 Otherwise native_mutex_*() is used.
39 3) mysql_mutex_*()
40 Functions that include Performance Schema instrumentation.
41 See include/mysql/psi/mysql_thread.h
42*/
43
44#include <assert.h>
45#include <stddef.h>
46#include <stdlib.h>
47#include <sys/types.h>
48
49#include "my_inttypes.h"
50#include "my_macros.h"
51#include "my_thread.h"
52
53/*
54 The following are part of the services ABI:
55 - native_mutex_t
56 - my_mutex_t
57*/
59
60/* Define mutex types, see my_thr_init.c */
61#define MY_MUTEX_INIT_SLOW NULL
62
63/* Can be set in /usr/include/pthread.h */
64#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
65extern native_mutexattr_t my_fast_mutexattr;
66#define MY_MUTEX_INIT_FAST &my_fast_mutexattr
67#else
68#define MY_MUTEX_INIT_FAST NULL
69#endif
70
71/* Can be set in /usr/include/pthread.h */
72#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
73extern native_mutexattr_t my_errorcheck_mutexattr;
74#define MY_MUTEX_INIT_ERRCHK &my_errorcheck_mutexattr
75#else
76#define MY_MUTEX_INIT_ERRCHK NULL
77#endif
78
79static inline int native_mutex_init(native_mutex_t *mutex,
80 const native_mutexattr_t *attr
81 [[maybe_unused]]) {
82#ifdef _WIN32
83 InitializeCriticalSection(mutex);
84 return 0;
85#else
86 return pthread_mutex_init(mutex, attr);
87#endif
88}
89
90static inline int native_mutex_lock(native_mutex_t *mutex) {
91#ifdef _WIN32
92 EnterCriticalSection(mutex);
93 return 0;
94#else
95 return pthread_mutex_lock(mutex);
96#endif
97}
98
99static inline int native_mutex_trylock(native_mutex_t *mutex) {
100#ifdef _WIN32
101 if (TryEnterCriticalSection(mutex)) {
102 /* Don't allow recursive lock */
103 if (mutex->RecursionCount > 1) {
104 LeaveCriticalSection(mutex);
105 return EBUSY;
106 }
107 return 0;
108 }
109 return EBUSY;
110#else
111 return pthread_mutex_trylock(mutex);
112#endif
113}
114
115static inline int native_mutex_unlock(native_mutex_t *mutex) {
116#ifdef _WIN32
117 LeaveCriticalSection(mutex);
118 return 0;
119#else
120 return pthread_mutex_unlock(mutex);
121#endif
122}
123
124static inline int native_mutex_destroy(native_mutex_t *mutex) {
125#ifdef _WIN32
126 DeleteCriticalSection(mutex);
127 return 0;
128#else
129 return pthread_mutex_destroy(mutex);
130#endif
131}
132
133#ifdef SAFE_MUTEX
134/* safe_mutex adds checking to mutex for easier debugging */
135struct safe_mutex_t {
136 native_mutex_t global, mutex;
137 const char *file;
138 uint line, count;
139 my_thread_t thread;
140};
141
142void safe_mutex_global_init();
143int safe_mutex_init(safe_mutex_t *mp, const native_mutexattr_t *attr,
144 const char *file, uint line);
145int safe_mutex_lock(safe_mutex_t *mp, bool try_lock, const char *file,
146 uint line);
147int safe_mutex_unlock(safe_mutex_t *mp, const char *file, uint line);
148int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line);
149
150static inline void safe_mutex_assert_owner(safe_mutex_t *mp) {
151 assert(mp != nullptr);
152 native_mutex_lock(&mp->global);
153 assert(mp->count > 0 && my_thread_equal(my_thread_self(), mp->thread));
154 native_mutex_unlock(&mp->global);
155}
156
157static inline void safe_mutex_assert_not_owner(safe_mutex_t *mp) {
158 assert(mp != nullptr);
159 native_mutex_lock(&mp->global);
160 assert(!mp->count || !my_thread_equal(my_thread_self(), mp->thread));
161 native_mutex_unlock(&mp->global);
162}
163#endif /* SAFE_MUTEX */
164
165static inline int my_mutex_init(my_mutex_t *mp, const native_mutexattr_t *attr
166#ifdef SAFE_MUTEX
167 ,
168 const char *file, uint line
169#endif
170) {
171#ifdef SAFE_MUTEX
172 assert(mp != nullptr);
173 mp->m_u.m_safe_ptr = (safe_mutex_t *)malloc(sizeof(safe_mutex_t));
174 return safe_mutex_init(mp->m_u.m_safe_ptr, attr, file, line);
175#else
176 return native_mutex_init(&mp->m_u.m_native, attr);
177#endif
178}
179
180static inline int my_mutex_lock(my_mutex_t *mp
181#ifdef SAFE_MUTEX
182 ,
183 const char *file, uint line
184#endif
185) {
186#ifdef SAFE_MUTEX
187 assert(mp != nullptr);
188 assert(mp->m_u.m_safe_ptr != nullptr);
189 return safe_mutex_lock(mp->m_u.m_safe_ptr, false, file, line);
190#else
191 return native_mutex_lock(&mp->m_u.m_native);
192#endif
193}
194
195static inline int my_mutex_trylock(my_mutex_t *mp
196#ifdef SAFE_MUTEX
197 ,
198 const char *file, uint line
199#endif
200) {
201#ifdef SAFE_MUTEX
202 assert(mp != nullptr);
203 assert(mp->m_u.m_safe_ptr != nullptr);
204 return safe_mutex_lock(mp->m_u.m_safe_ptr, true, file, line);
205#else
206 return native_mutex_trylock(&mp->m_u.m_native);
207#endif
208}
209
210static inline int my_mutex_unlock(my_mutex_t *mp
211#ifdef SAFE_MUTEX
212 ,
213 const char *file, uint line
214#endif
215) {
216#ifdef SAFE_MUTEX
217 assert(mp != nullptr);
218 assert(mp->m_u.m_safe_ptr != nullptr);
219 return safe_mutex_unlock(mp->m_u.m_safe_ptr, file, line);
220#else
221 return native_mutex_unlock(&mp->m_u.m_native);
222#endif
223}
224
225static inline int my_mutex_destroy(my_mutex_t *mp
226#ifdef SAFE_MUTEX
227 ,
228 const char *file, uint line
229#endif
230) {
231#ifdef SAFE_MUTEX
232 assert(mp != nullptr);
233 assert(mp->m_u.m_safe_ptr != nullptr);
234 int rc = safe_mutex_destroy(mp->m_u.m_safe_ptr, file, line);
235 free(mp->m_u.m_safe_ptr);
236 mp->m_u.m_safe_ptr = nullptr;
237 return rc;
238#else
239 return native_mutex_destroy(&mp->m_u.m_native);
240#endif
241}
242
243#endif /* THR_MUTEX_INCLUDED */
#define malloc(A)
Definition: lexyy.cc:914
#define free(A)
Definition: lexyy.cc:915
Some integer typedefs for easier portability.
Some common macros.
Defines to make different thread packages compatible.
static my_thread_t my_thread_self()
Definition: my_thread.h:75
static int my_thread_equal(my_thread_t t1, my_thread_t t2)
Definition: my_thread.h:83
pthread_t my_thread_t
Definition: my_thread_bits.h:48
static int count
Definition: myisam_ftdump.cc:45
Definition: os0file.h:89
Definition: thr_mutex_bits.h:61
union my_mutex_t::u m_u
static int my_mutex_init(my_mutex_t *mp, const native_mutexattr_t *attr)
Definition: thr_mutex.h:165
static int native_mutex_unlock(native_mutex_t *mutex)
Definition: thr_mutex.h:115
static int native_mutex_destroy(native_mutex_t *mutex)
Definition: thr_mutex.h:124
static int my_mutex_destroy(my_mutex_t *mp)
Definition: thr_mutex.h:225
static int native_mutex_trylock(native_mutex_t *mutex)
Definition: thr_mutex.h:99
static int native_mutex_lock(native_mutex_t *mutex)
Definition: thr_mutex.h:90
static int native_mutex_init(native_mutex_t *mutex, const native_mutexattr_t *attr)
Definition: thr_mutex.h:79
static int my_mutex_lock(my_mutex_t *mp)
Definition: thr_mutex.h:180
static int my_mutex_trylock(my_mutex_t *mp)
Definition: thr_mutex.h:195
static int my_mutex_unlock(my_mutex_t *mp)
Definition: thr_mutex.h:210
ABI for thd_mutex.
pthread_mutex_t native_mutex_t
Definition: thr_mutex_bits.h:55
pthread_mutexattr_t native_mutexattr_t
Definition: thr_mutex_bits.h:56
native_mutex_t m_native
Definition: thr_mutex_bits.h:63
safe_mutex_t * m_safe_ptr
Definition: thr_mutex_bits.h:64