diff -ru innodb_plugin-1.0.4_orig/include/sync0rw.h innodb_plugin-1.0.4_tmp/include/sync0rw.h --- innodb_plugin-1.0.4_orig/include/sync0rw.h 2009-05-26 22:28:49.000000000 +0900 +++ innodb_plugin-1.0.4_tmp/include/sync0rw.h 2009-10-20 17:21:16.000000000 +0900 @@ -360,6 +360,16 @@ rw_lock_get_x_lock_count( /*=====================*/ const rw_lock_t* lock); /*!< in: 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); /********************************************************************//** Check if there are threads waiting for the rw-lock. @return 1 if waiters, 0 otherwise */ diff -ru innodb_plugin-1.0.4_orig/include/sync0rw.ic innodb_plugin-1.0.4_tmp/include/sync0rw.ic --- innodb_plugin-1.0.4_orig/include/sync0rw.ic 2009-05-25 19:52:29.000000000 +0900 +++ innodb_plugin-1.0.4_tmp/include/sync0rw.ic 2009-10-20 17:33:31.000000000 +0900 @@ -76,6 +76,9 @@ /*================*/ const rw_lock_t* lock) /*!< in: rw-lock */ { +#ifdef HAVE_GCC_ATOMIC_BUILTINS + __sync_synchronize(); +#endif return(lock->waiters); } @@ -113,6 +116,29 @@ #endif /* INNODB_RW_LOCKS_USE_ATOMICS */ } +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); +} + /******************************************************************//** Returns the write-status of the lock - this function made more sense with the old rw_lock implementation. @@ -123,7 +149,7 @@ /*===============*/ const rw_lock_t* lock) /*!< in: rw-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. */ @@ -145,7 +171,7 @@ /*=====================*/ const rw_lock_t* lock) /*!< in: rw-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); @@ -177,7 +203,7 @@ /*=====================*/ const 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); @@ -200,14 +226,14 @@ ulint amount) /*!< in: amount to decrement */ { #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_lint(&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); #else /* INNODB_RW_LOCKS_USE_ATOMICS */ @@ -282,6 +308,10 @@ &lock->writer_thread, 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 */ @@ -454,12 +484,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); @@ -560,11 +594,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 @@ -575,7 +613,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.4_orig/include/sync0sync.h innodb_plugin-1.0.4_tmp/include/sync0sync.h --- innodb_plugin-1.0.4_orig/include/sync0sync.h 2009-07-20 09:08:49.000000000 +0900 +++ innodb_plugin-1.0.4_tmp/include/sync0sync.h 2009-10-20 17:35:00.000000000 +0900 @@ -49,7 +49,7 @@ typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates on LONG variable */ #else -typedef byte lock_word_t; +typedef lint lock_word_t; #endif /******************************************************************//** diff -ru innodb_plugin-1.0.4_orig/include/sync0sync.ic innodb_plugin-1.0.4_tmp/include/sync0sync.ic --- innodb_plugin-1.0.4_orig/include/sync0sync.ic 2009-05-26 22:28:49.000000000 +0900 +++ innodb_plugin-1.0.4_tmp/include/sync0sync.ic 2009-10-20 17:36:29.000000000 +0900 @@ -129,6 +129,9 @@ { ut_ad(mutex); +#ifdef HAVE_GCC_ATOMIC_BUILTINS + __sync_synchronize(); +#endif return(mutex->lock_word); } @@ -145,6 +148,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.4_orig/sync/sync0arr.c innodb_plugin-1.0.4_tmp/sync/sync0arr.c --- innodb_plugin-1.0.4_orig/sync/sync0arr.c 2009-05-26 22:28:49.000000000 +0900 +++ innodb_plugin-1.0.4_tmp/sync/sync0arr.c 2009-10-20 17:37:53.000000000 +0900 @@ -796,7 +796,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); @@ -807,7 +807,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); } @@ -815,7 +815,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.4_orig/sync/sync0rw.c innodb_plugin-1.0.4_tmp/sync/sync0rw.c --- innodb_plugin-1.0.4_orig/sync/sync0rw.c 2009-05-26 22:28:49.000000000 +0900 +++ innodb_plugin-1.0.4_tmp/sync/sync0rw.c 2009-10-20 17:40:54.000000000 +0900 @@ -375,7 +375,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)); } @@ -483,7 +483,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)); } @@ -501,7 +501,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++; @@ -566,10 +566,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); @@ -628,7 +632,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));