18
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
20
You should have received a copy of the GNU General Public License along with
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22
Place, Suite 330, Boston, MA 02111-1307 USA
21
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
St, Fifth Floor, Boston, MA 02110-1301 USA
24
24
*****************************************************************************/
38
38
#include "ut0lst.h"
41
/** Native event (slow)*/
42
typedef HANDLE os_native_event_t;
42
43
/** Native mutex */
43
#define os_fast_mutex_t CRITICAL_SECTION
46
typedef HANDLE os_native_event_t;
48
/** Operating system event */
49
typedef struct os_event_struct os_event_struct_t;
50
/** Operating system event handle */
51
typedef os_event_struct_t* os_event_t;
53
/** An asynchronous signal sent between threads */
54
struct os_event_struct {
55
os_native_event_t handle;
57
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
58
/*!< list of all created events */
44
typedef CRITICAL_SECTION os_fast_mutex_t;
45
/** Native condition variable. */
46
typedef CONDITION_VARIABLE os_cond_t;
61
48
/** Native mutex */
62
typedef pthread_mutex_t os_fast_mutex_t;
49
typedef pthread_mutex_t os_fast_mutex_t;
50
/** Native condition variable */
51
typedef pthread_cond_t os_cond_t;
64
54
/** Operating system event */
65
55
typedef struct os_event_struct os_event_struct_t;
77
71
ib_int64_t signal_count; /*!< this is incremented each time
78
72
the event becomes signaled */
79
pthread_cond_t cond_var; /*!< condition variable is used in
73
os_cond_t cond_var; /*!< condition variable is used in
80
74
waiting for the event */
81
75
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
82
76
/*!< list of all created events */
79
/** Denotes an infinite delay for os_event_wait_time() */
80
#define OS_SYNC_INFINITE_TIME ULINT_UNDEFINED
82
/** Return value of os_event_wait_time() when the time is exceeded */
83
#define OS_SYNC_TIME_EXCEEDED 1
86
85
/** Operating system mutex */
87
86
typedef struct os_mutex_struct os_mutex_str_t;
88
87
/** Operating system mutex handle */
89
88
typedef os_mutex_str_t* os_mutex_t;
91
/** Denotes an infinite delay for os_event_wait_time() */
92
#define OS_SYNC_INFINITE_TIME ((ulint)(-1))
94
/** Return value of os_event_wait_time() when the time is exceeded */
95
#define OS_SYNC_TIME_EXCEEDED 1
97
90
/** Mutex protecting counts and the event and OS 'slow' mutex lists */
98
91
extern os_mutex_t os_sync_mutex;
193
187
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
198
os_event_t event, /*!< in: event to wait */
199
ulint time); /*!< in: timeout in microseconds, or
200
OS_SYNC_INFINITE_TIME */
202
/**********************************************************//**
203
Waits for any event in an OS native event array. Returns if even a single
204
one is signaled or becomes signaled.
205
@return index of the event which was signaled */
208
os_event_wait_multiple(
190
os_event_wait_time_low(
209
191
/*===================*/
210
ulint n, /*!< in: number of events in the
212
os_native_event_t* native_event_array);
213
/*!< in: pointer to an array of event
192
os_event_t event, /*!< in: event to wait */
193
ulint time_in_usec, /*!< in: timeout in
195
OS_SYNC_INFINITE_TIME */
196
ib_int64_t reset_sig_count); /*!< in: zero or the value
197
returned by previous call of
216
199
/*********************************************************//**
217
200
Creates an operating system mutex semaphore. Because these are slow, the
218
201
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
219
202
@return the mutex handle */
224
const char* name); /*!< in: the name of the mutex, if NULL
225
the mutex is created without a name */
205
os_mutex_create(void);
206
/*=================*/
226
207
/**********************************************************//**
227
208
Acquires ownership of a mutex semaphore. */
285
266
/**********************************************************//**
286
267
Atomic compare-and-swap and increment for InnoDB. */
288
#ifdef HAVE_GCC_ATOMIC_BUILTINS
269
#if defined(HAVE_GCC_ATOMIC_BUILTINS)
271
#define HAVE_ATOMIC_BUILTINS
289
273
/**********************************************************//**
290
274
Returns true if swapped, ptr is pointer to target, old_val is value to
291
275
compare to, new_val is the value to swap in. */
292
277
# define os_compare_and_swap(ptr, old_val, new_val) \
293
278
__sync_bool_compare_and_swap(ptr, old_val, new_val)
294
280
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
295
281
os_compare_and_swap(ptr, old_val, new_val)
296
283
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
297
284
os_compare_and_swap(ptr, old_val, new_val)
298
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
286
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_GCC
287
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
299
288
os_compare_and_swap(ptr, old_val, new_val)
289
# define INNODB_RW_LOCKS_USE_ATOMICS
290
# define IB_ATOMICS_STARTUP_MSG \
291
"Mutexes and rw_locks use GCC atomic builtins"
292
# else /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
293
# define IB_ATOMICS_STARTUP_MSG \
294
"Mutexes use GCC atomic builtins, rw_locks do not"
295
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
300
297
/**********************************************************//**
301
298
Returns the resulting value, ptr is pointer to target, amount is the
302
299
amount of increment. */
303
301
# define os_atomic_increment(ptr, amount) \
304
302
__sync_add_and_fetch(ptr, amount)
305
304
# define os_atomic_increment_lint(ptr, amount) \
306
305
os_atomic_increment(ptr, amount)
307
307
# define os_atomic_increment_ulint(ptr, amount) \
308
308
os_atomic_increment(ptr, amount)
309
310
/**********************************************************//**
310
311
Returns the old value of *ptr, atomically sets *ptr to new_val */
311
313
# define os_atomic_test_and_set_byte(ptr, new_val) \
312
__sync_lock_test_and_set(ptr, new_val)
314
__sync_lock_test_and_set(ptr, (byte) new_val)
316
#elif defined(HAVE_SOLARIS_ATOMICS)
318
#define HAVE_ATOMIC_BUILTINS
313
320
/* If not compiling with GCC or GCC doesn't support the atomic
314
321
intrinsics and running on Solaris >= 10 use Solaris atomics */
315
#elif defined(HAVE_SOLARIS_ATOMICS)
316
323
#include <atomic.h>
317
325
/**********************************************************//**
318
326
Returns true if swapped, ptr is pointer to target, old_val is value to
319
327
compare to, new_val is the value to swap in. */
320
329
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
321
330
(atomic_cas_ulong(ptr, old_val, new_val) == old_val)
322
332
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
323
333
((lint)atomic_cas_ulong((ulong_t*) ptr, old_val, new_val) == old_val)
324
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
325
# if SIZEOF_PTHREAD_T == 4
335
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS
336
# if SIZEOF_PTHREAD_T == 4
326
337
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
327
338
((pthread_t)atomic_cas_32(ptr, old_val, new_val) == old_val)
328
339
# elif SIZEOF_PTHREAD_T == 8
332
343
# error "SIZEOF_PTHREAD_T != 4 or 8"
333
344
# endif /* SIZEOF_PTHREAD_T CHECK */
334
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
345
# define INNODB_RW_LOCKS_USE_ATOMICS
346
# define IB_ATOMICS_STARTUP_MSG \
347
"Mutexes and rw_locks use Solaris atomic functions"
348
# else /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
349
# define IB_ATOMICS_STARTUP_MSG \
350
"Mutexes use Solaris atomic functions, rw_locks do not"
351
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
336
353
/**********************************************************//**
337
354
Returns the resulting value, ptr is pointer to target, amount is the
338
355
amount of increment. */
339
357
# define os_atomic_increment_lint(ptr, amount) \
340
358
atomic_add_long_nv((ulong_t*) ptr, amount)
341
360
# define os_atomic_increment_ulint(ptr, amount) \
342
361
atomic_add_long_nv(ptr, amount)
343
363
/**********************************************************//**
344
364
Returns the old value of *ptr, atomically sets *ptr to new_val */
345
366
# define os_atomic_test_and_set_byte(ptr, new_val) \
346
367
atomic_swap_uchar(ptr, new_val)
369
#elif defined(HAVE_WINDOWS_ATOMICS)
371
#define HAVE_ATOMIC_BUILTINS
347
373
/* On Windows, use Windows atomics / interlocked */
348
#elif defined(HAVE_WINDOWS_ATOMICS)
350
375
# define win_cmp_and_xchg InterlockedCompareExchange64
351
376
# define win_xchg_and_add InterlockedExchangeAdd64
353
378
# define win_cmp_and_xchg InterlockedCompareExchange
354
379
# define win_xchg_and_add InterlockedExchangeAdd
356
382
/**********************************************************//**
357
383
Returns true if swapped, ptr is pointer to target, old_val is value to
358
384
compare to, new_val is the value to swap in. */
359
386
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
360
387
(win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
361
389
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
362
390
(win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
363
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
364
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
392
/* windows thread objects can always be passed to windows atomic functions */
393
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
365
394
(InterlockedCompareExchange(ptr, new_val, old_val) == old_val)
366
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
395
# define INNODB_RW_LOCKS_USE_ATOMICS
396
# define IB_ATOMICS_STARTUP_MSG \
397
"Mutexes and rw_locks use Windows interlocked functions"
367
399
/**********************************************************//**
368
400
Returns the resulting value, ptr is pointer to target, amount is the
369
401
amount of increment. */
370
403
# define os_atomic_increment_lint(ptr, amount) \
371
404
(win_xchg_and_add(ptr, amount) + amount)
372
406
# define os_atomic_increment_ulint(ptr, amount) \
373
407
((ulint) (win_xchg_and_add(ptr, amount) + amount))
374
409
/**********************************************************//**
375
410
Returns the old value of *ptr, atomically sets *ptr to new_val.
376
411
InterlockedExchange() operates on LONG, and the LONG will be
378
414
# define os_atomic_test_and_set_byte(ptr, new_val) \
379
415
((byte) InterlockedExchange(ptr, new_val))
380
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
418
# define IB_ATOMICS_STARTUP_MSG \
419
"Mutexes and rw_locks use InnoDB's own implementation"
382
422
#ifndef UNIV_NONINL
383
423
#include "os0sync.ic"