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
*****************************************************************************/
285
285
/**********************************************************//**
286
286
Atomic compare-and-swap and increment for InnoDB. */
288
#ifdef HAVE_GCC_ATOMIC_BUILTINS
288
#if defined(HAVE_GCC_ATOMIC_BUILTINS)
290
#define HAVE_ATOMIC_BUILTINS
289
292
/**********************************************************//**
290
293
Returns true if swapped, ptr is pointer to target, old_val is value to
291
294
compare to, new_val is the value to swap in. */
292
296
# define os_compare_and_swap(ptr, old_val, new_val) \
293
297
__sync_bool_compare_and_swap(ptr, old_val, new_val)
294
299
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
295
300
os_compare_and_swap(ptr, old_val, new_val)
296
302
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
297
303
os_compare_and_swap(ptr, old_val, new_val)
298
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
305
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_GCC
306
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
299
307
os_compare_and_swap(ptr, old_val, new_val)
308
# define INNODB_RW_LOCKS_USE_ATOMICS
309
# define IB_ATOMICS_STARTUP_MSG \
310
"Mutexes and rw_locks use GCC atomic builtins"
311
# else /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
312
# define IB_ATOMICS_STARTUP_MSG \
313
"Mutexes use GCC atomic builtins, rw_locks do not"
314
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
300
316
/**********************************************************//**
301
317
Returns the resulting value, ptr is pointer to target, amount is the
302
318
amount of increment. */
303
320
# define os_atomic_increment(ptr, amount) \
304
321
__sync_add_and_fetch(ptr, amount)
305
323
# define os_atomic_increment_lint(ptr, amount) \
306
324
os_atomic_increment(ptr, amount)
307
326
# define os_atomic_increment_ulint(ptr, amount) \
308
327
os_atomic_increment(ptr, amount)
309
329
/**********************************************************//**
310
330
Returns the old value of *ptr, atomically sets *ptr to new_val */
311
332
# define os_atomic_test_and_set_byte(ptr, new_val) \
312
333
__sync_lock_test_and_set(ptr, new_val)
335
#elif defined(HAVE_SOLARIS_ATOMICS)
337
#define HAVE_ATOMIC_BUILTINS
313
339
/* If not compiling with GCC or GCC doesn't support the atomic
314
340
intrinsics and running on Solaris >= 10 use Solaris atomics */
315
#elif defined(HAVE_SOLARIS_ATOMICS)
316
342
#include <atomic.h>
317
344
/**********************************************************//**
318
345
Returns true if swapped, ptr is pointer to target, old_val is value to
319
346
compare to, new_val is the value to swap in. */
320
348
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
321
349
(atomic_cas_ulong(ptr, old_val, new_val) == old_val)
322
351
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
323
352
((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
354
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS
355
# if SIZEOF_PTHREAD_T == 4
326
356
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
327
357
((pthread_t)atomic_cas_32(ptr, old_val, new_val) == old_val)
328
358
# elif SIZEOF_PTHREAD_T == 8
332
362
# error "SIZEOF_PTHREAD_T != 4 or 8"
333
363
# endif /* SIZEOF_PTHREAD_T CHECK */
334
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
364
# define INNODB_RW_LOCKS_USE_ATOMICS
365
# define IB_ATOMICS_STARTUP_MSG \
366
"Mutexes and rw_locks use Solaris atomic functions"
367
# else /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
368
# define IB_ATOMICS_STARTUP_MSG \
369
"Mutexes use Solaris atomic functions, rw_locks do not"
370
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
336
372
/**********************************************************//**
337
373
Returns the resulting value, ptr is pointer to target, amount is the
338
374
amount of increment. */
339
376
# define os_atomic_increment_lint(ptr, amount) \
340
377
atomic_add_long_nv((ulong_t*) ptr, amount)
341
379
# define os_atomic_increment_ulint(ptr, amount) \
342
380
atomic_add_long_nv(ptr, amount)
343
382
/**********************************************************//**
344
383
Returns the old value of *ptr, atomically sets *ptr to new_val */
345
385
# define os_atomic_test_and_set_byte(ptr, new_val) \
346
386
atomic_swap_uchar(ptr, new_val)
388
#elif defined(HAVE_WINDOWS_ATOMICS)
390
#define HAVE_ATOMIC_BUILTINS
347
392
/* On Windows, use Windows atomics / interlocked */
348
#elif defined(HAVE_WINDOWS_ATOMICS)
350
394
# define win_cmp_and_xchg InterlockedCompareExchange64
351
395
# define win_xchg_and_add InterlockedExchangeAdd64
353
397
# define win_cmp_and_xchg InterlockedCompareExchange
354
398
# define win_xchg_and_add InterlockedExchangeAdd
356
401
/**********************************************************//**
357
402
Returns true if swapped, ptr is pointer to target, old_val is value to
358
403
compare to, new_val is the value to swap in. */
359
405
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
360
406
(win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
361
408
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
362
409
(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) \
411
/* windows thread objects can always be passed to windows atomic functions */
412
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
365
413
(InterlockedCompareExchange(ptr, new_val, old_val) == old_val)
366
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
414
# define INNODB_RW_LOCKS_USE_ATOMICS
415
# define IB_ATOMICS_STARTUP_MSG \
416
"Mutexes and rw_locks use Windows interlocked functions"
367
418
/**********************************************************//**
368
419
Returns the resulting value, ptr is pointer to target, amount is the
369
420
amount of increment. */
370
422
# define os_atomic_increment_lint(ptr, amount) \
371
423
(win_xchg_and_add(ptr, amount) + amount)
372
425
# define os_atomic_increment_ulint(ptr, amount) \
373
426
((ulint) (win_xchg_and_add(ptr, amount) + amount))
374
428
/**********************************************************//**
375
429
Returns the old value of *ptr, atomically sets *ptr to new_val.
376
430
InterlockedExchange() operates on LONG, and the LONG will be
378
433
# define os_atomic_test_and_set_byte(ptr, new_val) \
379
434
((byte) InterlockedExchange(ptr, new_val))
380
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
437
# define IB_ATOMICS_STARTUP_MSG \
438
"Mutexes and rw_locks use InnoDB's own implementation"
382
441
#ifndef UNIV_NONINL
383
442
#include "os0sync.ic"