mariadb/storage/innobase/include/os0atomic.ic
Jan Lindström fec844aca8 Merge InnoDB 5.7 from mysql-5.7.14.
Contains also:
       MDEV-10549 mysqld: sql/handler.cc:2692: int handler::ha_index_first(uchar*): Assertion `table_share->tmp_table != NO_TMP_TABLE || m_lock_type != 2' failed. (branch bb-10.2-jan)
       Unlike MySQL, InnoDB still uses THR_LOCK in MariaDB

       MDEV-10548 Some of the debug sync waits do not work with InnoDB 5.7 (branch bb-10.2-jan)
       enable tests that were fixed in MDEV-10549

       MDEV-10548 Some of the debug sync waits do not work with InnoDB 5.7 (branch bb-10.2-jan)
       fix main.innodb_mysql_sync - re-enable online alter for partitioned innodb tables
2016-09-08 15:49:03 +03:00

224 lines
6.3 KiB
Text

/*****************************************************************************
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 */