diff -ru innodb_plugin-1.0.3_orig/include/sync0rw.h innodb_plugin-1.0.3_tmp/include/sync0rw.h --- innodb_plugin-1.0.3_orig/include/sync0rw.h 2009-02-17 16:56:33.000000000 +0900 +++ innodb_plugin-1.0.3_tmp/include/sync0rw.h 2009-10-20 17:08:47.000000000 +0900 @@ -358,6 +358,16 @@ /************************************************************************ Accessor functions for rw lock. */ UNIV_INLINE +volatile lint +rw_lock_get_lock_word( +/*==================*/ + rw_lock_t* lock); +UNIV_INLINE +volatile ibool +rw_lock_get_recursive( +/*==================*/ + rw_lock_t* lock); +UNIV_INLINE ulint rw_lock_get_waiters( /*================*/ diff -ru innodb_plugin-1.0.3_orig/include/sync0rw.ic innodb_plugin-1.0.3_tmp/include/sync0rw.ic --- innodb_plugin-1.0.3_orig/include/sync0rw.ic 2009-02-17 21:59:54.000000000 +0900 +++ innodb_plugin-1.0.3_tmp/include/sync0rw.ic 2009-10-20 17:08:47.000000000 +0900 @@ -69,12 +69,37 @@ /************************************************************************ Accessor functions for rw lock. */ UNIV_INLINE +volatile lint +rw_lock_get_lock_word( +/*==================*/ + rw_lock_t* lock) +{ +#ifdef HAVE_GCC_ATOMIC_BUILTINS + __sync_synchronize(); +#endif + return(lock->lock_word); +} +UNIV_INLINE +volatile ibool +rw_lock_get_recursive( +/*==================*/ + rw_lock_t* lock) +{ +#ifdef HAVE_GCC_ATOMIC_BUILTINS + __sync_synchronize(); +#endif + return(lock->recursive); +} +UNIV_INLINE ulint rw_lock_get_waiters( /*================*/ /* out: 1 if waiters, 0 otherwise */ rw_lock_t* lock) /* in: rw-lock */ { +#ifdef HAVE_GCC_ATOMIC_BUILTINS + __sync_synchronize(); +#endif return(lock->waiters); } @@ -121,7 +146,7 @@ /*===============*/ rw_lock_t* lock) { - lint lock_word = lock->lock_word; + lint lock_word = rw_lock_get_lock_word(lock); if(lock_word > 0) { /* return NOT_LOCKED in s-lock state, like the writer member of the old lock implementation. */ @@ -142,7 +167,7 @@ /*=====================*/ rw_lock_t* lock) { - lint lock_word = lock->lock_word; + lint lock_word = rw_lock_get_lock_word(lock); if(lock_word > 0) { /* s-locked, no x-waiters */ return(X_LOCK_DECR - lock_word); @@ -174,7 +199,7 @@ /* out: value of writer_count */ rw_lock_t* lock) /* in: rw-lock */ { - lint lock_copy = lock->lock_word; + lint lock_copy = rw_lock_get_lock_word(lock); /* If there is a reader, lock_word is not divisible by X_LOCK_DECR */ if(lock_copy > 0 || (-lock_copy) % X_LOCK_DECR != 0) { return(0); @@ -199,14 +224,14 @@ #ifdef INNODB_RW_LOCKS_USE_ATOMICS - lint local_lock_word = lock->lock_word; + lint local_lock_word = rw_lock_get_lock_word(lock); while (local_lock_word > 0) { if(os_compare_and_swap(&(lock->lock_word), local_lock_word, local_lock_word - amount)) { return(TRUE); } - local_lock_word = lock->lock_word; + local_lock_word = rw_lock_get_lock_word(lock); } return(FALSE); @@ -291,6 +316,10 @@ local_thread, curr_thread); ut_a(success); lock->recursive = recursive; +#ifdef HAVE_GCC_ATOMIC_BUILTINS + //__sync_synchronize(); + asm volatile ("isync"); +#endif #else /* INNODB_RW_LOCKS_USE_ATOMICS */ @@ -463,12 +492,16 @@ if (success) { rw_lock_set_writer_id_and_recursion_flag(lock, TRUE); - } else if (lock->recursive + } else if (rw_lock_get_recursive(lock) && os_thread_eq(lock->writer_thread, curr_thread)) { /* Relock: this lock_word modification is safe since no other threads can modify (lock, unlock, or reserve) lock_word while there is an exclusive writer and this is the writer thread. */ lock->lock_word -= X_LOCK_DECR; +#ifdef HAVE_GCC_ATOMIC_BUILTINS + //__sync_synchronize(); + asm volatile ("isync"); +#endif ut_ad(((-lock->lock_word) % X_LOCK_DECR) == 0); @@ -571,11 +604,15 @@ lock->writer_thread is now stale. Note that since we still hold the x-lock we can safely read the lock_word. */ - if (lock->lock_word == 0) { + if (rw_lock_get_lock_word(lock) == 0) { /* Last caller in a possible recursive chain. */ lock->recursive = FALSE; UNIV_MEM_INVALID(&lock->writer_thread, sizeof lock->writer_thread); +#ifdef HAVE_GCC_ATOMIC_BUILTINS + //__sync_synchronize(); + asm volatile ("isync"); +#endif } #ifdef UNIV_SYNC_DEBUG @@ -586,7 +623,7 @@ /* Lock is now free. May have to signal read/write waiters. We do not need to signal wait_ex waiters, since they cannot exist when there is a writer. */ - if (lock->waiters) { + if (rw_lock_get_waiters(lock)) { rw_lock_reset_waiter_flag(lock); os_event_set(lock->event); sync_array_object_signalled(sync_primary_wait_array); diff -ru innodb_plugin-1.0.3_orig/include/sync0sync.h innodb_plugin-1.0.3_tmp/include/sync0sync.h --- innodb_plugin-1.0.3_orig/include/sync0sync.h 2009-02-17 16:56:33.000000000 +0900 +++ innodb_plugin-1.0.3_tmp/include/sync0sync.h 2009-10-20 17:08:47.000000000 +0900 @@ -260,7 +260,7 @@ NOT to be used outside this module except in debugging! Gets the value of the lock word. */ UNIV_INLINE -byte +lint mutex_get_lock_word( /*================*/ const mutex_t* mutex); /* in: mutex */ @@ -486,7 +486,7 @@ struct mutex_struct { os_event_t event; /* Used by sync0arr.c for the wait queue */ - byte lock_word; /* This byte is the target of the atomic + lint lock_word; /* This byte is the target of the atomic 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) diff -ru innodb_plugin-1.0.3_orig/include/sync0sync.ic innodb_plugin-1.0.3_tmp/include/sync0sync.ic --- innodb_plugin-1.0.3_orig/include/sync0sync.ic 2009-02-17 16:56:33.000000000 +0900 +++ innodb_plugin-1.0.3_tmp/include/sync0sync.ic 2009-10-20 17:08:47.000000000 +0900 @@ -164,15 +164,18 @@ /********************************************************************** Gets the value of the lock word. */ UNIV_INLINE -byte +lint mutex_get_lock_word( /*================*/ const mutex_t* mutex) /* in: mutex */ { - const volatile byte* ptr; /* declared volatile to ensure that + const volatile lint* ptr; /* declared volatile to ensure that lock_word is loaded from memory */ ut_ad(mutex); +#ifdef HAVE_GCC_ATOMIC_BUILTINS + __sync_synchronize(); +#endif ptr = &(mutex->lock_word); return(*ptr); @@ -191,6 +194,9 @@ the value is read from memory */ ut_ad(mutex); +#ifdef HAVE_GCC_ATOMIC_BUILTINS + __sync_synchronize(); +#endif ptr = &(mutex->waiters); return(*ptr); /* Here we assume that the read of a single diff -ru innodb_plugin-1.0.3_orig/sync/sync0arr.c innodb_plugin-1.0.3_tmp/sync/sync0arr.c --- innodb_plugin-1.0.3_orig/sync/sync0arr.c 2009-02-17 21:26:53.000000000 +0900 +++ innodb_plugin-1.0.3_tmp/sync/sync0arr.c 2009-10-20 17:08:47.000000000 +0900 @@ -792,7 +792,7 @@ lock = cell->wait_object; - if (lock->lock_word > 0) { + if (rw_lock_get_lock_word(lock) > 0) { /* Either unlocked or only read locked. */ return(TRUE); @@ -803,7 +803,7 @@ lock = cell->wait_object; /* lock_word == 0 means all readers have left */ - if (lock->lock_word == 0) { + if (rw_lock_get_lock_word(lock) == 0) { return(TRUE); } @@ -811,7 +811,7 @@ lock = cell->wait_object; /* lock_word > 0 means no writer or reserved writer */ - if (lock->lock_word > 0) { + if (rw_lock_get_lock_word(lock) > 0) { return(TRUE); } diff -ru innodb_plugin-1.0.3_orig/sync/sync0rw.c innodb_plugin-1.0.3_tmp/sync/sync0rw.c --- innodb_plugin-1.0.3_orig/sync/sync0rw.c 2009-02-17 21:26:53.000000000 +0900 +++ innodb_plugin-1.0.3_tmp/sync/sync0rw.c 2009-10-20 17:08:47.000000000 +0900 @@ -371,7 +371,7 @@ lock_loop: /* Spin waiting for the writer field to become free */ - while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) { + while (i < SYNC_SPIN_ROUNDS && rw_lock_get_lock_word(lock) <= 0) { if (srv_spin_wait_delay) { ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); } @@ -479,7 +479,7 @@ ut_ad(lock->lock_word <= 0); - while (lock->lock_word < 0) { + while (rw_lock_get_lock_word(lock) < 0) { if (srv_spin_wait_delay) { ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); } @@ -497,7 +497,7 @@ file_name, line, &index); /* Check lock_word to ensure wake-up isn't missed.*/ - if(lock->lock_word < 0) { + if(rw_lock_get_lock_word(lock) < 0) { /* these stats may not be accurate */ lock->count_os_wait++; @@ -563,10 +563,14 @@ } else { /* Decrement failed: relock or failed lock */ - if (!pass && lock->recursive + if (!pass && rw_lock_get_recursive(lock) && os_thread_eq(lock->writer_thread, curr_thread)) { /* Relock */ lock->lock_word -= X_LOCK_DECR; +#ifdef HAVE_GCC_ATOMIC_BUILTINS + //__sync_synchronize(); + asm volatile ("isync"); +#endif } else { /* Another thread locked before us */ return(FALSE); @@ -625,7 +629,7 @@ /* Spin waiting for the lock_word to become free */ while (i < SYNC_SPIN_ROUNDS - && lock->lock_word <= 0) { + && rw_lock_get_lock_word(lock) <= 0) { if (srv_spin_wait_delay) { ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));