Commit 7e065ee9 authored by Mikael Ronstrom's avatar Mikael Ronstrom

Merge port of Google SMP patch to Solaris

parent 84e311c8
......@@ -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",
......
......@@ -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"
......
......@@ -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 */
......@@ -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;
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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);
......
......@@ -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
}
......
......@@ -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
......
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