From 7e065ee9ae35e6ac501c1d6a3c06cd83039ab290 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom <mikael@mysql.com> Date: Thu, 30 Oct 2008 10:23:36 +0100 Subject: [PATCH] Merge port of Google SMP patch to Solaris --- storage/innobase/handler/ha_innodb.cc | 4 ++-- storage/innobase/include/os0sync.h | 9 ++++++-- storage/innobase/include/os0sync.ic | 30 ++++++++++++++++++--------- storage/innobase/include/srv0srv.h | 2 +- storage/innobase/include/sync0rw.h | 4 ++-- storage/innobase/include/sync0rw.ic | 16 +++++++------- storage/innobase/include/sync0sync.h | 6 +++++- storage/innobase/include/sync0sync.ic | 9 ++++---- storage/innobase/include/univ.i | 7 +++++++ storage/innobase/srv/srv0srv.c | 6 +++--- storage/innobase/srv/srv0start.c | 4 ++-- storage/innobase/sync/sync0arr.c | 4 ++-- storage/innobase/sync/sync0rw.c | 24 ++++++++++----------- storage/innobase/sync/sync0sync.c | 4 ++-- 14 files changed, 78 insertions(+), 51 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c1c497214db..06378462c53 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -389,8 +389,8 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG}, {"dblwr_writes", (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG}, - {"have_atomic_builtins", - (char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL}, + {"have_sync_atomic", + (char*) &export_vars.innodb_have_sync_atomic, SHOW_BOOL}, {"heap_enabled", (char*) &export_vars.innodb_heap_enabled, SHOW_BOOL}, {"log_waits", diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index 5533df4f608..28e67483fa6 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -12,6 +12,10 @@ Created 9/6/1995 Heikki Tuuri #include "univ.i" #include "ut0lst.h" +#ifdef HAVE_SOLARIS_ATOMIC +#include <atomic.h> +#endif + #ifdef __WIN__ #define os_fast_mutex_t CRITICAL_SECTION @@ -261,7 +265,7 @@ os_fast_mutex_free( /*===============*/ os_fast_mutex_t* fast_mutex); /* in: mutex to free */ -#ifdef HAVE_GCC_ATOMIC_BUILTINS +#ifdef UNIV_SYNC_ATOMIC /************************************************************** Atomic compare-and-swap for InnoDB. Currently requires GCC atomic builtins. */ UNIV_INLINE @@ -272,6 +276,7 @@ os_compare_and_swap( volatile lint* ptr, /* in: pointer to target */ lint oldVal, /* in: value to compare to */ lint newVal); /* in: value to swap in */ + /************************************************************** Atomic increment for InnoDB. Currently requires GCC atomic builtins. */ UNIV_INLINE @@ -282,7 +287,7 @@ os_atomic_increment( volatile lint* ptr, /* in: pointer to target */ lint amount); /* in: amount of increment */ -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ +#endif /* UNIV_SYNC_ATOMIC */ #ifndef UNIV_NONINL #include "os0sync.ic" diff --git a/storage/innobase/include/os0sync.ic b/storage/innobase/include/os0sync.ic index 2a962529d95..4370e07e672 100644 --- a/storage/innobase/include/os0sync.ic +++ b/storage/innobase/include/os0sync.ic @@ -45,9 +45,10 @@ os_fast_mutex_trylock( #endif } -#ifdef HAVE_GCC_ATOMIC_BUILTINS +#ifdef UNIV_SYNC_ATOMIC /************************************************************** -Atomic compare-and-swap for InnoDB. Currently requires GCC atomic builtins. */ +Atomic compare-and-swap for InnoDB. Currently requires GCC atomic builtins +or Solaris atomic_* functions. */ UNIV_INLINE ibool os_compare_and_swap( @@ -57,11 +58,15 @@ os_compare_and_swap( lint oldVal, /* in: value to compare to */ lint newVal) /* in: value to swap in */ { - if(__sync_bool_compare_and_swap(ptr, oldVal, newVal)) { - return(TRUE); - } - - return(FALSE); +#ifdef HAVE_GCC_ATOMIC_BULTINS + return (__sync_bool_compare_and_swap(ptr, oldVal, newVal)); +#elif HAVE_SOLARIS_ATOMIC + lint retVal = (lint)atomic_cas_ulong((volatile ulong_t *)ptr, + oldVal, newVal); + return (retVal == oldVal); +#else +#error "Need support for atomic ops" +#endif } /************************************************************** @@ -74,8 +79,13 @@ os_atomic_increment( volatile lint* ptr, /* in: pointer to target */ lint amount) /* in: amount of increment */ { - lint newVal = __sync_add_and_fetch(ptr, amount); - return newVal; +#ifdef HAVE_GCC_ATOMIC_BULTINS + return (__sync_add_and_fetch(ptr, amount)); +#elif HAVE_SOLARIS_ATOMIC + return ((lint)atomic_add_long_nv((volatile ulong_t *)ptr, amount)); +#else +#error "Need support for atomic ops" +#endif } -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ +#endif /* UNIV_SYNC_ATOMIC */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index c8a84ca390a..528c4053a2e 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -523,7 +523,7 @@ struct export_var_struct{ ulint innodb_buffer_pool_read_ahead_rnd; ulint innodb_dblwr_pages_written; ulint innodb_dblwr_writes; - ibool innodb_have_atomic_builtins; + ibool innodb_have_sync_atomic; ibool innodb_heap_enabled; ulint innodb_log_waits; ulint innodb_log_write_requests; diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h index f329e7d161c..6de26535689 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -460,9 +460,9 @@ struct rw_lock_struct { os_event_t wait_ex_event; /* Event for next-writer to wait on. A thread must decrement lock_word before waiting. */ -#ifndef HAVE_GCC_ATOMIC_BUILTINS +#ifndef UNIV_SYNC_ATOMIC mutex_t mutex; /* The mutex protecting rw_lock_struct */ -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ +#endif /* UNIV_SYNC_ATOMIC */ UT_LIST_NODE_T(rw_lock_t) list; /* All allocated rw locks are put into a diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index bcadff0bd67..d5d3ee954be 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -103,7 +103,7 @@ rw_lock_get_reader_count( return 0; } -#ifndef HAVE_GCC_ATOMIC_BUILTINS +#ifndef UNIV_SYNC_ATOMIC UNIV_INLINE mutex_t* rw_lock_get_mutex( @@ -146,7 +146,7 @@ rw_lock_lock_word_decr( ulint amount) /* in: amount of decrement */ { -#ifdef HAVE_GCC_ATOMIC_BUILTINS +#ifdef UNIV_SYNC_ATOMIC lint local_lock_word = lock->lock_word; while (local_lock_word > 0) { @@ -159,7 +159,7 @@ rw_lock_lock_word_decr( } return(FALSE); -#else /* HAVE_GCC_ATOMIC_BUILTINS */ +#else /* UNIV_SYNC_ATOMIC */ ibool success = FALSE; mutex_enter(&(lock->mutex)); @@ -170,7 +170,7 @@ rw_lock_lock_word_decr( mutex_exit(&(lock->mutex)); return success; -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ +#endif /* UNIV_SYNC_ATOMIC */ } @@ -186,11 +186,11 @@ rw_lock_lock_word_incr( ulint amount) /* in: amount of increment */ { -#ifdef HAVE_GCC_ATOMIC_BUILTINS +#ifdef UNIV_SYNC_ATOMIC return(os_atomic_increment(&(lock->lock_word), amount)); -#else /* HAVE_GCC_ATOMIC_BUILTINS */ +#else /* UNIV_SYNC_ATOMIC */ lint local_lock_word; @@ -203,7 +203,7 @@ rw_lock_lock_word_incr( return local_lock_word; -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ +#endif /* UNIV_SYNC_ATOMIC */ } @@ -352,7 +352,7 @@ rw_lock_x_lock_func_nowait( ibool success; -#ifdef HAVE_GCC_ATOMIC_BUILTINS +#ifdef UNIV_SYNC_ATOMIC success = os_compare_and_swap(&(lock->lock_word), X_LOCK_DECR, 0); #else diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index cfc1c8d2c40..e311d75a189 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -16,6 +16,7 @@ Created 9/5/1995 Heikki Tuuri #include "os0thread.h" #include "os0sync.h" #include "sync0arr.h" +#include "my_atomic.h" #ifndef UNIV_HOTBACKUP extern my_bool timed_mutexes; @@ -476,7 +477,10 @@ struct mutex_struct { test-and-set instruction in Win32 and x86 32/64 with GCC 4.1.0 or later version */ #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) -#elif defined(HAVE_GCC_ATOMIC_BUILTINS) +#elif defined(MY_ATOMIC_NOLOCK) + /* We have my_atomic_* routines that are + intrinsically atomic, so no need for the + mutex. */ #else os_fast_mutex_t os_fast_mutex; /* In other systems we use this OS mutex diff --git a/storage/innobase/include/sync0sync.ic b/storage/innobase/include/sync0sync.ic index ffe8794eca5..f48077e43fe 100644 --- a/storage/innobase/include/sync0sync.ic +++ b/storage/innobase/include/sync0sync.ic @@ -88,8 +88,9 @@ mutex_test_and_set( /* mutex_fence(); */ return(res); -#elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __sync_lock_test_and_set(&(mutex->lock_word), 1); +#elif defined(MY_ATOMIC_NOLOCK) + return ((byte)my_atomic_swap8( + (int8 volatile *)&(mutex->lock_word), 1)); #else ibool ret; @@ -126,11 +127,11 @@ mutex_reset_lock_word( __asm MOV EDX, 0 __asm MOV ECX, lw __asm XCHG DL, BYTE PTR [ECX] -#elif defined(HAVE_GCC_ATOMIC_BUILTINS) +#elif defined(MY_ATOMIC_NOLOCK) /* In theory __sync_lock_release should be used to release the lock. Unfortunately, it does not work properly alone. The workaround is that more conservative __sync_lock_test_and_set is used instead. */ - __sync_lock_test_and_set(&(mutex->lock_word), 0); + (void)my_atomic_swap8((int8 volatile *)&(mutex->lock_word), 0); #else mutex->lock_word = 0; diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 6e9f3d74d22..ae6081185f7 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -123,6 +123,13 @@ by one. */ /* Use malloc instead of innodb additional memory pool (great with tcmalloc) */ #define UNIV_DISABLE_MEM_POOL +#if defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_SOLARIS_ATOMIC) +/* + * We have a full set of atomic ops available - we will use them + */ +#define UNIV_SYNC_ATOMIC +#endif + /* #define UNIV_SQL_DEBUG #define UNIV_LOG_DEBUG diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index 9ae821182bf..305be04874f 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -1900,10 +1900,10 @@ srv_export_innodb_status(void) export_vars.innodb_buffer_pool_pages_misc = buf_pool->max_size - UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free); -#ifdef HAVE_GCC_ATOMIC_BUILTINS - export_vars.innodb_have_atomic_builtins = 1; +#ifdef UNIV_SYNC_ATOMIC + export_vars.innodb_have_sync_atomic = 1; #else - export_vars.innodb_have_atomic_builtins = 0; + export_vars.innodb_have_sync_atomic = 0; #endif #ifdef UNIV_DISABLE_MEM_POOL export_vars.innodb_heap_enabled = 0; diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index 41b0cd0fcd9..f64ebab1281 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -1068,9 +1068,9 @@ innobase_start_or_create_for_mysql(void) "InnoDB: The InnoDB memory heap has been disabled.\n"); #endif -#ifdef HAVE_GCC_ATOMIC_BUILTINS +#ifdef UNIV_SYNC_ATOMIC fprintf(stderr, - "InnoDB: Mutex and rw_lock use GCC atomic builtins.\n"); + "InnoDB: Mutex and rw_lock use atomics.\n"); #endif /* Since InnoDB does not currently clean up all its internal data diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c index ee6e901ab81..5ee2a37bfd9 100644 --- a/storage/innobase/sync/sync0arr.c +++ b/storage/innobase/sync/sync0arr.c @@ -834,8 +834,8 @@ sync_array_object_signalled( /*========================*/ sync_array_t* arr) /* in: wait array */ { -#ifdef HAVE_GCC_ATOMIC_BUILTINS - __sync_fetch_and_add(&(arr->sg_count),1); +#ifdef UNIV_SYNC_ATOMIC + (void)os_atomic_increment((volatile lint *)&(arr->sg_count), 1); #else sync_array_enter(arr); diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c index 0d6cb025260..ced2f72187a 100644 --- a/storage/innobase/sync/sync0rw.c +++ b/storage/innobase/sync/sync0rw.c @@ -195,7 +195,7 @@ rw_lock_create_func( /* If this is the very first time a synchronization object is created, then the following call initializes the sync system. */ -#ifndef HAVE_GCC_ATOMIC_BUILTINS +#ifndef UNIV_SYNC_ATOMIC mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK); lock->mutex.cfile_name = cfile_name; @@ -206,7 +206,7 @@ rw_lock_create_func( lock->mutex.mutex_type = 1; #endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ +#endif /* UNIV_SYNC_ATOMIC */ lock->lock_word = X_LOCK_DECR; rw_lock_set_waiters(lock, 0); @@ -260,9 +260,9 @@ rw_lock_free( lock->magic_n = 0; -#ifndef HAVE_GCC_ATOMIC_BUILTINS +#ifndef UNIV_SYNC_ATOMIC mutex_free(rw_lock_get_mutex(lock)); -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ +#endif /* UNIV_SYNC_ATOMIC */ mutex_enter(&rw_lock_list_mutex); os_event_free(lock->event); @@ -413,13 +413,13 @@ rw_lock_x_lock_move_ownership( { ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX)); -#ifdef HAVE_GCC_ATOMIC_BUILTINS +#ifdef UNIV_SYNC_ATOMIC os_thread_id_t local_writer_thread = lock->writer_thread; os_thread_id_t new_writer_thread = os_thread_get_curr_id(); while (TRUE) { if ((int)local_writer_thread != -1) { if(os_compare_and_swap( - &(lock->writer_thread), + (volatile lint*)&(lock->writer_thread), local_writer_thread, new_writer_thread)) { break; @@ -428,12 +428,12 @@ rw_lock_x_lock_move_ownership( local_writer_thread = lock->writer_thread; } lock->pass = 0; -#else /* HAVE_GCC_ATOMIC_BUILTINS */ +#else /* UNIV_SYNC_ATOMIC */ mutex_enter(&(lock->mutex)); lock->writer_thread = os_thread_get_curr_id(); lock->pass = 0; mutex_exit(&(lock->mutex)); -#endif /* HAVE_GCC_ATOMIC_BUILTINS */ +#endif /* UNIV_SYNC_ATOMIC */ } /********************************************************************** @@ -883,7 +883,7 @@ rw_lock_list_print_info( count++; -#ifndef HAVE_GCC_ATOMIC_BUILTINS +#ifndef UNIV_SYNC_ATOMIC mutex_enter(&(lock->mutex)); #endif if (lock->lock_word != X_LOCK_DECR) { @@ -902,7 +902,7 @@ rw_lock_list_print_info( info = UT_LIST_GET_NEXT(list, info); } } -#ifndef HAVE_GCC_ATOMIC_BUILTINS +#ifndef UNIV_SYNC_ATOMIC mutex_exit(&(lock->mutex)); #endif @@ -928,7 +928,7 @@ rw_lock_print( "RW-LATCH INFO\n" "RW-LATCH: %p ", (void*) lock); -#ifndef HAVE_GCC_ATOMIC_BUILTINS +#ifndef UNIV_SYNC_ATOMIC mutex_enter(&(lock->mutex)); #endif if (lock->lock_word != X_LOCK_DECR) { @@ -945,7 +945,7 @@ rw_lock_print( info = UT_LIST_GET_NEXT(list, info); } } -#ifndef HAVE_GCC_ATOMIC_BUILTINS +#ifndef UNIV_SYNC_ATOMIC mutex_exit(&(lock->mutex)); #endif } diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c index 4176143d679..a8b1ac4926e 100644 --- a/storage/innobase/sync/sync0sync.c +++ b/storage/innobase/sync/sync0sync.c @@ -238,7 +238,7 @@ mutex_create_func( { #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) mutex_reset_lock_word(mutex); -#elif defined(HAVE_GCC_ATOMIC_BUILTINS) +#elif defined(MY_ATOMIC_NOLOCK) mutex_reset_lock_word(mutex); #else os_fast_mutex_init(&(mutex->os_fast_mutex)); @@ -331,7 +331,7 @@ mutex_free( os_event_free(mutex->event); #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) -#elif defined(HAVE_GCC_ATOMIC_BUILTINS) +#elif defined(MY_ATOMIC_NOLOCK) #else os_fast_mutex_free(&(mutex->os_fast_mutex)); #endif -- 2.30.9