mirror of
https://github.com/MariaDB/server.git
synced 2025-11-30 05:23:50 +03:00
MDEV-10813 - Clean-up InnoDB atomics, memory barriers and mutexes
Clean-up periodic mutex/rwlock waiters wake up. This was a hack needed to workaround broken mutexes/rwlocks implementation. We must have sane implementations now and don't need these anymore: release thread is guaranteed to wake up waiters. Removed redundant ifdef that has equivalent code in both branches. Removed os0atomic.h and os0atomic.ic: not used anymore. Clean-up unused cmake checks.
This commit is contained in:
@@ -1,397 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
|
||||||
Copyright (c) 2008, Google Inc.
|
|
||||||
|
|
||||||
Portions of this file contain modifications contributed and copyrighted by
|
|
||||||
Google, Inc. Those modifications are gratefully acknowledged and are described
|
|
||||||
briefly in the InnoDB documentation. The contributions by Google are
|
|
||||||
incorporated with their permission, and subject to the conditions contained in
|
|
||||||
the file COPYING.Google.
|
|
||||||
|
|
||||||
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/os0atomic.h
|
|
||||||
Macros for using atomics
|
|
||||||
|
|
||||||
Created 2012-09-23 Sunny Bains (Split from os0sync.h)
|
|
||||||
*******************************************************/
|
|
||||||
|
|
||||||
#ifndef os0atomic_h
|
|
||||||
#define os0atomic_h
|
|
||||||
|
|
||||||
#include "univ.i"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
/** On Windows, InterlockedExchange operates on LONG variable */
|
|
||||||
typedef LONG lock_word_t;
|
|
||||||
|
|
||||||
#elif defined(MUTEX_FUTEX)
|
|
||||||
|
|
||||||
typedef int lock_word_t;
|
|
||||||
|
|
||||||
# else
|
|
||||||
|
|
||||||
typedef ulint lock_word_t;
|
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
#if defined __i386__ || defined __x86_64__ || defined _M_IX86 \
|
|
||||||
|| defined _M_X64 || defined __WIN__
|
|
||||||
|
|
||||||
#define IB_STRONG_MEMORY_MODEL
|
|
||||||
|
|
||||||
#endif /* __i386__ || __x86_64__ || _M_IX86 || _M_X64 || __WIN__ */
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
Atomic compare-and-swap and increment for InnoDB. */
|
|
||||||
|
|
||||||
/** Do an atomic test and set.
|
|
||||||
@param[in/out] ptr Memory location to set
|
|
||||||
@param[in] new_val new value
|
|
||||||
@return old value of memory location. */
|
|
||||||
UNIV_INLINE
|
|
||||||
lock_word_t
|
|
||||||
os_atomic_test_and_set(
|
|
||||||
volatile lock_word_t* ptr,
|
|
||||||
lock_word_t new_val);
|
|
||||||
|
|
||||||
|
|
||||||
/** Do an atomic compare and set
|
|
||||||
@param[in/out] ptr Memory location to set
|
|
||||||
@param[in] old_val old value to compare
|
|
||||||
@param[in] new_val new value to set
|
|
||||||
@return the value of ptr before the operation. */
|
|
||||||
UNIV_INLINE
|
|
||||||
lock_word_t
|
|
||||||
os_atomic_val_compare_and_swap(
|
|
||||||
volatile lock_word_t* ptr,
|
|
||||||
lock_word_t old_val,
|
|
||||||
lock_word_t new_val);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
Atomic compare and exchange of signed integers (both 32 and 64 bit).
|
|
||||||
@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 */
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
Returns true if swapped, ptr is pointer to target, old_val is value to
|
|
||||||
compare to, new_val is the value to swap in. */
|
|
||||||
|
|
||||||
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
|
|
||||||
(win_cmp_and_xchg_lint(ptr, new_val, old_val) == old_val)
|
|
||||||
|
|
||||||
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
|
|
||||||
(win_cmp_and_xchg_ulint(ptr, new_val, old_val) == old_val)
|
|
||||||
|
|
||||||
# define os_compare_and_swap_uint32(ptr, old_val, new_val) \
|
|
||||||
(InterlockedCompareExchange(ptr, new_val, old_val) == old_val)
|
|
||||||
|
|
||||||
/* windows thread objects can always be passed to windows atomic functions */
|
|
||||||
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
|
|
||||||
(win_cmp_and_xchg_dword(ptr, new_val, old_val) == old_val)
|
|
||||||
|
|
||||||
# define INNODB_RW_LOCKS_USE_ATOMICS
|
|
||||||
# define IB_ATOMICS_STARTUP_MSG \
|
|
||||||
"Mutexes and rw_locks use Windows interlocked functions"
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
Returns the resulting value, ptr is pointer to target, amount is the
|
|
||||||
amount of increment. */
|
|
||||||
|
|
||||||
# define os_atomic_increment_lint(ptr, amount) \
|
|
||||||
(win_xchg_and_add(ptr, amount) + amount)
|
|
||||||
|
|
||||||
# define os_atomic_increment_ulint(ptr, amount) \
|
|
||||||
(static_cast<ulint>(win_xchg_and_add( \
|
|
||||||
reinterpret_cast<volatile lint*>(ptr), \
|
|
||||||
static_cast<lint>(amount))) \
|
|
||||||
+ static_cast<ulint>(amount))
|
|
||||||
|
|
||||||
# define os_atomic_increment_uint32(ptr, amount) \
|
|
||||||
(static_cast<ulint>(InterlockedExchangeAdd( \
|
|
||||||
reinterpret_cast<long*>(ptr), \
|
|
||||||
static_cast<long>(amount))) \
|
|
||||||
+ static_cast<ulint>(amount))
|
|
||||||
|
|
||||||
# define os_atomic_increment_uint64(ptr, amount) \
|
|
||||||
(static_cast<ib_uint64_t>(InterlockedExchangeAdd64( \
|
|
||||||
reinterpret_cast<LONGLONG*>(ptr), \
|
|
||||||
static_cast<LONGLONG>(amount))) \
|
|
||||||
+ static_cast<ib_uint64_t>(amount))
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
Returns the resulting value, ptr is pointer to target, amount is the
|
|
||||||
amount to decrement. There is no atomic substract function on Windows */
|
|
||||||
|
|
||||||
# define os_atomic_decrement_lint(ptr, amount) \
|
|
||||||
(win_xchg_and_add(ptr, -(static_cast<lint>(amount))) - amount)
|
|
||||||
|
|
||||||
# define os_atomic_decrement_ulint(ptr, amount) \
|
|
||||||
(static_cast<ulint>(win_xchg_and_add( \
|
|
||||||
reinterpret_cast<volatile lint*>(ptr), \
|
|
||||||
-(static_cast<lint>(amount)))) \
|
|
||||||
- static_cast<ulint>(amount))
|
|
||||||
|
|
||||||
# define os_atomic_decrement_uint32(ptr, amount) \
|
|
||||||
(static_cast<ib_uint32_t>(InterlockedExchangeAdd( \
|
|
||||||
reinterpret_cast<long*>(ptr), \
|
|
||||||
-(static_cast<long>(amount)))) \
|
|
||||||
- static_cast<ib_uint32_t>(amount))
|
|
||||||
|
|
||||||
# define os_atomic_decrement_uint64(ptr, amount) \
|
|
||||||
(static_cast<ib_uint64_t>(InterlockedExchangeAdd64( \
|
|
||||||
reinterpret_cast<LONGLONG*>(ptr), \
|
|
||||||
-(static_cast<LONGLONG>(amount)))) \
|
|
||||||
- static_cast<ib_uint64_t>(amount))
|
|
||||||
|
|
||||||
#else
|
|
||||||
/* Fall back to GCC-style atomic builtins. */
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
Returns true if swapped, ptr is pointer to target, old_val is value to
|
|
||||||
compare to, new_val is the value to swap in. */
|
|
||||||
|
|
||||||
#if defined(HAVE_GCC_SYNC_BUILTINS)
|
|
||||||
|
|
||||||
# define os_compare_and_swap(ptr, old_val, new_val) \
|
|
||||||
__sync_bool_compare_and_swap(ptr, old_val, new_val)
|
|
||||||
|
|
||||||
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
|
|
||||||
os_compare_and_swap(ptr, old_val, new_val)
|
|
||||||
|
|
||||||
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
|
|
||||||
os_compare_and_swap(ptr, old_val, new_val)
|
|
||||||
|
|
||||||
# define os_compare_and_swap_uint32(ptr, old_val, new_val) \
|
|
||||||
os_compare_and_swap(ptr, old_val, new_val)
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
UNIV_INLINE
|
|
||||||
bool
|
|
||||||
os_compare_and_swap_ulint(volatile ulint* ptr, ulint old_val, ulint new_val)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_IB_GCC_ATOMIC_SEQ_CST
|
|
||||||
return __atomic_compare_exchange_n(ptr, &old_val, new_val, 0,
|
|
||||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
|
||||||
#else
|
|
||||||
return __sync_bool_compare_and_swap(ptr, old_val, new_val);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIV_INLINE
|
|
||||||
bool
|
|
||||||
os_compare_and_swap_lint(volatile lint* ptr, lint old_val, lint new_val)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_IB_GCC_ATOMIC_SEQ_CST
|
|
||||||
return __atomic_compare_exchange_n(ptr, &old_val, new_val, 0,
|
|
||||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
|
||||||
#else
|
|
||||||
return __sync_bool_compare_and_swap(ptr, old_val, new_val);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIV_INLINE
|
|
||||||
bool
|
|
||||||
os_compare_and_swap_uint32(volatile ib_uint32_t* ptr, ib_uint32_t old_val, ib_uint32_t new_val)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_IB_GCC_ATOMIC_SEQ_CST
|
|
||||||
return __atomic_compare_exchange_n(ptr, &old_val, new_val, 0,
|
|
||||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
|
||||||
#else
|
|
||||||
return __sync_bool_compare_and_swap(ptr, old_val, new_val);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_GCC_SYNC_BUILTINS */
|
|
||||||
|
|
||||||
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_GCC
|
|
||||||
#if defined(HAVE_GCC_SYNC_BUILTINS)
|
|
||||||
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
|
|
||||||
os_compare_and_swap(ptr, old_val, new_val)
|
|
||||||
#else
|
|
||||||
UNIV_INLINE
|
|
||||||
bool
|
|
||||||
os_compare_and_swap_thread_id(volatile os_thread_id_t* ptr, os_thread_id_t old_val, os_thread_id_t new_val)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_IB_GCC_ATOMIC_SEQ_CST
|
|
||||||
return __atomic_compare_exchange_n(ptr, &old_val, new_val, 0,
|
|
||||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
|
||||||
#else
|
|
||||||
return __sync_bool_compare_and_swap(ptr, old_val, new_val);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif /* HAVE_GCC_SYNC_BUILTINS */
|
|
||||||
# define INNODB_RW_LOCKS_USE_ATOMICS
|
|
||||||
# define IB_ATOMICS_STARTUP_MSG \
|
|
||||||
"Mutexes and rw_locks use GCC atomic builtins"
|
|
||||||
# else /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
|
|
||||||
# define IB_ATOMICS_STARTUP_MSG \
|
|
||||||
"Mutexes use GCC atomic builtins, rw_locks do not"
|
|
||||||
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
Returns the resulting value, ptr is pointer to target, amount is the
|
|
||||||
amount of increment. */
|
|
||||||
|
|
||||||
#if defined(HAVE_GCC_SYNC_BUILTINS)
|
|
||||||
# define os_atomic_increment(ptr, amount) \
|
|
||||||
__sync_add_and_fetch(ptr, amount)
|
|
||||||
#else
|
|
||||||
#ifdef HAVE_IB_GCC_ATOMIC_SEQ_CST
|
|
||||||
# define os_atomic_increment(ptr, amount) \
|
|
||||||
__atomic_add_fetch(ptr, amount, __ATOMIC_SEQ_CST)
|
|
||||||
#else
|
|
||||||
# define os_atomic_increment(ptr, amount) \
|
|
||||||
__sync_add_and_fetch(ptr, amount)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HAVE_GCC_SYNC_BUILTINS */
|
|
||||||
|
|
||||||
# define os_atomic_increment_lint(ptr, amount) \
|
|
||||||
os_atomic_increment(ptr, amount)
|
|
||||||
|
|
||||||
# define os_atomic_increment_ulint(ptr, amount) \
|
|
||||||
os_atomic_increment(ptr, amount)
|
|
||||||
|
|
||||||
# define os_atomic_increment_uint32(ptr, amount ) \
|
|
||||||
os_atomic_increment(ptr, amount)
|
|
||||||
|
|
||||||
# define os_atomic_increment_uint64(ptr, amount) \
|
|
||||||
os_atomic_increment(ptr, amount)
|
|
||||||
|
|
||||||
/* Returns the resulting value, ptr is pointer to target, amount is the
|
|
||||||
amount to decrement. */
|
|
||||||
|
|
||||||
#if defined(HAVE_GCC_SYNC_BUILTINS)
|
|
||||||
# define os_atomic_decrement(ptr, amount) \
|
|
||||||
__sync_sub_and_fetch(ptr, amount)
|
|
||||||
#else
|
|
||||||
#ifdef HAVE_IB_GCC_ATOMIC_SEQ_CST
|
|
||||||
# define os_atomic_decrement(ptr, amount) \
|
|
||||||
__atomic_sub_fetch(ptr, amount, __ATOMIC_SEQ_CST)
|
|
||||||
#else
|
|
||||||
# define os_atomic_decrement(ptr, amount) \
|
|
||||||
__sync_sub_and_fetch(ptr, amount)
|
|
||||||
#endif
|
|
||||||
#endif /* HAVE_GCC_SYNC_BUILTINS */
|
|
||||||
|
|
||||||
# define os_atomic_decrement_lint(ptr, amount) \
|
|
||||||
os_atomic_decrement(ptr, amount)
|
|
||||||
|
|
||||||
# define os_atomic_decrement_ulint(ptr, amount) \
|
|
||||||
os_atomic_decrement(ptr, amount)
|
|
||||||
|
|
||||||
# define os_atomic_decrement_uint32(ptr, amount) \
|
|
||||||
os_atomic_decrement(ptr, amount)
|
|
||||||
|
|
||||||
# define os_atomic_decrement_uint64(ptr, amount) \
|
|
||||||
os_atomic_decrement(ptr, amount)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define os_atomic_inc_ulint(m,v,d) os_atomic_increment_ulint(v, d)
|
|
||||||
#define os_atomic_dec_ulint(m,v,d) os_atomic_decrement_ulint(v, d)
|
|
||||||
#define TAS(l, n) os_atomic_test_and_set((l), (n))
|
|
||||||
#define CAS(l, o, n) os_atomic_val_compare_and_swap((l), (o), (n))
|
|
||||||
|
|
||||||
/** barrier definitions for memory ordering */
|
|
||||||
#ifdef HAVE_IB_GCC_ATOMIC_THREAD_FENCE
|
|
||||||
# define HAVE_MEMORY_BARRIER
|
|
||||||
# define os_rmb __atomic_thread_fence(__ATOMIC_ACQUIRE)
|
|
||||||
# define os_wmb __atomic_thread_fence(__ATOMIC_RELEASE)
|
|
||||||
# define IB_MEMORY_BARRIER_STARTUP_MSG \
|
|
||||||
"GCC builtin __atomic_thread_fence() is used for memory barrier"
|
|
||||||
|
|
||||||
#elif defined(HAVE_IB_GCC_SYNC_SYNCHRONISE)
|
|
||||||
# define HAVE_MEMORY_BARRIER
|
|
||||||
# define os_rmb __sync_synchronize()
|
|
||||||
# define os_wmb __sync_synchronize()
|
|
||||||
# define IB_MEMORY_BARRIER_STARTUP_MSG \
|
|
||||||
"GCC builtin __sync_synchronize() is used for memory barrier"
|
|
||||||
|
|
||||||
#elif defined(HAVE_IB_MACHINE_BARRIER_SOLARIS)
|
|
||||||
# define HAVE_MEMORY_BARRIER
|
|
||||||
# include <mbarrier.h>
|
|
||||||
# define os_rmb __machine_r_barrier()
|
|
||||||
# define os_wmb __machine_w_barrier()
|
|
||||||
# define IB_MEMORY_BARRIER_STARTUP_MSG \
|
|
||||||
"Solaris memory ordering functions are used for memory barrier"
|
|
||||||
|
|
||||||
#elif defined(HAVE_WINDOWS_MM_FENCE) && defined(_WIN64)
|
|
||||||
# define HAVE_MEMORY_BARRIER
|
|
||||||
# include <mmintrin.h>
|
|
||||||
# define os_rmb _mm_lfence()
|
|
||||||
# define os_wmb _mm_sfence()
|
|
||||||
# define IB_MEMORY_BARRIER_STARTUP_MSG \
|
|
||||||
"_mm_lfence() and _mm_sfence() are used for memory barrier"
|
|
||||||
|
|
||||||
#else
|
|
||||||
# define os_rmb
|
|
||||||
# define os_wmb
|
|
||||||
# define IB_MEMORY_BARRIER_STARTUP_MSG \
|
|
||||||
"Memory barrier is not used"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef UNIV_NONINL
|
|
||||||
#include "os0atomic.ic"
|
|
||||||
#endif /* UNIV_NOINL */
|
|
||||||
|
|
||||||
#endif /* !os0atomic_h */
|
|
||||||
@@ -1,224 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
|
|
||||||
Copyright (c) 2013, 2016, 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/os0atomics.ic
|
|
||||||
The interface to the operating system synchronization primitives.
|
|
||||||
|
|
||||||
Created 2012-09-23 Sunny Bains (Split from include/os0sync.ic)
|
|
||||||
*******************************************************/
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <winbase.h>
|
|
||||||
|
|
||||||
/* 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 /* _WIN64 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
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 /* _WIN64 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************//**
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Do an atomic test and set.
|
|
||||||
@param[in,out] ptr Memory location to set
|
|
||||||
@param[in] new_val new value
|
|
||||||
@return old value of memory location. */
|
|
||||||
UNIV_INLINE
|
|
||||||
lock_word_t
|
|
||||||
os_atomic_test_and_set(
|
|
||||||
volatile lock_word_t* ptr,
|
|
||||||
lock_word_t new_val)
|
|
||||||
{
|
|
||||||
return(InterlockedExchange(ptr, new_val));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Do an atomic compare and set
|
|
||||||
@param[in,out] ptr Memory location to set
|
|
||||||
@param[in] old_val old value to compare
|
|
||||||
@param[in] new_val new value to set
|
|
||||||
@return the value of ptr before the operation. */
|
|
||||||
UNIV_INLINE
|
|
||||||
lock_word_t
|
|
||||||
os_atomic_val_compare_and_swap(
|
|
||||||
volatile lock_word_t* ptr,
|
|
||||||
lock_word_t old_val,
|
|
||||||
lock_word_t new_val)
|
|
||||||
{
|
|
||||||
return(static_cast<lock_word_t>(win_cmp_and_xchg_lint(
|
|
||||||
reinterpret_cast<volatile lint*>(ptr),
|
|
||||||
static_cast<lint>(new_val),
|
|
||||||
static_cast<lint>(old_val))));
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(HAVE_IB_GCC_ATOMIC_COMPARE_EXCHANGE)
|
|
||||||
|
|
||||||
/** Do an atomic test and set.
|
|
||||||
@param[in,out] ptr Memory location to set
|
|
||||||
@param[in] new_val new value
|
|
||||||
@return old value of memory location. */
|
|
||||||
UNIV_INLINE
|
|
||||||
lock_word_t
|
|
||||||
os_atomic_test_and_set(
|
|
||||||
volatile lock_word_t* ptr,
|
|
||||||
lock_word_t new_val)
|
|
||||||
{
|
|
||||||
lock_word_t ret;
|
|
||||||
|
|
||||||
/* Silence a compiler warning about unused ptr. */
|
|
||||||
(void) ptr;
|
|
||||||
|
|
||||||
#if defined(__powerpc__) || defined(__aarch64__)
|
|
||||||
__atomic_exchange(ptr, &new_val, &ret, __ATOMIC_SEQ_CST);
|
|
||||||
#else
|
|
||||||
__atomic_exchange(ptr, &new_val, &ret, __ATOMIC_RELEASE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Do an atomic compare and set
|
|
||||||
@param[in,out] ptr Memory location to set
|
|
||||||
@param[in] old_val old value to compare
|
|
||||||
@param[in] new_val new value to set
|
|
||||||
@return the value of ptr before the operation. */
|
|
||||||
UNIV_INLINE
|
|
||||||
lock_word_t
|
|
||||||
os_atomic_val_compare_and_swap(
|
|
||||||
volatile lock_word_t* ptr,
|
|
||||||
lock_word_t old_val,
|
|
||||||
lock_word_t new_val)
|
|
||||||
{
|
|
||||||
/* Silence a compiler warning about unused ptr. */
|
|
||||||
(void) ptr;
|
|
||||||
|
|
||||||
#if defined(__powerpc__) || defined(__aarch64__)
|
|
||||||
__atomic_compare_exchange(ptr, &old_val, &new_val, false,
|
|
||||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
|
||||||
#else
|
|
||||||
__atomic_compare_exchange(ptr, &old_val, &new_val, false,
|
|
||||||
__ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return(old_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(IB_STRONG_MEMORY_MODEL)
|
|
||||||
|
|
||||||
/** Do an atomic test and set.
|
|
||||||
@param[in,out] ptr Memory location to set
|
|
||||||
@param[in] new_val new value
|
|
||||||
@return old value of memory location. */
|
|
||||||
UNIV_INLINE
|
|
||||||
lock_word_t
|
|
||||||
os_atomic_test_and_set(
|
|
||||||
volatile lock_word_t* ptr,
|
|
||||||
lock_word_t new_val)
|
|
||||||
{
|
|
||||||
return(__sync_lock_test_and_set(ptr, new_val));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Do an atomic compare and set
|
|
||||||
@param[in,out] ptr Memory location to set
|
|
||||||
@param[in] old_val old value to compare
|
|
||||||
@param[in] new_val new value to set
|
|
||||||
@return the value of ptr before the operation. */
|
|
||||||
UNIV_INLINE
|
|
||||||
lock_word_t
|
|
||||||
os_atomic_val_compare_and_swap(
|
|
||||||
volatile lock_word_t* ptr,
|
|
||||||
lock_word_t old_val,
|
|
||||||
lock_word_t new_val)
|
|
||||||
{
|
|
||||||
return(__sync_val_compare_and_swap(ptr, old_val, new_val));
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#error "Unsupported platform"
|
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
@@ -29,7 +29,6 @@ Created Feb 20, 2014 Vasil Dimov
|
|||||||
|
|
||||||
#include "univ.i"
|
#include "univ.i"
|
||||||
|
|
||||||
#include "os0atomic.h"
|
|
||||||
#include "ut0ut.h"
|
#include "ut0ut.h"
|
||||||
|
|
||||||
/** Execute a given function exactly once in a multi-threaded environment
|
/** Execute a given function exactly once in a multi-threaded environment
|
||||||
|
|||||||
@@ -85,13 +85,6 @@ Note that one of the wait objects was signalled. */
|
|||||||
void
|
void
|
||||||
sync_array_object_signalled();
|
sync_array_object_signalled();
|
||||||
|
|
||||||
/**********************************************************************//**
|
|
||||||
If the wakeup algorithm does not work perfectly at semaphore relases,
|
|
||||||
this function will do the waking (see the comment in mutex_exit). This
|
|
||||||
function should be called about every 1 second in the server. */
|
|
||||||
void
|
|
||||||
sync_arr_wake_threads_if_sema_free();
|
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Prints warnings of long semaphore waits to stderr.
|
Prints warnings of long semaphore waits to stderr.
|
||||||
@return TRUE if fatal semaphore wait threshold was exceeded */
|
@return TRUE if fatal semaphore wait threshold was exceeded */
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ extern ulong srv_spin_wait_delay;
|
|||||||
extern ulong srv_n_spin_wait_rounds;
|
extern ulong srv_n_spin_wait_rounds;
|
||||||
extern ulong srv_force_recovery_crash;
|
extern ulong srv_force_recovery_crash;
|
||||||
|
|
||||||
#include "os0atomic.h"
|
|
||||||
#include "sync0policy.h"
|
#include "sync0policy.h"
|
||||||
#include "ib0mutex.h"
|
#include "ib0mutex.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -45,25 +44,6 @@ extern ulong srv_force_recovery_crash;
|
|||||||
|
|
||||||
typedef OSMutex EventMutex;
|
typedef OSMutex EventMutex;
|
||||||
|
|
||||||
#ifndef UNIV_DEBUG
|
|
||||||
|
|
||||||
# ifdef HAVE_IB_LINUX_FUTEX
|
|
||||||
UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
|
|
||||||
UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
|
|
||||||
# endif /* HAVE_IB_LINUX_FUTEX */
|
|
||||||
|
|
||||||
UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex);
|
|
||||||
UT_MUTEX_TYPE(TTASMutex, BlockMutexPolicy, BlockSpinMutex);
|
|
||||||
|
|
||||||
|
|
||||||
UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex);
|
|
||||||
UT_MUTEX_TYPE(OSTrackMutex, BlockMutexPolicy, BlockSysMutex);
|
|
||||||
|
|
||||||
UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex);
|
|
||||||
UT_MUTEX_TYPE(TTASEventMutex, BlockMutexPolicy, BlockSyncArrayMutex);
|
|
||||||
|
|
||||||
#else /* !UNIV_DEBUG */
|
|
||||||
|
|
||||||
# ifdef HAVE_IB_LINUX_FUTEX
|
# ifdef HAVE_IB_LINUX_FUTEX
|
||||||
UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
|
UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
|
||||||
UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
|
UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
|
||||||
@@ -78,8 +58,6 @@ UT_MUTEX_TYPE(OSTrackMutex, BlockMutexPolicy, BlockSysMutex);
|
|||||||
UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex);
|
UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex);
|
||||||
UT_MUTEX_TYPE(TTASEventMutex, BlockMutexPolicy, BlockSyncArrayMutex);
|
UT_MUTEX_TYPE(TTASEventMutex, BlockMutexPolicy, BlockSyncArrayMutex);
|
||||||
|
|
||||||
#endif /* !UNIV_DEBUG */
|
|
||||||
|
|
||||||
#ifdef MUTEX_FUTEX
|
#ifdef MUTEX_FUTEX
|
||||||
/** The default mutex type. */
|
/** The default mutex type. */
|
||||||
typedef FutexMutex ib_mutex_t;
|
typedef FutexMutex ib_mutex_t;
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ Created 1/20/1994 Heikki Tuuri
|
|||||||
|
|
||||||
#include "db0err.h"
|
#include "db0err.h"
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
|
||||||
# include "os0atomic.h"
|
|
||||||
#endif /* UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifndef MYSQL_SERVER
|
#ifndef MYSQL_SERVER
|
||||||
|
|||||||
@@ -158,200 +158,12 @@ IF(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE)
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(NOT MSVC)
|
IF(NOT MSVC)
|
||||||
# either define HAVE_IB_GCC_ATOMIC_BUILTINS or not
|
|
||||||
# either define HAVE_IB_GCC_ATOMIC_BUILTINS or not
|
|
||||||
# workaround for gcc 4.1.2 RHEL5/x86, gcc atomic ops only work under -march=i686
|
# workaround for gcc 4.1.2 RHEL5/x86, gcc atomic ops only work under -march=i686
|
||||||
IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "i686" AND CMAKE_COMPILER_IS_GNUCC AND
|
IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "i686" AND CMAKE_COMPILER_IS_GNUCC AND
|
||||||
CMAKE_C_COMPILER_VERSION VERSION_LESS "4.1.3")
|
CMAKE_C_COMPILER_VERSION VERSION_LESS "4.1.3")
|
||||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
CHECK_C_SOURCE(
|
|
||||||
"
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
long x;
|
|
||||||
long y;
|
|
||||||
long res;
|
|
||||||
|
|
||||||
x = 10;
|
|
||||||
y = 123;
|
|
||||||
res = __sync_bool_compare_and_swap(&x, x, y);
|
|
||||||
if (!res || x != y) {
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
x = 10;
|
|
||||||
y = 123;
|
|
||||||
res = __sync_bool_compare_and_swap(&x, x + 1, y);
|
|
||||||
if (res || x != 10) {
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
x = 10;
|
|
||||||
y = 123;
|
|
||||||
res = __sync_add_and_fetch(&x, y);
|
|
||||||
if (res != 123 + 10 || x != 123 + 10) {
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_GCC_ATOMIC_BUILTINS
|
|
||||||
)
|
|
||||||
CHECK_C_SOURCE(
|
|
||||||
"
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
long res;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
c = 10;
|
|
||||||
res = __sync_lock_test_and_set(&c, 123);
|
|
||||||
if (res != 10 || c != 123) {
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE
|
|
||||||
)
|
|
||||||
CHECK_C_SOURCE(
|
|
||||||
"#include<stdint.h>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
int64_t x,y,res;
|
|
||||||
|
|
||||||
x = 10;
|
|
||||||
y = 123;
|
|
||||||
res = __sync_sub_and_fetch(&y, x);
|
|
||||||
if (res != y || y != 113) {
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
res = __sync_add_and_fetch(&y, x);
|
|
||||||
if (res != y || y != 123) {
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_GCC_ATOMIC_BUILTINS_64
|
|
||||||
)
|
|
||||||
CHECK_C_SOURCE(
|
|
||||||
"#include<stdint.h>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
__sync_synchronize();
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_GCC_SYNC_SYNCHRONISE
|
|
||||||
)
|
|
||||||
CHECK_C_SOURCE(
|
|
||||||
"#include<stdint.h>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
__atomic_thread_fence(__ATOMIC_ACQUIRE);
|
|
||||||
__atomic_thread_fence(__ATOMIC_RELEASE);
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_GCC_ATOMIC_THREAD_FENCE
|
|
||||||
)
|
|
||||||
CHECK_C_SOURCE(
|
|
||||||
"#include<stdint.h>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
__atomic_test_and_set(&c, __ATOMIC_ACQUIRE);
|
|
||||||
__atomic_clear(&c, __ATOMIC_RELEASE);
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_GCC_ATOMIC_TEST_AND_SET
|
|
||||||
)
|
|
||||||
CHECK_C_SOURCE_RUNS(
|
|
||||||
"#include<stdint.h>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
unsigned char a = 0;
|
|
||||||
unsigned char b = 0;
|
|
||||||
unsigned char c = 1;
|
|
||||||
|
|
||||||
__atomic_exchange(&a, &b, &c, __ATOMIC_RELEASE);
|
|
||||||
__atomic_compare_exchange(&a, &b, &c, 0,
|
|
||||||
__ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_GCC_ATOMIC_COMPARE_EXCHANGE
|
|
||||||
)
|
|
||||||
CHECK_C_SOURCE_RUNS(
|
|
||||||
"#include<stdint.h>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
unsigned char a = 0;
|
|
||||||
unsigned char b = 0;
|
|
||||||
unsigned char c = 1;
|
|
||||||
|
|
||||||
__atomic_compare_exchange_n(&a, &b, &c, 0,
|
|
||||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
|
||||||
return (0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_GCC_ATOMIC_SEQ_CST
|
|
||||||
)
|
|
||||||
|
|
||||||
IF (HAVE_IB_GCC_ATOMIC_SEQ_CST)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_CST=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_GCC_ATOMIC_BUILTINS)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_BYTE=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_GCC_ATOMIC_BUILTINS_64)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_64=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_GCC_SYNC_SYNCHRONISE)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_GCC_SYNC_SYNCHRONISE=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_GCC_ATOMIC_THREAD_FENCE)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_THREAD_FENCE=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_TEST_AND_SET=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_GCC_ATOMIC_COMPARE_EXCHANGE)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_COMPARE_EXCHANGE=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not
|
|
||||||
IF(NOT CMAKE_CROSSCOMPILING)
|
|
||||||
CHECK_C_SOURCE_RUNS(
|
|
||||||
"
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
pthread_t x1;
|
|
||||||
pthread_t x2;
|
|
||||||
pthread_t x3;
|
|
||||||
|
|
||||||
memset(&x1, 0x0, sizeof(x1));
|
|
||||||
memset(&x2, 0x0, sizeof(x2));
|
|
||||||
memset(&x3, 0x0, sizeof(x3));
|
|
||||||
|
|
||||||
__sync_bool_compare_and_swap(&x1, x2, x3);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_ATOMIC_PTHREAD_T_GCC)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_ATOMIC_PTHREAD_T_GCC)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_GCC=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# Only use futexes on Linux if GCC atomics are available
|
# Only use futexes on Linux if GCC atomics are available
|
||||||
IF(NOT MSVC AND NOT CMAKE_CROSSCOMPILING)
|
IF(NOT MSVC AND NOT CMAKE_CROSSCOMPILING)
|
||||||
@@ -402,73 +214,6 @@ IF(HAVE_C99_INITIALIZERS)
|
|||||||
ADD_DEFINITIONS(-DHAVE_C99_INITIALIZERS)
|
ADD_DEFINITIONS(-DHAVE_C99_INITIALIZERS)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Solaris atomics
|
|
||||||
IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
|
||||||
CHECK_FUNCTION_EXISTS(atomic_cas_ulong HAVE_ATOMIC_CAS_ULONG)
|
|
||||||
CHECK_FUNCTION_EXISTS(atomic_cas_32 HAVE_ATOMIC_CAS_32)
|
|
||||||
CHECK_FUNCTION_EXISTS(atomic_cas_64 HAVE_ATOMIC_CAS_64)
|
|
||||||
CHECK_FUNCTION_EXISTS(atomic_add_long_nv HAVE_ATOMIC_ADD_LONG_NV)
|
|
||||||
CHECK_FUNCTION_EXISTS(atomic_swap_uchar HAVE_ATOMIC_SWAP_UCHAR)
|
|
||||||
IF(HAVE_ATOMIC_CAS_ULONG AND
|
|
||||||
HAVE_ATOMIC_CAS_32 AND
|
|
||||||
HAVE_ATOMIC_CAS_64 AND
|
|
||||||
HAVE_ATOMIC_ADD_LONG_NV AND
|
|
||||||
HAVE_ATOMIC_SWAP_UCHAR)
|
|
||||||
SET(HAVE_IB_SOLARIS_ATOMICS 1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(HAVE_IB_SOLARIS_ATOMICS)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_SOLARIS_ATOMICS=1)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not
|
|
||||||
CHECK_C_SOURCE_COMPILES(
|
|
||||||
" #include <pthread.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
pthread_t x1;
|
|
||||||
pthread_t x2;
|
|
||||||
pthread_t x3;
|
|
||||||
|
|
||||||
memset(&x1, 0x0, sizeof(x1));
|
|
||||||
memset(&x2, 0x0, sizeof(x2));
|
|
||||||
memset(&x3, 0x0, sizeof(x3));
|
|
||||||
|
|
||||||
if (sizeof(pthread_t) == 4) {
|
|
||||||
|
|
||||||
atomic_cas_32(&x1, x2, x3);
|
|
||||||
|
|
||||||
} else if (sizeof(pthread_t) == 8) {
|
|
||||||
|
|
||||||
atomic_cas_64(&x1, x2, x3);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
" HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS)
|
|
||||||
CHECK_C_SOURCE_COMPILES(
|
|
||||||
"#include <mbarrier.h>
|
|
||||||
int main() {
|
|
||||||
__machine_r_barrier();
|
|
||||||
__machine_w_barrier();
|
|
||||||
return(0);
|
|
||||||
}"
|
|
||||||
HAVE_IB_MACHINE_BARRIER_SOLARIS)
|
|
||||||
|
|
||||||
IF(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_SOLARIS=1)
|
|
||||||
ENDIF()
|
|
||||||
IF(HAVE_IB_MACHINE_BARRIER_SOLARIS)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_IB_MACHINE_BARRIER_SOLARIS=1)
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
|
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
# this is needed to know which one of atomic_cas_32() or atomic_cas_64()
|
# this is needed to know which one of atomic_cas_32() or atomic_cas_64()
|
||||||
# to use in the source
|
# to use in the source
|
||||||
@@ -481,11 +226,6 @@ IF(SIZEOF_PTHREAD_T)
|
|||||||
ADD_DEFINITIONS(-DSIZEOF_PTHREAD_T=${SIZEOF_PTHREAD_T})
|
ADD_DEFINITIONS(-DSIZEOF_PTHREAD_T=${SIZEOF_PTHREAD_T})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(MSVC)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_WINDOWS_MM_FENCE)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
SET(MUTEXTYPE "event" CACHE STRING "Mutex type: event, sys or futex")
|
SET(MUTEXTYPE "event" CACHE STRING "Mutex type: event, sys or futex")
|
||||||
|
|
||||||
IF(MUTEXTYPE MATCHES "event")
|
IF(MUTEXTYPE MATCHES "event")
|
||||||
|
|||||||
@@ -152,19 +152,6 @@ srv_conc_enter_innodb_with_atomics(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srv_thread_concurrency == 0) {
|
|
||||||
|
|
||||||
if (notified_mysql) {
|
|
||||||
|
|
||||||
(void) my_atomic_addlint(
|
|
||||||
&srv_conc.n_waiting, -1);
|
|
||||||
|
|
||||||
thd_wait_end(trx->mysql_thd);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srv_conc.n_active < (lint) srv_thread_concurrency) {
|
if (srv_conc.n_active < (lint) srv_thread_concurrency) {
|
||||||
ulint n_active;
|
ulint n_active;
|
||||||
|
|
||||||
|
|||||||
@@ -426,12 +426,7 @@ ulong srv_doublewrite_batch_size = 120;
|
|||||||
ulong srv_replication_delay = 0;
|
ulong srv_replication_delay = 0;
|
||||||
|
|
||||||
/*-------------------------------------------*/
|
/*-------------------------------------------*/
|
||||||
#ifdef HAVE_MEMORY_BARRIER
|
|
||||||
/* No idea to wait long with memory barriers */
|
|
||||||
UNIV_INTERN ulong srv_n_spin_wait_rounds = 15;
|
UNIV_INTERN ulong srv_n_spin_wait_rounds = 15;
|
||||||
#else
|
|
||||||
UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
|
|
||||||
#endif
|
|
||||||
ulong srv_spin_wait_delay = 6;
|
ulong srv_spin_wait_delay = 6;
|
||||||
ibool srv_priority_boost = TRUE;
|
ibool srv_priority_boost = TRUE;
|
||||||
|
|
||||||
@@ -1896,8 +1891,6 @@ exit_func:
|
|||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
A thread which prints warnings about semaphore waits which have lasted
|
A thread which prints warnings about semaphore waits which have lasted
|
||||||
too long. These can be used to track bugs which cause hangs.
|
too long. These can be used to track bugs which cause hangs.
|
||||||
Note: In order to make sync_arr_wake_threads_if_sema_free work as expected,
|
|
||||||
we should avoid waiting any mutexes in this function!
|
|
||||||
@return a dummy parameter */
|
@return a dummy parameter */
|
||||||
extern "C"
|
extern "C"
|
||||||
os_thread_ret_t
|
os_thread_ret_t
|
||||||
@@ -1960,12 +1953,6 @@ loop:
|
|||||||
eviction policy. */
|
eviction policy. */
|
||||||
buf_LRU_stat_update();
|
buf_LRU_stat_update();
|
||||||
|
|
||||||
/* In case mutex_exit is not a memory barrier, it is
|
|
||||||
theoretically possible some threads are left waiting though
|
|
||||||
the semaphore is already released. Wake up those threads: */
|
|
||||||
|
|
||||||
sync_arr_wake_threads_if_sema_free();
|
|
||||||
|
|
||||||
if (sync_array_print_long_waits(&waiter, &sema)
|
if (sync_array_print_long_waits(&waiter, &sema)
|
||||||
&& sema == old_sema && os_thread_eq(waiter, old_waiter)) {
|
&& sema == old_sema && os_thread_eq(waiter, old_waiter)) {
|
||||||
#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES)
|
#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES)
|
||||||
|
|||||||
@@ -1517,17 +1517,6 @@ innobase_start_or_create_for_mysql(void)
|
|||||||
ib::info() << "Mutexes and rw_locks use GCC atomic builtins";
|
ib::info() << "Mutexes and rw_locks use GCC atomic builtins";
|
||||||
#endif
|
#endif
|
||||||
ib::info() << MUTEX_TYPE;
|
ib::info() << MUTEX_TYPE;
|
||||||
ib::info() << IB_MEMORY_BARRIER_STARTUP_MSG;
|
|
||||||
|
|
||||||
#ifndef HAVE_MEMORY_BARRIER
|
|
||||||
#if defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64 || defined _WIN32
|
|
||||||
#else
|
|
||||||
ib::warn() << "MySQL was built without a memory barrier capability on"
|
|
||||||
" this architecture, which might allow a mutex/rw_lock"
|
|
||||||
" violation under high thread concurrency. This may cause a"
|
|
||||||
" hang.";
|
|
||||||
#endif /* IA32 or AMD64 */
|
|
||||||
#endif /* HAVE_MEMORY_BARRIER */
|
|
||||||
|
|
||||||
ib::info() << "Compressed tables use zlib " ZLIB_VERSION
|
ib::info() << "Compressed tables use zlib " ZLIB_VERSION
|
||||||
#ifdef UNIV_ZIP_DEBUG
|
#ifdef UNIV_ZIP_DEBUG
|
||||||
|
|||||||
@@ -961,81 +961,6 @@ sync_array_detect_deadlock(
|
|||||||
}
|
}
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
/******************************************************************//**
|
|
||||||
Determines if we can wake up the thread waiting for a sempahore. */
|
|
||||||
static
|
|
||||||
bool
|
|
||||||
sync_arr_cell_can_wake_up(
|
|
||||||
/*======================*/
|
|
||||||
sync_cell_t* cell) /*!< in: cell to search */
|
|
||||||
{
|
|
||||||
rw_lock_t* lock;
|
|
||||||
|
|
||||||
switch (cell->request_type) {
|
|
||||||
WaitMutex* mutex;
|
|
||||||
BlockWaitMutex* bpmutex;
|
|
||||||
case SYNC_MUTEX:
|
|
||||||
mutex = cell->latch.mutex;
|
|
||||||
|
|
||||||
os_rmb;
|
|
||||||
if (mutex->state() == MUTEX_STATE_UNLOCKED) {
|
|
||||||
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SYNC_BUF_BLOCK:
|
|
||||||
bpmutex = cell->latch.bpmutex;
|
|
||||||
|
|
||||||
os_rmb;
|
|
||||||
if (bpmutex->state() == MUTEX_STATE_UNLOCKED) {
|
|
||||||
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RW_LOCK_X:
|
|
||||||
case RW_LOCK_SX:
|
|
||||||
lock = cell->latch.lock;
|
|
||||||
|
|
||||||
os_rmb;
|
|
||||||
if (lock->lock_word > X_LOCK_HALF_DECR) {
|
|
||||||
/* Either unlocked or only read locked. */
|
|
||||||
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RW_LOCK_X_WAIT:
|
|
||||||
|
|
||||||
lock = cell->latch.lock;
|
|
||||||
|
|
||||||
/* lock_word == 0 means all readers or sx have left */
|
|
||||||
os_rmb;
|
|
||||||
if (lock->lock_word == 0) {
|
|
||||||
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RW_LOCK_S:
|
|
||||||
|
|
||||||
lock = cell->latch.lock;
|
|
||||||
|
|
||||||
/* lock_word > 0 means no writer or reserved writer */
|
|
||||||
os_rmb;
|
|
||||||
if (lock->lock_word > 0) {
|
|
||||||
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Increments the signalled count. */
|
Increments the signalled count. */
|
||||||
void
|
void
|
||||||
@@ -1045,58 +970,6 @@ sync_array_object_signalled()
|
|||||||
++sg_count;
|
++sg_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************//**
|
|
||||||
If the wakeup algorithm does not work perfectly at semaphore relases,
|
|
||||||
this function will do the waking (see the comment in mutex_exit). This
|
|
||||||
function should be called about every 1 second in the server.
|
|
||||||
|
|
||||||
Note that there's a race condition between this thread and mutex_exit
|
|
||||||
changing the lock_word and calling signal_object, so sometimes this finds
|
|
||||||
threads to wake up even when nothing has gone wrong. */
|
|
||||||
static
|
|
||||||
void
|
|
||||||
sync_array_wake_threads_if_sema_free_low(
|
|
||||||
/*=====================================*/
|
|
||||||
sync_array_t* arr) /* in/out: wait array */
|
|
||||||
{
|
|
||||||
sync_array_enter(arr);
|
|
||||||
|
|
||||||
for (ulint i = 0; i < arr->next_free_slot; ++i) {
|
|
||||||
sync_cell_t* cell;
|
|
||||||
|
|
||||||
cell = sync_array_get_nth_cell(arr, i);
|
|
||||||
|
|
||||||
if (cell->latch.mutex != 0 && sync_arr_cell_can_wake_up(cell)) {
|
|
||||||
os_event_t event;
|
|
||||||
|
|
||||||
event = sync_cell_get_event(cell);
|
|
||||||
|
|
||||||
os_event_set(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sync_array_exit(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************//**
|
|
||||||
If the wakeup algorithm does not work perfectly at semaphore relases,
|
|
||||||
this function will do the waking (see the comment in mutex_exit). This
|
|
||||||
function should be called about every 1 second in the server.
|
|
||||||
|
|
||||||
Note that there's a race condition between this thread and mutex_exit
|
|
||||||
changing the lock_word and calling signal_object, so sometimes this finds
|
|
||||||
threads to wake up even when nothing has gone wrong. */
|
|
||||||
void
|
|
||||||
sync_arr_wake_threads_if_sema_free(void)
|
|
||||||
/*====================================*/
|
|
||||||
{
|
|
||||||
for (ulint i = 0; i < sync_array_size; ++i) {
|
|
||||||
|
|
||||||
sync_array_wake_threads_if_sema_free_low(
|
|
||||||
sync_wait_array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Prints warnings of long semaphore waits to stderr.
|
Prints warnings of long semaphore waits to stderr.
|
||||||
@return TRUE if fatal semaphore wait threshold was exceeded */
|
@return TRUE if fatal semaphore wait threshold was exceeded */
|
||||||
|
|||||||
Reference in New Issue
Block a user