Commit bd2117d1 authored by Michael Widenius's avatar Michael Widenius

Automatic merge from 5.5

Fixed 2 failing tests by replacing result files
parents cfa1ce81 5569132f
MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MAJOR=10
MYSQL_VERSION_MINOR=0 MYSQL_VERSION_MINOR=0
MYSQL_VERSION_PATCH=14 MYSQL_VERSION_PATCH=14
MYSQL_VERSION_EXTRA=
/* Copyright (c) 2013, MariaDB foundation Ab and SkySQL
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 St, Fifth Floor, Boston, MA 02111-1307 USA
*/
/* instructions for specific cpu's */
/*
Macros for adjusting thread priority (hardware multi-threading)
The defines are the same ones used by the linux kernel
*/
#if defined(__powerpc__)
/* Very low priority */
#define HMT_very_low() asm volatile("or 31,31,31")
/* Low priority */
#define HMT_low() asm volatile("or 1,1,1")
/* Medium low priority */
#define HMT_medium_low() asm volatile("or 6,6,6")
/* Medium priority */
#define HMT_medium() asm volatile("or 2,2,2")
/* Medium high priority */
#define HMT_medium_high() asm volatile("or 5,5,5")
/* High priority */
#define HMT_high() asm volatile("or 3,3,3")
#else
#define HMT_very_low()
#define HMT_low()
#define HMT_medium_low()
#define HMT_medium()
#define HMT_medium_high()
#define HMT_high()
#endif
...@@ -227,7 +227,7 @@ DROP TABLE mysql050614_xxx_croatian_ci; ...@@ -227,7 +227,7 @@ DROP TABLE mysql050614_xxx_croatian_ci;
# Checking mysql_upgrade # Checking mysql_upgrade
# #
# Running mysql_upgrade # Running mysql_upgrade
Phase 1/3: Running 'mysql_fix_privilege_tables'... Phase 1/4: Checking mysql database
Processing databases Processing databases
mysql mysql
mysql.column_stats OK mysql.column_stats OK
...@@ -258,8 +258,9 @@ mysql.time_zone_name OK ...@@ -258,8 +258,9 @@ mysql.time_zone_name OK
mysql.time_zone_transition OK mysql.time_zone_transition OK
mysql.time_zone_transition_type OK mysql.time_zone_transition_type OK
mysql.user OK mysql.user OK
Phase 2/3: Fixing table and database names Phase 2/4: Running 'mysql_fix_privilege_tables'...
Phase 3/3: Checking and upgrading tables Phase 3/4: Fixing table and database names
Phase 4/4: Checking and upgrading tables
Processing databases Processing databases
information_schema information_schema
mtr mtr
...@@ -281,7 +282,7 @@ test.maria100004_xxx_croatian_ci OK ...@@ -281,7 +282,7 @@ test.maria100004_xxx_croatian_ci OK
OK OK
# Running mysql_upgrade for the second time # Running mysql_upgrade for the second time
# This should report OK for all tables # This should report OK for all tables
Phase 1/3: Running 'mysql_fix_privilege_tables'... Phase 1/4: Checking mysql database
Processing databases Processing databases
mysql mysql
mysql.column_stats OK mysql.column_stats OK
...@@ -312,8 +313,9 @@ mysql.time_zone_name OK ...@@ -312,8 +313,9 @@ mysql.time_zone_name OK
mysql.time_zone_transition OK mysql.time_zone_transition OK
mysql.time_zone_transition_type OK mysql.time_zone_transition_type OK
mysql.user OK mysql.user OK
Phase 2/3: Fixing table and database names Phase 2/4: Running 'mysql_fix_privilege_tables'...
Phase 3/3: Checking and upgrading tables Phase 3/4: Fixing table and database names
Phase 4/4: Checking and upgrading tables
Processing databases Processing databases
information_schema information_schema
mtr mtr
......
...@@ -11,7 +11,7 @@ Table Op Msg_type Msg_text ...@@ -11,7 +11,7 @@ Table Op Msg_type Msg_text
test.bug49823 repair status OK test.bug49823 repair status OK
RENAME TABLE general_log TO renamed_general_log; RENAME TABLE general_log TO renamed_general_log;
RENAME TABLE test.bug49823 TO general_log; RENAME TABLE test.bug49823 TO general_log;
Phase 1/3: Running 'mysql_fix_privilege_tables'... Phase 1/4: Checking mysql database
Processing databases Processing databases
mysql mysql
mysql.column_stats OK mysql.column_stats OK
...@@ -43,8 +43,9 @@ mysql.time_zone_name OK ...@@ -43,8 +43,9 @@ mysql.time_zone_name OK
mysql.time_zone_transition OK mysql.time_zone_transition OK
mysql.time_zone_transition_type OK mysql.time_zone_transition_type OK
mysql.user OK mysql.user OK
Phase 2/3: Fixing table and database names Phase 2/4: Running 'mysql_fix_privilege_tables'...
Phase 3/3: Checking and upgrading tables Phase 3/4: Fixing table and database names
Phase 4/4: Checking and upgrading tables
Processing databases Processing databases
information_schema information_schema
mtr mtr
......
File mode changed from 100644 to 100755
...@@ -32,13 +32,6 @@ SET_SOURCE_FILES_PROPERTIES(${GEN_SOURCES} PROPERTIES GENERATED 1) ...@@ -32,13 +32,6 @@ SET_SOURCE_FILES_PROPERTIES(${GEN_SOURCES} PROPERTIES GENERATED 1)
ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER) ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER)
IF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR
CMAKE_SYSTEM_NAME MATCHES "Windows" OR
CMAKE_SYSTEM_NAME MATCHES "SunOS" OR
HAVE_KQUEUE)
ADD_DEFINITIONS(-DHAVE_POOL_OF_THREADS)
ENDIF()
IF(SSL_DEFINES) IF(SSL_DEFINES)
ADD_DEFINITIONS(${SSL_DEFINES}) ADD_DEFINITIONS(${SSL_DEFINES})
ENDIF() ENDIF()
...@@ -105,10 +98,16 @@ SET (SQL_SOURCE ...@@ -105,10 +98,16 @@ SET (SQL_SOURCE
${MYSYS_LIBWRAP_SOURCE} ${MYSYS_LIBWRAP_SOURCE}
) )
IF(WIN32) IF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR
CMAKE_SYSTEM_NAME MATCHES "Windows" OR
CMAKE_SYSTEM_NAME MATCHES "SunOS" OR
HAVE_KQUEUE)
ADD_DEFINITIONS(-DHAVE_POOL_OF_THREADS)
IF(WIN32)
SET(SQL_SOURCE ${SQL_SOURCE} threadpool_win.cc) SET(SQL_SOURCE ${SQL_SOURCE} threadpool_win.cc)
ELSE() ELSE()
SET(SQL_SOURCE ${SQL_SOURCE} threadpool_unix.cc) SET(SQL_SOURCE ${SQL_SOURCE} threadpool_unix.cc)
ENDIF()
ENDIF() ENDIF()
MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY
......
...@@ -123,6 +123,25 @@ IF(NOT CMAKE_CROSSCOMPILING) ...@@ -123,6 +123,25 @@ IF(NOT CMAKE_CROSSCOMPILING)
}" }"
HAVE_IB_GCC_ATOMIC_BUILTINS_64 HAVE_IB_GCC_ATOMIC_BUILTINS_64
) )
CHECK_C_SOURCE_RUNS(
"#include<stdint.h>
int main()
{
__sync_synchronize();
return(0);
}"
HAVE_IB_GCC_SYNC_SYNCHRONISE
)
CHECK_C_SOURCE_RUNS(
"#include<stdint.h>
int main()
{
__atomic_thread_fence(__ATOMIC_ACQUIRE);
__atomic_thread_fence(__ATOMIC_RELEASE);
return(0);
}"
HAVE_IB_GCC_ATOMIC_THREAD_FENCE
)
ENDIF() ENDIF()
IF(HAVE_IB_GCC_ATOMIC_BUILTINS) IF(HAVE_IB_GCC_ATOMIC_BUILTINS)
...@@ -133,6 +152,14 @@ IF(HAVE_IB_GCC_ATOMIC_BUILTINS_64) ...@@ -133,6 +152,14 @@ IF(HAVE_IB_GCC_ATOMIC_BUILTINS_64)
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_64=1) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_64=1)
ENDIF() 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()
# either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not # either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not
IF(NOT CMAKE_CROSSCOMPILING) IF(NOT CMAKE_CROSSCOMPILING)
CHECK_C_SOURCE_RUNS( CHECK_C_SOURCE_RUNS(
...@@ -214,10 +241,21 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS") ...@@ -214,10 +241,21 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
return(0); return(0);
} }
" HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) " 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)
ENDIF() ENDIF()
IF(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) IF(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS)
ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_SOLARIS=1) ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_SOLARIS=1)
ENDIF() ENDIF()
IF(HAVE_IB_MACHINE_BARRIER_SOLARIS)
ADD_DEFINITIONS(-DHAVE_IB_MACHINE_BARRIER_SOLARIS=1)
ENDIF()
ENDIF() ENDIF()
...@@ -235,6 +273,7 @@ ENDIF() ...@@ -235,6 +273,7 @@ ENDIF()
IF(MSVC) IF(MSVC)
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS) ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS)
ADD_DEFINITIONS(-DHAVE_WINDOWS_MM_FENCE)
ENDIF() ENDIF()
......
...@@ -147,6 +147,13 @@ lsn_t ...@@ -147,6 +147,13 @@ lsn_t
log_get_lsn(void); log_get_lsn(void);
/*=============*/ /*=============*/
/************************************************************//** /************************************************************//**
Gets the current lsn.
@return current lsn */
UNIV_INLINE
lsn_t
log_get_lsn_nowait(void);
/*=============*/
/************************************************************//**
Gets the last lsn that is fully flushed to disk. Gets the last lsn that is fully flushed to disk.
@return last flushed lsn */ @return last flushed lsn */
UNIV_INLINE UNIV_INLINE
......
...@@ -434,6 +434,26 @@ log_get_flush_lsn(void) ...@@ -434,6 +434,26 @@ log_get_flush_lsn(void)
return(lsn); return(lsn);
} }
/************************************************************//**
Gets the current lsn with a trylock
@return current lsn or 0 if false*/
UNIV_INLINE
lsn_t
log_get_lsn_nowait(void)
/*=============*/
{
lsn_t lsn;
if (mutex_enter_nowait(&(log_sys->mutex)))
return 0;
lsn = log_sys->lsn;
mutex_exit(&(log_sys->mutex));
return(lsn);
}
/**************************************************************** /****************************************************************
Gets the log group capacity. It is OK to read the value without Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant. holding log_sys->mutex because it is constant.
......
...@@ -694,6 +694,54 @@ for synchronization */ ...@@ -694,6 +694,54 @@ for synchronization */
os_decrement_counter_by_amount(mutex, counter, 1);\ os_decrement_counter_by_amount(mutex, counter, 1);\
} while (0); } while (0);
/** 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)
#ifdef __powerpc__
# define os_isync __asm __volatile ("isync":::"memory")
#else
#define os_isync do { } while(0)
#endif
# 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 os_isync __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 os_isync os_rmb; os_wmb
# define IB_MEMORY_BARRIER_STARTUP_MSG \
"Soralis memory ordering functions are used for memory barrier"
#elif defined(HAVE_WINDOWS_MM_FENCE)
# define HAVE_MEMORY_BARRIER
# include <mmintrin.h>
# define os_rmb _mm_lfence()
# define os_wmb _mm_sfence()
# define os_isync os_rmb; os_wmb
# define IB_MEMORY_BARRIER_STARTUP_MSG \
"_mm_lfence() and _mm_sfence() are used for memory barrier"
#else
# define os_rmb do { } while(0)
# define os_wmb do { } while(0)
# define os_isync do { } while(0)
# define IB_MEMORY_BARRIER_STARTUP_MSG \
"Memory barrier is not used"
#endif
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "os0sync.ic" #include "os0sync.ic"
#endif #endif
......
...@@ -199,14 +199,14 @@ rw_lock_lock_word_decr( ...@@ -199,14 +199,14 @@ rw_lock_lock_word_decr(
ulint amount) /*!< in: amount to decrement */ ulint amount) /*!< in: amount to decrement */
{ {
#ifdef INNODB_RW_LOCKS_USE_ATOMICS #ifdef INNODB_RW_LOCKS_USE_ATOMICS
lint local_lock_word = lock->lock_word; lint local_lock_word;
while (local_lock_word > 0) { os_rmb;
while ((local_lock_word= lock->lock_word) > 0) {
if (os_compare_and_swap_lint(&lock->lock_word, if (os_compare_and_swap_lint(&lock->lock_word,
local_lock_word, local_lock_word,
local_lock_word - amount)) { local_lock_word - amount)) {
return(TRUE); return(TRUE);
} }
local_lock_word = lock->lock_word;
} }
return(FALSE); return(FALSE);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */ #else /* INNODB_RW_LOCKS_USE_ATOMICS */
......
...@@ -92,6 +92,7 @@ ib_mutex_test_and_set( ...@@ -92,6 +92,7 @@ ib_mutex_test_and_set(
ut_a(mutex->lock_word == 0); ut_a(mutex->lock_word == 0);
mutex->lock_word = 1; mutex->lock_word = 1;
os_wmb;
} }
return((byte) ret); return((byte) ret);
...@@ -144,6 +145,7 @@ mutex_get_waiters( ...@@ -144,6 +145,7 @@ mutex_get_waiters(
ptr = &(mutex->waiters); ptr = &(mutex->waiters);
os_rmb;
return(*ptr); /* Here we assume that the read of a single return(*ptr); /* Here we assume that the read of a single
word from memory is atomic */ word from memory is atomic */
} }
...@@ -178,6 +180,7 @@ mutex_exit_func( ...@@ -178,6 +180,7 @@ mutex_exit_func(
to wake up possible hanging threads if to wake up possible hanging threads if
they are missed in mutex_signal_object. */ they are missed in mutex_signal_object. */
os_isync;
if (mutex_get_waiters(mutex) != 0) { if (mutex_get_waiters(mutex) != 0) {
mutex_signal_object(mutex); mutex_signal_object(mutex);
......
...@@ -356,7 +356,12 @@ UNIV_INTERN ibool srv_use_posix_fallocate = TRUE; ...@@ -356,7 +356,12 @@ UNIV_INTERN ibool srv_use_posix_fallocate = TRUE;
UNIV_INTERN ulong srv_replication_delay = 0; UNIV_INTERN 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;
#else
UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
#endif
UNIV_INTERN ulong srv_spin_wait_delay = 6; UNIV_INTERN ulong srv_spin_wait_delay = 6;
UNIV_INTERN ibool srv_priority_boost = TRUE; UNIV_INTERN ibool srv_priority_boost = TRUE;
...@@ -1709,9 +1714,10 @@ DECLARE_THREAD(srv_error_monitor_thread)( ...@@ -1709,9 +1714,10 @@ DECLARE_THREAD(srv_error_monitor_thread)(
/* Try to track a strange bug reported by Harald Fuchs and others, /* Try to track a strange bug reported by Harald Fuchs and others,
where the lsn seems to decrease at times */ where the lsn seems to decrease at times */
new_lsn = log_get_lsn(); /* We have to use nowait to ensure we don't block */
new_lsn= log_get_lsn_nowait();
if (new_lsn < old_lsn) { if (new_lsn && new_lsn < old_lsn) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: Error: old log sequence number " LSN_PF " InnoDB: Error: old log sequence number " LSN_PF
...@@ -1723,6 +1729,7 @@ DECLARE_THREAD(srv_error_monitor_thread)( ...@@ -1723,6 +1729,7 @@ DECLARE_THREAD(srv_error_monitor_thread)(
ut_ad(0); ut_ad(0);
} }
if (new_lsn)
old_lsn = new_lsn; old_lsn = new_lsn;
if (difftime(time(NULL), srv_last_monitor_time) > 60) { if (difftime(time(NULL), srv_last_monitor_time) > 60) {
......
...@@ -758,6 +758,7 @@ sync_arr_cell_can_wake_up( ...@@ -758,6 +758,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object); lock = static_cast<rw_lock_t*>(cell->wait_object);
os_rmb;
if (lock->lock_word > 0) { if (lock->lock_word > 0) {
/* Either unlocked or only read locked. */ /* Either unlocked or only read locked. */
...@@ -769,6 +770,7 @@ sync_arr_cell_can_wake_up( ...@@ -769,6 +770,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object); lock = static_cast<rw_lock_t*>(cell->wait_object);
/* lock_word == 0 means all readers have left */ /* lock_word == 0 means all readers have left */
os_rmb;
if (lock->lock_word == 0) { if (lock->lock_word == 0) {
return(TRUE); return(TRUE);
...@@ -777,6 +779,7 @@ sync_arr_cell_can_wake_up( ...@@ -777,6 +779,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object); lock = static_cast<rw_lock_t*>(cell->wait_object);
/* lock_word > 0 means no writer or reserved writer */ /* lock_word > 0 means no writer or reserved writer */
os_rmb;
if (lock->lock_word > 0) { if (lock->lock_word > 0) {
return(TRUE); return(TRUE);
......
...@@ -41,6 +41,7 @@ Created 9/11/1995 Heikki Tuuri ...@@ -41,6 +41,7 @@ Created 9/11/1995 Heikki Tuuri
#include "srv0srv.h" #include "srv0srv.h"
#include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ #include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
#include "ha_prototypes.h" #include "ha_prototypes.h"
#include "my_cpu.h"
/* /*
IMPLEMENTATION OF THE RW_LOCK IMPLEMENTATION OF THE RW_LOCK
...@@ -375,15 +376,19 @@ rw_lock_s_lock_spin( ...@@ -375,15 +376,19 @@ rw_lock_s_lock_spin(
lock_loop: lock_loop:
/* Spin waiting for the writer field to become free */ /* Spin waiting for the writer field to become free */
os_rmb;
HMT_low();
while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) { while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) {
if (srv_spin_wait_delay) { if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
} }
i++; i++;
os_rmb;
} }
if (i == SYNC_SPIN_ROUNDS) { HMT_medium();
if (lock->lock_word <= 0) {
os_thread_yield(); os_thread_yield();
} }
...@@ -472,14 +477,18 @@ rw_lock_x_lock_wait( ...@@ -472,14 +477,18 @@ rw_lock_x_lock_wait(
ut_ad(lock->lock_word <= 0); ut_ad(lock->lock_word <= 0);
os_rmb;
HMT_low();
while (lock->lock_word < 0) { while (lock->lock_word < 0) {
if (srv_spin_wait_delay) { if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
} }
if(i < SYNC_SPIN_ROUNDS) { if(i < SYNC_SPIN_ROUNDS) {
i++; i++;
os_rmb;
continue; continue;
} }
HMT_medium();
/* If there is still a reader, then go to sleep.*/ /* If there is still a reader, then go to sleep.*/
rw_lock_stats.rw_x_spin_round_count.add(counter_index, i); rw_lock_stats.rw_x_spin_round_count.add(counter_index, i);
...@@ -516,7 +525,9 @@ rw_lock_x_lock_wait( ...@@ -516,7 +525,9 @@ rw_lock_x_lock_wait(
} else { } else {
sync_array_free_cell(sync_arr, index); sync_array_free_cell(sync_arr, index);
} }
HMT_low();
} }
HMT_medium();
rw_lock_stats.rw_x_spin_round_count.add(counter_index, i); rw_lock_stats.rw_x_spin_round_count.add(counter_index, i);
} }
...@@ -553,7 +564,8 @@ rw_lock_x_lock_low( ...@@ -553,7 +564,8 @@ rw_lock_x_lock_low(
} else { } else {
os_thread_id_t thread_id = os_thread_get_curr_id(); os_thread_id_t thread_id = os_thread_get_curr_id();
if (!pass)
os_rmb;
/* Decrement failed: relock or failed lock */ /* Decrement failed: relock or failed lock */
if (!pass && lock->recursive if (!pass && lock->recursive
&& os_thread_eq(lock->writer_thread, thread_id)) { && os_thread_eq(lock->writer_thread, thread_id)) {
...@@ -632,6 +644,8 @@ rw_lock_x_lock_func( ...@@ -632,6 +644,8 @@ rw_lock_x_lock_func(
} }
/* Spin waiting for the lock_word to become free */ /* Spin waiting for the lock_word to become free */
os_rmb;
HMT_low();
while (i < SYNC_SPIN_ROUNDS while (i < SYNC_SPIN_ROUNDS
&& lock->lock_word <= 0) { && lock->lock_word <= 0) {
if (srv_spin_wait_delay) { if (srv_spin_wait_delay) {
...@@ -640,7 +654,9 @@ rw_lock_x_lock_func( ...@@ -640,7 +654,9 @@ rw_lock_x_lock_func(
} }
i++; i++;
os_rmb;
} }
HMT_medium();
if (i == SYNC_SPIN_ROUNDS) { if (i == SYNC_SPIN_ROUNDS) {
os_thread_yield(); os_thread_yield();
} else { } else {
......
...@@ -45,6 +45,7 @@ Created 9/5/1995 Heikki Tuuri ...@@ -45,6 +45,7 @@ Created 9/5/1995 Heikki Tuuri
# include "srv0start.h" /* srv_is_being_started */ # include "srv0start.h" /* srv_is_being_started */
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
#include "ha_prototypes.h" #include "ha_prototypes.h"
#include "my_cpu.h"
/* /*
REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
...@@ -456,6 +457,8 @@ mutex_set_waiters( ...@@ -456,6 +457,8 @@ mutex_set_waiters(
ptr = &(mutex->waiters); ptr = &(mutex->waiters);
os_wmb;
*ptr = n; /* Here we assume that the write of a single *ptr = n; /* Here we assume that the write of a single
word in memory is atomic */ word in memory is atomic */
} }
...@@ -500,13 +503,15 @@ mutex_spin_wait( ...@@ -500,13 +503,15 @@ mutex_spin_wait(
spin_loop: spin_loop:
HMT_low();
while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) {
if (srv_spin_wait_delay) { if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
} }
os_rmb; // Ensure future reads sees new values
i++; i++;
} }
HMT_medium();
if (i == SYNC_SPIN_ROUNDS) { if (i == SYNC_SPIN_ROUNDS) {
os_thread_yield(); os_thread_yield();
......
# verify that information_schema.tokudb_locks gets populated with locks, information_schema.tokudb_lock_waits gets # verify that information_schema.tokudb_locks gets populated with locks, information_schema.tokudb_lock_waits gets
if (`select @@tokudb_version <= "7.1.6"`) if (`select @@tokudb_version <= "7.1.7"`)
{ {
--skip Race condition in the test in TokuDB 7.1.6 or earlier --skip Race condition in the test in TokuDB 7.1.7 or earlier
} }
# populated with 1 lock_wait and all transactions are present in information_schema.tokudb_trx for 2 clients # populated with 1 lock_wait and all transactions are present in information_schema.tokudb_trx for 2 clients
......
if (`select @@tokudb_version <= "7.1.6"`) if (`select @@tokudb_version <= "7.1.7"`)
{ {
--skip Race condition in the test in TokuDB 7.1.6 or earlier --skip Race condition in the test in TokuDB 7.1.7 or earlier
} }
# verify that information_schema.tokudb_locks gets populated with locks for 2 clients # verify that information_schema.tokudb_locks gets populated with locks for 2 clients
......
...@@ -129,6 +129,25 @@ IF(NOT CMAKE_CROSSCOMPILING) ...@@ -129,6 +129,25 @@ IF(NOT CMAKE_CROSSCOMPILING)
}" }"
HAVE_IB_GCC_ATOMIC_BUILTINS_64 HAVE_IB_GCC_ATOMIC_BUILTINS_64
) )
CHECK_C_SOURCE_RUNS(
"#include<stdint.h>
int main()
{
__sync_synchronize();
return(0);
}"
HAVE_IB_GCC_SYNC_SYNCHRONISE
)
CHECK_C_SOURCE_RUNS(
"#include<stdint.h>
int main()
{
__atomic_thread_fence(__ATOMIC_ACQUIRE);
__atomic_thread_fence(__ATOMIC_RELEASE);
return(0);
}"
HAVE_IB_GCC_ATOMIC_THREAD_FENCE
)
ENDIF() ENDIF()
IF(HAVE_IB_GCC_ATOMIC_BUILTINS) IF(HAVE_IB_GCC_ATOMIC_BUILTINS)
...@@ -140,6 +159,14 @@ IF(HAVE_IB_GCC_ATOMIC_BUILTINS_64) ...@@ -140,6 +159,14 @@ IF(HAVE_IB_GCC_ATOMIC_BUILTINS_64)
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_64=1) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_64=1)
ENDIF() 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()
# either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not # either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not
IF(NOT CMAKE_CROSSCOMPILING) IF(NOT CMAKE_CROSSCOMPILING)
CHECK_C_SOURCE_RUNS( CHECK_C_SOURCE_RUNS(
...@@ -222,10 +249,21 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS") ...@@ -222,10 +249,21 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
return(0); return(0);
} }
" HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) " 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)
ENDIF() ENDIF()
IF(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) IF(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS)
ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_SOLARIS=1) ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_SOLARIS=1)
ENDIF() ENDIF()
IF(HAVE_IB_MACHINE_BARRIER_SOLARIS)
ADD_DEFINITIONS(-DHAVE_IB_MACHINE_BARRIER_SOLARIS=1)
ENDIF()
ENDIF() ENDIF()
...@@ -243,6 +281,7 @@ ENDIF() ...@@ -243,6 +281,7 @@ ENDIF()
IF(MSVC) IF(MSVC)
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS) ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS)
ADD_DEFINITIONS(-DHAVE_WINDOWS_MM_FENCE)
SET(XTRADB_OK 1) SET(XTRADB_OK 1)
# Avoid "unreferenced label" warning in generated file # Avoid "unreferenced label" warning in generated file
......
...@@ -168,6 +168,13 @@ lsn_t ...@@ -168,6 +168,13 @@ lsn_t
log_get_lsn(void); log_get_lsn(void);
/*=============*/ /*=============*/
/************************************************************//** /************************************************************//**
Gets the current lsn.
@return current lsn */
UNIV_INLINE
lsn_t
log_get_lsn_nowait(void);
/*=============*/
/************************************************************//**
Gets the last lsn that is fully flushed to disk. Gets the last lsn that is fully flushed to disk.
@return last flushed lsn */ @return last flushed lsn */
UNIV_INLINE UNIV_INLINE
......
...@@ -486,6 +486,26 @@ log_get_flush_lsn(void) ...@@ -486,6 +486,26 @@ log_get_flush_lsn(void)
return(lsn); return(lsn);
} }
/************************************************************//**
Gets the current lsn with a trylock
@return current lsn or 0 if false*/
UNIV_INLINE
lsn_t
log_get_lsn_nowait(void)
/*=============*/
{
lsn_t lsn;
if (mutex_enter_nowait(&(log_sys->mutex)))
return 0;
lsn = log_sys->lsn;
mutex_exit(&(log_sys->mutex));
return(lsn);
}
/**************************************************************** /****************************************************************
Gets the log group capacity. It is OK to read the value without Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant. holding log_sys->mutex because it is constant.
......
...@@ -694,6 +694,54 @@ for synchronization */ ...@@ -694,6 +694,54 @@ for synchronization */
os_decrement_counter_by_amount(mutex, counter, 1);\ os_decrement_counter_by_amount(mutex, counter, 1);\
} while (0); } while (0);
/** 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)
#ifdef __powerpc__
# define os_isync __asm __volatile ("isync":::"memory")
#else
#define os_isync do { } while(0)
#endif
# 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 os_isync __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 os_isync os_rmb; os_wmb
# define IB_MEMORY_BARRIER_STARTUP_MSG \
"Soralis memory ordering functions are used for memory barrier"
#elif defined(HAVE_WINDOWS_MM_FENCE)
# define HAVE_MEMORY_BARRIER
# include <mmintrin.h>
# define os_rmb _mm_lfence()
# define os_wmb _mm_sfence()
# define os_isync os_rmb; os_wmb
# define IB_MEMORY_BARRIER_STARTUP_MSG \
"_mm_lfence() and _mm_sfence() are used for memory barrier"
#else
# define os_rmb do { } while(0)
# define os_wmb do { } while(0)
# define os_isync do { } while(0)
# define IB_MEMORY_BARRIER_STARTUP_MSG \
"Memory barrier is not used"
#endif
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "os0sync.ic" #include "os0sync.ic"
#endif #endif
......
...@@ -256,14 +256,14 @@ rw_lock_lock_word_decr( ...@@ -256,14 +256,14 @@ rw_lock_lock_word_decr(
ulint amount) /*!< in: amount to decrement */ ulint amount) /*!< in: amount to decrement */
{ {
#ifdef INNODB_RW_LOCKS_USE_ATOMICS #ifdef INNODB_RW_LOCKS_USE_ATOMICS
lint local_lock_word = lock->lock_word; lint local_lock_word;
while (local_lock_word > 0) { os_rmb;
while ((local_lock_word= lock->lock_word) > 0) {
if (os_compare_and_swap_lint(&lock->lock_word, if (os_compare_and_swap_lint(&lock->lock_word,
local_lock_word, local_lock_word,
local_lock_word - amount)) { local_lock_word - amount)) {
return(TRUE); return(TRUE);
} }
local_lock_word = lock->lock_word;
} }
return(FALSE); return(FALSE);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */ #else /* INNODB_RW_LOCKS_USE_ATOMICS */
......
...@@ -95,6 +95,7 @@ ib_mutex_test_and_set( ...@@ -95,6 +95,7 @@ ib_mutex_test_and_set(
ut_a(mutex->lock_word == 0); ut_a(mutex->lock_word == 0);
mutex->lock_word = 1; mutex->lock_word = 1;
os_wmb;
} }
return((byte) ret); return((byte) ret);
...@@ -147,6 +148,7 @@ mutex_get_waiters( ...@@ -147,6 +148,7 @@ mutex_get_waiters(
ptr = &(mutex->waiters); ptr = &(mutex->waiters);
os_rmb;
return(*ptr); /* Here we assume that the read of a single return(*ptr); /* Here we assume that the read of a single
word from memory is atomic */ word from memory is atomic */
} }
...@@ -181,6 +183,7 @@ mutex_exit_func( ...@@ -181,6 +183,7 @@ mutex_exit_func(
to wake up possible hanging threads if to wake up possible hanging threads if
they are missed in mutex_signal_object. */ they are missed in mutex_signal_object. */
os_isync;
if (mutex_get_waiters(mutex) != 0) { if (mutex_get_waiters(mutex) != 0) {
mutex_signal_object(mutex); mutex_signal_object(mutex);
......
...@@ -477,7 +477,12 @@ UNIV_INTERN ulong srv_log_checksum_algorithm = ...@@ -477,7 +477,12 @@ UNIV_INTERN ulong srv_log_checksum_algorithm =
SRV_CHECKSUM_ALGORITHM_INNODB; SRV_CHECKSUM_ALGORITHM_INNODB;
/*-------------------------------------------*/ /*-------------------------------------------*/
#ifdef HAVE_MEMORY_BARRIER
/* No idea to wait long with memory barriers */
UNIV_INTERN ulong srv_n_spin_wait_rounds = 15;
#else
UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
#endif
UNIV_INTERN ulong srv_spin_wait_delay = 6; UNIV_INTERN ulong srv_spin_wait_delay = 6;
UNIV_INTERN ibool srv_priority_boost = TRUE; UNIV_INTERN ibool srv_priority_boost = TRUE;
...@@ -2094,9 +2099,10 @@ DECLARE_THREAD(srv_error_monitor_thread)( ...@@ -2094,9 +2099,10 @@ DECLARE_THREAD(srv_error_monitor_thread)(
/* Try to track a strange bug reported by Harald Fuchs and others, /* Try to track a strange bug reported by Harald Fuchs and others,
where the lsn seems to decrease at times */ where the lsn seems to decrease at times */
new_lsn = log_get_lsn(); /* We have to use nowait to ensure we don't block */
new_lsn= log_get_lsn_nowait();
if (new_lsn < old_lsn) { if (new_lsn && new_lsn < old_lsn) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: Error: old log sequence number " LSN_PF " InnoDB: Error: old log sequence number " LSN_PF
...@@ -2108,6 +2114,7 @@ DECLARE_THREAD(srv_error_monitor_thread)( ...@@ -2108,6 +2114,7 @@ DECLARE_THREAD(srv_error_monitor_thread)(
ut_ad(0); ut_ad(0);
} }
if (new_lsn)
old_lsn = new_lsn; old_lsn = new_lsn;
if (difftime(time(NULL), srv_last_monitor_time) > 60) { if (difftime(time(NULL), srv_last_monitor_time) > 60) {
......
...@@ -849,6 +849,7 @@ sync_arr_cell_can_wake_up( ...@@ -849,6 +849,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object); lock = static_cast<rw_lock_t*>(cell->wait_object);
os_rmb;
if (lock->lock_word > 0) { if (lock->lock_word > 0) {
/* Either unlocked or only read locked. */ /* Either unlocked or only read locked. */
...@@ -860,6 +861,7 @@ sync_arr_cell_can_wake_up( ...@@ -860,6 +861,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object); lock = static_cast<rw_lock_t*>(cell->wait_object);
/* lock_word == 0 means all readers have left */ /* lock_word == 0 means all readers have left */
os_rmb;
if (lock->lock_word == 0) { if (lock->lock_word == 0) {
return(TRUE); return(TRUE);
...@@ -869,6 +871,7 @@ sync_arr_cell_can_wake_up( ...@@ -869,6 +871,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object); lock = static_cast<rw_lock_t*>(cell->wait_object);
/* lock_word > 0 means no writer or reserved writer */ /* lock_word > 0 means no writer or reserved writer */
os_rmb;
if (lock->lock_word > 0) { if (lock->lock_word > 0) {
return(TRUE); return(TRUE);
......
...@@ -41,6 +41,7 @@ Created 9/11/1995 Heikki Tuuri ...@@ -41,6 +41,7 @@ Created 9/11/1995 Heikki Tuuri
#include "srv0srv.h" #include "srv0srv.h"
#include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ #include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
#include "ha_prototypes.h" #include "ha_prototypes.h"
#include "my_cpu.h"
/* /*
IMPLEMENTATION OF THE RW_LOCK IMPLEMENTATION OF THE RW_LOCK
...@@ -448,6 +449,8 @@ rw_lock_s_lock_spin( ...@@ -448,6 +449,8 @@ rw_lock_s_lock_spin(
lock)) { lock)) {
/* Spin waiting for the writer field to become free */ /* Spin waiting for the writer field to become free */
os_rmb;
HMT_low();
while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) { while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) {
if (srv_spin_wait_delay) { if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, ut_delay(ut_rnd_interval(0,
...@@ -455,9 +458,11 @@ rw_lock_s_lock_spin( ...@@ -455,9 +458,11 @@ rw_lock_s_lock_spin(
} }
i++; i++;
os_rmb;
} }
if (i == SYNC_SPIN_ROUNDS) { HMT_medium();
if (lock->lock_word <= 0) {
os_thread_yield(); os_thread_yield();
} }
...@@ -605,14 +610,18 @@ rw_lock_x_lock_wait( ...@@ -605,14 +610,18 @@ rw_lock_x_lock_wait(
ut_ad(lock->lock_word <= 0); ut_ad(lock->lock_word <= 0);
os_rmb;
HMT_low();
while (lock->lock_word < 0) { while (lock->lock_word < 0) {
if (srv_spin_wait_delay) { if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
} }
if(i < SYNC_SPIN_ROUNDS) { if(i < SYNC_SPIN_ROUNDS) {
i++; i++;
os_rmb;
continue; continue;
} }
HMT_medium();
/* If there is still a reader, then go to sleep.*/ /* If there is still a reader, then go to sleep.*/
rw_lock_stats.rw_x_spin_round_count.add(counter_index, i); rw_lock_stats.rw_x_spin_round_count.add(counter_index, i);
...@@ -660,7 +669,9 @@ rw_lock_x_lock_wait( ...@@ -660,7 +669,9 @@ rw_lock_x_lock_wait(
prio_rw_lock->high_priority_wait_ex_waiter = 0; prio_rw_lock->high_priority_wait_ex_waiter = 0;
} }
} }
HMT_low();
} }
HMT_medium();
rw_lock_stats.rw_x_spin_round_count.add(counter_index, i); rw_lock_stats.rw_x_spin_round_count.add(counter_index, i);
} }
...@@ -701,7 +712,8 @@ rw_lock_x_lock_low( ...@@ -701,7 +712,8 @@ rw_lock_x_lock_low(
} else { } else {
os_thread_id_t thread_id = os_thread_get_curr_id(); os_thread_id_t thread_id = os_thread_get_curr_id();
if (!pass)
os_rmb;
/* Decrement failed: relock or failed lock */ /* Decrement failed: relock or failed lock */
if (!pass && lock->recursive if (!pass && lock->recursive
&& os_thread_eq(lock->writer_thread, thread_id)) { && os_thread_eq(lock->writer_thread, thread_id)) {
...@@ -792,6 +804,8 @@ rw_lock_x_lock_func( ...@@ -792,6 +804,8 @@ rw_lock_x_lock_func(
} }
/* Spin waiting for the lock_word to become free */ /* Spin waiting for the lock_word to become free */
os_rmb;
HMT_low();
while (i < SYNC_SPIN_ROUNDS while (i < SYNC_SPIN_ROUNDS
&& lock->lock_word <= 0) { && lock->lock_word <= 0) {
if (srv_spin_wait_delay) { if (srv_spin_wait_delay) {
...@@ -800,7 +814,9 @@ rw_lock_x_lock_func( ...@@ -800,7 +814,9 @@ rw_lock_x_lock_func(
} }
i++; i++;
os_rmb;
} }
HMT_medium();
if (i == SYNC_SPIN_ROUNDS) { if (i == SYNC_SPIN_ROUNDS) {
os_thread_yield(); os_thread_yield();
} else { } else {
......
...@@ -46,6 +46,7 @@ Created 9/5/1995 Heikki Tuuri ...@@ -46,6 +46,7 @@ Created 9/5/1995 Heikki Tuuri
# include "srv0start.h" /* srv_is_being_started */ # include "srv0start.h" /* srv_is_being_started */
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
#include "ha_prototypes.h" #include "ha_prototypes.h"
#include "my_cpu.h"
/* /*
REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
...@@ -535,6 +536,8 @@ mutex_set_waiters( ...@@ -535,6 +536,8 @@ mutex_set_waiters(
ptr = &(mutex->waiters); ptr = &(mutex->waiters);
os_wmb;
*ptr = n; /* Here we assume that the write of a single *ptr = n; /* Here we assume that the write of a single
word in memory is atomic */ word in memory is atomic */
} }
...@@ -587,13 +590,15 @@ mutex_spin_wait( ...@@ -587,13 +590,15 @@ mutex_spin_wait(
spin_loop: spin_loop:
HMT_low();
while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) {
if (srv_spin_wait_delay) { if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
} }
os_rmb; // Ensure future reads sees new values
i++; i++;
} }
HMT_medium();
if (i == SYNC_SPIN_ROUNDS) { if (i == SYNC_SPIN_ROUNDS) {
os_thread_yield(); os_thread_yield();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment