1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
/*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
/**************************************************//**
@file include/os0sync.ic
The interface to the operating system synchronization primitives.
Created 9/6/1995 Heikki Tuuri
*******************************************************/
#ifdef __WIN__
#include <winbase.h>
#endif
/**********************************************************//**
Acquires ownership of a fast mutex.
@return 0 if success, != 0 if was reserved by another thread */
UNIV_INLINE
ulint
os_fast_mutex_trylock(
/*==================*/
os_fast_mutex_t* fast_mutex) /*!< in: mutex to acquire */
{
fast_mutex_t* mutex = &fast_mutex->mutex;
#ifdef __WIN__
return(!TryEnterCriticalSection(mutex));
#else
/* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock
so that it returns 0 on success. In the operating system
libraries, HP-UX-10.20 follows the old Posix 1003.4a Draft 4 and
returns 1 on success (but MySQL remaps that to 0), while Linux,
FreeBSD, Solaris, AIX, Tru64 Unix, HP-UX-11.0 return 0 on success. */
return((ulint) pthread_mutex_trylock(mutex));
#endif
}
#ifdef UNIV_PFS_MUTEX
/*********************************************************//**
NOTE! Please use the corresponding macro os_fast_mutex_init(), not directly
this function!
A wrapper function for os_fast_mutex_init_func(). Initializes an operating
system fast mutex semaphore. */
UNIV_INLINE
void
pfs_os_fast_mutex_init(
/*===================*/
PSI_mutex_key key, /*!< in: Performance Schema
key */
os_fast_mutex_t* fast_mutex) /*!< out: fast mutex */
{
#ifdef HAVE_PSI_MUTEX_INTERFACE
fast_mutex->pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, &fast_mutex->mutex);
#else
fast_mutex->pfs_psi = NULL;
#endif
os_fast_mutex_init_func(&fast_mutex->mutex);
}
/******************************************************************//**
NOTE! Please use the corresponding macro os_fast_mutex_free(), not directly
this function!
Wrapper function for pfs_os_fast_mutex_free(). Also destroys the performance
schema probes when freeing the mutex */
UNIV_INLINE
void
pfs_os_fast_mutex_free(
/*===================*/
os_fast_mutex_t* fast_mutex) /*!< in/out: mutex */
{
#ifdef HAVE_PSI_MUTEX_INTERFACE
if (fast_mutex->pfs_psi != NULL)
PSI_MUTEX_CALL(destroy_mutex)(fast_mutex->pfs_psi);
#endif
fast_mutex->pfs_psi = NULL;
os_fast_mutex_free_func(&fast_mutex->mutex);
}
/**********************************************************//**
NOTE! Please use the corresponding macro os_fast_mutex_lock, not directly
this function!
Wrapper function of os_fast_mutex_lock_func. Acquires ownership of a fast
mutex. */
UNIV_INLINE
void
pfs_os_fast_mutex_lock(
/*===================*/
os_fast_mutex_t* fast_mutex, /*!< in/out: mutex to acquire */
const char* file_name, /*!< in: file name where
locked */
ulint line) /*!< in: line where locked */
{
#ifdef HAVE_PSI_MUTEX_INTERFACE
if (fast_mutex->pfs_psi != NULL)
{
PSI_mutex_locker* locker;
PSI_mutex_locker_state state;
locker = PSI_MUTEX_CALL(start_mutex_wait)(
&state, fast_mutex->pfs_psi,
PSI_MUTEX_LOCK, file_name,
static_cast<uint>(line));
os_fast_mutex_lock_func(&fast_mutex->mutex);
if (locker != NULL)
PSI_MUTEX_CALL(end_mutex_wait)(locker, 0);
}
else
#endif
{
os_fast_mutex_lock_func(&fast_mutex->mutex);
}
return;
}
/**********************************************************//**
NOTE! Please use the corresponding macro os_fast_mutex_unlock, not directly
this function!
Wrapper function of os_fast_mutex_unlock_func. Releases ownership of a
fast mutex. */
UNIV_INLINE
void
pfs_os_fast_mutex_unlock(
/*=====================*/
os_fast_mutex_t* fast_mutex) /*!< in/out: mutex to release */
{
#ifdef HAVE_PSI_MUTEX_INTERFACE
if (fast_mutex->pfs_psi != NULL)
PSI_MUTEX_CALL(unlock_mutex)(fast_mutex->pfs_psi);
#endif
os_fast_mutex_unlock_func(&fast_mutex->mutex);
}
#endif /* UNIV_PFS_MUTEX */
#ifdef HAVE_WINDOWS_ATOMICS
/* Use inline functions to make 64 and 32 bit versions of windows atomic
functions so that typecasts are evaluated at compile time. Take advantage
that lint is either __int64 or long int and windows atomic functions work
on __int64 and LONG */
/**********************************************************//**
Atomic compare and exchange of unsigned integers.
@return value found before the exchange.
If it is not equal to old_value the exchange did not happen. */
UNIV_INLINE
lint
win_cmp_and_xchg_lint(
/*==================*/
volatile lint* ptr, /*!< in/out: source/destination */
lint new_val, /*!< in: exchange value */
lint old_val) /*!< in: value to compare to */
{
# ifdef _WIN64
return(InterlockedCompareExchange64(ptr, new_val, old_val));
# else
return(InterlockedCompareExchange(ptr, new_val, old_val));
# endif
}
/**********************************************************//**
Atomic addition of signed integers.
@return Initial value of the variable pointed to by ptr */
UNIV_INLINE
lint
win_xchg_and_add(
/*=============*/
volatile lint* ptr, /*!< in/out: address of destination */
lint val) /*!< in: number to be added */
{
#ifdef _WIN64
return(InterlockedExchangeAdd64(ptr, val));
#else
return(InterlockedExchangeAdd(ptr, val));
#endif
}
/**********************************************************//**
Atomic compare and exchange of unsigned integers.
@return value found before the exchange.
If it is not equal to old_value the exchange did not happen. */
UNIV_INLINE
ulint
win_cmp_and_xchg_ulint(
/*===================*/
volatile ulint* ptr, /*!< in/out: source/destination */
ulint new_val, /*!< in: exchange value */
ulint old_val) /*!< in: value to compare to */
{
return((ulint) win_cmp_and_xchg_lint(
(volatile lint*) ptr,
(lint) new_val,
(lint) old_val));
}
/**********************************************************//**
Atomic compare and exchange of 32-bit unsigned integers.
@return value found before the exchange.
If it is not equal to old_value the exchange did not happen. */
UNIV_INLINE
DWORD
win_cmp_and_xchg_dword(
/*===================*/
volatile DWORD* ptr, /*!< in/out: source/destination */
DWORD new_val, /*!< in: exchange value */
DWORD old_val) /*!< in: value to compare to */
{
ut_ad(sizeof(DWORD) == sizeof(LONG)); /* We assume this. */
return(InterlockedCompareExchange(
(volatile LONG*) ptr,
(LONG) new_val,
(LONG) old_val));
}
#endif /* HAVE_WINDOWS_ATOMICS */
/**********************************************************//**
Acquires ownership of a fast mutex. Implies a full memory barrier even on
platforms such as PowerPC where this is not normally required.
@return 0 if success, != 0 if was reserved by another thread */
UNIV_INLINE
ulint
os_fast_mutex_trylock_full_barrier(
/*==================*/
os_fast_mutex_t* fast_mutex) /*!< in: mutex to acquire */
{
#ifdef __WIN__
if (TryEnterCriticalSection(&fast_mutex->mutex)) {
return(0);
} else {
return(1);
}
#else
/* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock
so that it returns 0 on success. In the operating system
libraries, HP-UX-10.20 follows the old Posix 1003.4a Draft 4 and
returns 1 on success (but MySQL remaps that to 0), while Linux,
FreeBSD, Solaris, AIX, Tru64 Unix, HP-UX-11.0 return 0 on success. */
#ifdef __powerpc__
os_mb;
#endif
return((ulint) pthread_mutex_trylock(&fast_mutex->mutex));
#endif
}
|