38
37
#include "ut0lst.h"
41
/** Native event (slow)*/
42
typedef HANDLE os_native_event_t;
44
typedef CRITICAL_SECTION os_fast_mutex_t;
45
/** Native condition variable. */
46
typedef CONDITION_VARIABLE os_cond_t;
41
#define os_fast_mutex_t CRITICAL_SECTION
43
typedef HANDLE os_native_event_t;
45
typedef struct os_event_struct os_event_struct_t;
46
typedef os_event_struct_t* os_event_t;
48
struct os_event_struct {
49
os_native_event_t handle;
51
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
52
/* list of all created events */
49
typedef pthread_mutex_t os_fast_mutex_t;
50
/** Native condition variable */
51
typedef pthread_cond_t os_cond_t;
55
typedef pthread_mutex_t os_fast_mutex_t;
54
/** Operating system event */
55
57
typedef struct os_event_struct os_event_struct_t;
56
/** Operating system event handle */
57
58
typedef os_event_struct_t* os_event_t;
59
/** An asynchronous signal sent between threads */
60
60
struct os_event_struct {
62
HANDLE handle; /*!< kernel event object, slow,
63
used on older Windows */
65
os_fast_mutex_t os_mutex; /*!< this mutex protects the next
61
os_fast_mutex_t os_mutex; /* this mutex protects the next
67
ibool is_set; /*!< this is TRUE when the event is
63
ibool is_set; /* this is TRUE when the event is
68
64
in the signaled state, i.e., a thread
69
65
does not stop if it tries to wait for
71
ib_int64_t signal_count; /*!< this is incremented each time
67
ib_int64_t signal_count; /* this is incremented each time
72
68
the event becomes signaled */
73
os_cond_t cond_var; /*!< condition variable is used in
69
pthread_cond_t cond_var; /* condition variable is used in
74
70
waiting for the event */
75
71
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
76
/*!< list of all created events */
72
/* list of all created events */
79
/** Operating system mutex */
80
76
typedef struct os_mutex_struct os_mutex_str_t;
81
/** Operating system mutex handle */
82
77
typedef os_mutex_str_t* os_mutex_t;
84
/** Mutex protecting counts and the event and OS 'slow' mutex lists */
79
#define OS_SYNC_INFINITE_TIME ((ulint)(-1))
81
#define OS_SYNC_TIME_EXCEEDED 1
83
/* Mutex protecting counts and the event and OS 'slow' mutex lists */
85
84
extern os_mutex_t os_sync_mutex;
87
/** This is incremented by 1 in os_thread_create and decremented by 1 in
86
/* This is incremented by 1 in os_thread_create and decremented by 1 in
89
88
extern ulint os_thread_count;
168
179
os_event_wait_low(
169
180
/*==============*/
170
os_event_t event, /*!< in: event to wait */
171
ib_int64_t reset_sig_count);/*!< in: zero or the value
181
os_event_t event, /* in: event to wait */
182
ib_int64_t reset_sig_count);/* in: zero or the value
172
183
returned by previous call of
173
184
os_event_reset(). */
175
186
#define os_event_wait(event) os_event_wait_low(event, 0)
177
/*********************************************************//**
188
/**************************************************************
189
Waits for an event object until it is in the signaled state or
190
a timeout is exceeded. In Unix the timeout is always infinite. */
195
/* out: 0 if success,
196
OS_SYNC_TIME_EXCEEDED if timeout
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. */
207
os_event_wait_multiple(
208
/*===================*/
209
/* out: index of the event
210
which was signaled */
211
ulint n, /* in: number of events in the
213
os_native_event_t* native_event_array);
214
/* in: pointer to an array of event
217
/*************************************************************
178
218
Creates an operating system mutex semaphore. Because these are slow, the
179
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
180
@return the mutex handle */
219
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
183
os_mutex_create(void);
184
/*=================*/
185
/**********************************************************//**
224
/* out: the mutex handle */
225
const char* name); /* in: the name of the mutex, if NULL
226
the mutex is created without a name */
227
/**************************************************************
186
228
Acquires ownership of a mutex semaphore. */
191
os_mutex_t mutex); /*!< in: mutex to acquire */
192
/**********************************************************//**
233
os_mutex_t mutex); /* in: mutex to acquire */
234
/**************************************************************
193
235
Releases ownership of a mutex. */
198
os_mutex_t mutex); /*!< in: mutex to release */
199
/**********************************************************//**
240
os_mutex_t mutex); /* in: mutex to release */
241
/**************************************************************
200
242
Frees an mutex object. */
205
os_mutex_t mutex); /*!< in: mutex to free */
206
/**********************************************************//**
247
os_mutex_t mutex); /* in: mutex to free */
248
/**************************************************************
207
249
Acquires ownership of a fast mutex. Currently in Windows this is the same
208
as os_fast_mutex_lock!
209
@return 0 if success, != 0 if was reserved by another thread */
250
as os_fast_mutex_lock! */
212
253
os_fast_mutex_trylock(
213
254
/*==================*/
214
os_fast_mutex_t* fast_mutex); /*!< in: mutex to acquire */
215
/**********************************************************//**
255
/* out: 0 if success, != 0 if
256
was reserved by another
258
os_fast_mutex_t* fast_mutex); /* in: mutex to acquire */
259
/**************************************************************
216
260
Releases ownership of a fast mutex. */
219
263
os_fast_mutex_unlock(
220
264
/*=================*/
221
os_fast_mutex_t* fast_mutex); /*!< in: mutex to release */
222
/*********************************************************//**
265
os_fast_mutex_t* fast_mutex); /* in: mutex to release */
266
/*************************************************************
223
267
Initializes an operating system fast mutex semaphore. */
226
270
os_fast_mutex_init(
227
271
/*===============*/
228
os_fast_mutex_t* fast_mutex); /*!< in: fast mutex */
229
/**********************************************************//**
272
os_fast_mutex_t* fast_mutex); /* in: fast mutex */
273
/**************************************************************
230
274
Acquires ownership of a fast mutex. */
233
277
os_fast_mutex_lock(
234
278
/*===============*/
235
os_fast_mutex_t* fast_mutex); /*!< in: mutex to acquire */
236
/**********************************************************//**
279
os_fast_mutex_t* fast_mutex); /* in: mutex to acquire */
280
/**************************************************************
237
281
Frees an mutex object. */
240
284
os_fast_mutex_free(
241
285
/*===============*/
242
os_fast_mutex_t* fast_mutex); /*!< in: mutex to free */
244
/**********************************************************//**
245
Atomic compare-and-swap and increment for InnoDB. */
247
#if defined(HAVE_GCC_ATOMIC_BUILTINS)
249
#define HAVE_ATOMIC_BUILTINS
251
/**********************************************************//**
286
os_fast_mutex_t* fast_mutex); /* in: mutex to free */
288
#ifdef HAVE_GCC_ATOMIC_BUILTINS
289
/**************************************************************
290
Atomic compare-and-swap for InnoDB. Currently requires GCC atomic builtins.
252
291
Returns true if swapped, ptr is pointer to target, old_val is value to
253
292
compare to, new_val is the value to swap in. */
255
# define os_compare_and_swap(ptr, old_val, new_val) \
293
#define os_compare_and_swap(ptr, old_val, new_val) \
256
294
__sync_bool_compare_and_swap(ptr, old_val, new_val)
258
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
259
os_compare_and_swap(ptr, old_val, new_val)
261
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
262
os_compare_and_swap(ptr, old_val, new_val)
264
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_GCC
265
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
266
os_compare_and_swap(ptr, old_val, new_val)
267
# define INNODB_RW_LOCKS_USE_ATOMICS
268
# define IB_ATOMICS_STARTUP_MSG \
269
"Mutexes and rw_locks use GCC atomic builtins"
270
# else /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
271
# define IB_ATOMICS_STARTUP_MSG \
272
"Mutexes use GCC atomic builtins, rw_locks do not"
273
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
275
/**********************************************************//**
296
/**************************************************************
297
Atomic increment for InnoDB. Currently requires GCC atomic builtins.
276
298
Returns the resulting value, ptr is pointer to target, amount is the
277
299
amount of increment. */
279
# define os_atomic_increment(ptr, amount) \
300
#define os_atomic_increment(ptr, amount) \
280
301
__sync_add_and_fetch(ptr, amount)
282
# define os_atomic_increment_lint(ptr, amount) \
283
os_atomic_increment(ptr, amount)
285
# define os_atomic_increment_ulint(ptr, amount) \
286
os_atomic_increment(ptr, amount)
288
/**********************************************************//**
289
Returns the old value of *ptr, atomically sets *ptr to new_val */
291
# define os_atomic_test_and_set_byte(ptr, new_val) \
292
__sync_lock_test_and_set(ptr, (byte) new_val)
294
#elif defined(HAVE_SOLARIS_ATOMICS)
296
#define HAVE_ATOMIC_BUILTINS
298
/* If not compiling with GCC or GCC doesn't support the atomic
299
intrinsics and running on Solaris >= 10 use Solaris atomics */
303
/**********************************************************//**
304
Returns true if swapped, ptr is pointer to target, old_val is value to
305
compare to, new_val is the value to swap in. */
307
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
308
(atomic_cas_ulong(ptr, old_val, new_val) == old_val)
310
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
311
((lint)atomic_cas_ulong((ulong_t*) ptr, old_val, new_val) == old_val)
313
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS
314
# if SIZEOF_PTHREAD_T == 4
315
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
316
((pthread_t)atomic_cas_32(ptr, old_val, new_val) == old_val)
317
# elif SIZEOF_PTHREAD_T == 8
318
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
319
((pthread_t)atomic_cas_64(ptr, old_val, new_val) == old_val)
321
# error "SIZEOF_PTHREAD_T != 4 or 8"
322
# endif /* SIZEOF_PTHREAD_T CHECK */
323
# define INNODB_RW_LOCKS_USE_ATOMICS
324
# define IB_ATOMICS_STARTUP_MSG \
325
"Mutexes and rw_locks use Solaris atomic functions"
326
# else /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
327
# define IB_ATOMICS_STARTUP_MSG \
328
"Mutexes use Solaris atomic functions, rw_locks do not"
329
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
331
/**********************************************************//**
332
Returns the resulting value, ptr is pointer to target, amount is the
333
amount of increment. */
335
# define os_atomic_increment_lint(ptr, amount) \
336
atomic_add_long_nv((ulong_t*) ptr, amount)
338
# define os_atomic_increment_ulint(ptr, amount) \
339
atomic_add_long_nv(ptr, amount)
341
/**********************************************************//**
342
Returns the old value of *ptr, atomically sets *ptr to new_val */
344
# define os_atomic_test_and_set_byte(ptr, new_val) \
345
atomic_swap_uchar(ptr, new_val)
347
#elif defined(HAVE_WINDOWS_ATOMICS)
349
#define HAVE_ATOMIC_BUILTINS
351
/* On Windows, use Windows atomics / interlocked */
353
# define win_cmp_and_xchg InterlockedCompareExchange64
354
# define win_xchg_and_add InterlockedExchangeAdd64
356
# define win_cmp_and_xchg InterlockedCompareExchange
357
# define win_xchg_and_add InterlockedExchangeAdd
360
/**********************************************************//**
361
Returns true if swapped, ptr is pointer to target, old_val is value to
362
compare to, new_val is the value to swap in. */
364
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
365
(win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
367
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
368
(win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
370
/* windows thread objects can always be passed to windows atomic functions */
371
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
372
(InterlockedCompareExchange(ptr, new_val, old_val) == old_val)
373
# define INNODB_RW_LOCKS_USE_ATOMICS
374
# define IB_ATOMICS_STARTUP_MSG \
375
"Mutexes and rw_locks use Windows interlocked functions"
377
/**********************************************************//**
378
Returns the resulting value, ptr is pointer to target, amount is the
379
amount of increment. */
381
# define os_atomic_increment_lint(ptr, amount) \
382
(win_xchg_and_add(ptr, amount) + amount)
384
# define os_atomic_increment_ulint(ptr, amount) \
385
((ulint) (win_xchg_and_add(ptr, amount) + amount))
387
/**********************************************************//**
388
Returns the old value of *ptr, atomically sets *ptr to new_val.
389
InterlockedExchange() operates on LONG, and the LONG will be
392
# define os_atomic_test_and_set_byte(ptr, new_val) \
393
((byte) InterlockedExchange(ptr, new_val))
396
# define IB_ATOMICS_STARTUP_MSG \
397
"Mutexes and rw_locks use InnoDB's own implementation"
303
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
400
305
#ifndef UNIV_NONINL
401
306
#include "os0sync.ic"