[Commits] Rev 4346: MDEV-7026 - Occasional hang during startup on Power8 in lp:maria/5.5

Sergey Vojtovich svoj at mariadb.org
Wed Nov 12 13:49:27 EET 2014


At lp:maria/5.5

------------------------------------------------------------
revno: 4346
revision-id: svoj at mariadb.org-20141112114907-thnro6e3kg2ofdsw
parent: knielsen at knielsen-hq.org-20141112101013-t63ayylsk08ncgs3
committer: Sergey Vojtovich <svoj at mariadb.org>
branch nick: 5.5
timestamp: Wed 2014-11-12 15:49:07 +0400
message:
  MDEV-7026 - Occasional hang during startup on Power8
  
  InnoDB/XtraDB was getting stuck during server startup. In particular (but not
  limited to) while creating doublewrite buffer.
  
  It happens because mutex_exit() didn't wake up waiters of affected mutex. This
  is kind of acceptable because error monitor thread is supposed to wake up such
  waiters. But since error monitor thread hasn't been started that early, nobody
  did inform waiting threads that mutex was released.
  
  To avoid this hang we need to ensure proper StoreLoad order between lock_word
  and waiters flags. They must appear in the following order:
  
  mutex_enter()
  {
    ...
    waiters= 1;
    if (lock_word == 1)
    ...
  }
  
  mutex_exit()
  {
    ...
    lock_word= 0;
    if (waiters)
    ...
  }
  
  There was an attempt to ensure this order by "isync":::"memory", but it is just
  instruction synchronization + compiler memory barrier. It is not HW memory
  barrier.
  
  Since isync is not a memory barrier and lwsync doesn't guarantee StoreLoad
  order, the only option we have is full memory barrier.
=== modified file 'storage/innobase/include/os0sync.h'
--- a/storage/innobase/include/os0sync.h	2014-09-08 15:10:48 +0000
+++ b/storage/innobase/include/os0sync.h	2014-11-12 11:49:07 +0000
@@ -427,11 +427,7 @@ clobbered */
 # 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 os_sync __atomic_thread_fence(__ATOMIC_SEQ_CST)
 
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"GCC builtin __atomic_thread_fence() is used for memory barrier"
@@ -440,7 +436,7 @@ clobbered */
 # define HAVE_MEMORY_BARRIER
 # define os_rmb	__sync_synchronize()
 # define os_wmb	__sync_synchronize()
-# define os_isync __sync_synchronize()
+# define os_sync __sync_synchronize()
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"GCC builtin __sync_synchronize() is used for memory barrier"
 
@@ -449,7 +445,7 @@ clobbered */
 # include <mbarrier.h>
 # define os_rmb	__machine_r_barrier()
 # define os_wmb	__machine_w_barrier()
-# define os_isync os_rmb; os_wmb
+# define os_sync __machine_rw_barrier()
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"Soralis memory ordering functions are used for memory barrier"
 
@@ -458,7 +454,7 @@ clobbered */
 # include <intrin.h>
 # define os_rmb	_mm_lfence()
 # define os_wmb	_mm_sfence()
-# define os_isync os_rmb; os_wmb
+# define os_sync _mm_mfence()
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"_mm_lfence() and _mm_sfence() are used for memory barrier"
 
@@ -468,7 +464,7 @@ clobbered */
 #else
 # define os_rmb do { } while(0)
 # define os_wmb do { } while(0)
-# define os_isync do { } while(0)
+# define os_sync do { } while(0)
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"Memory barrier is not used"
 #endif

=== modified file 'storage/innobase/include/sync0sync.ic'
--- a/storage/innobase/include/sync0sync.ic	2014-08-29 12:02:46 +0000
+++ b/storage/innobase/include/sync0sync.ic	2014-11-12 11:49:07 +0000
@@ -145,7 +145,6 @@ mutex_get_waiters(
 
 	ptr = &(mutex->waiters);
 
-        os_rmb;
 	return(*ptr);		/* Here we assume that the read of a single
 				word from memory is atomic */
 }
@@ -180,7 +179,7 @@ mutex_exit_func(
 	to wake up possible hanging threads if
 	they are missed in mutex_signal_object. */
 
-        os_isync;
+        os_sync;
 	if (mutex_get_waiters(mutex) != 0) {
 
 		mutex_signal_object(mutex);

=== modified file 'storage/innobase/sync/sync0sync.c'
--- a/storage/innobase/sync/sync0sync.c	2014-11-03 13:43:44 +0000
+++ b/storage/innobase/sync/sync0sync.c	2014-11-12 11:49:07 +0000
@@ -474,10 +474,9 @@ mutex_set_waiters(
 
 	ptr = &(mutex->waiters);
 
-        os_wmb;
-
 	*ptr = n;		/* Here we assume that the write of a single
 				word in memory is atomic */
+        os_sync;
 }
 
 /******************************************************************//**

=== modified file 'storage/xtradb/include/os0sync.h'
--- a/storage/xtradb/include/os0sync.h	2014-09-08 15:10:48 +0000
+++ b/storage/xtradb/include/os0sync.h	2014-11-12 11:49:07 +0000
@@ -447,11 +447,7 @@ clobbered */
 # 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 os_sync __atomic_thread_fence(__ATOMIC_SEQ_CST)
 
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"GCC builtin __atomic_thread_fence() is used for memory barrier"
@@ -460,7 +456,7 @@ clobbered */
 # define HAVE_MEMORY_BARRIER
 # define os_rmb	__sync_synchronize()
 # define os_wmb	__sync_synchronize()
-# define os_isync __sync_synchronize()
+# define os_sync __sync_synchronize()
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"GCC builtin __sync_synchronize() is used for memory barrier"
 
@@ -469,7 +465,7 @@ clobbered */
 # include <mbarrier.h>
 # define os_rmb	__machine_r_barrier()
 # define os_wmb	__machine_w_barrier()
-# define os_isync os_rmb; os_wmb
+# define os_sync __machine_rw_barrier()
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"Soralis memory ordering functions are used for memory barrier"
 
@@ -478,7 +474,7 @@ clobbered */
 # include <intrin.h>
 # define os_rmb	_mm_lfence()
 # define os_wmb	_mm_sfence()
-# define os_isync os_rmb; os_wmb
+# define os_sync _mm_mfence()
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"_mm_lfence() and _mm_sfence() are used for memory barrier"
 
@@ -488,7 +484,7 @@ clobbered */
 #else
 # define os_rmb do { } while(0)
 # define os_wmb do { } while(0)
-# define os_isync do { } while(0)
+# define os_sync do { } while(0)
 # define IB_MEMORY_BARRIER_STARTUP_MSG \
 	"Memory barrier is not used"
 #endif

=== modified file 'storage/xtradb/include/sync0sync.ic'
--- a/storage/xtradb/include/sync0sync.ic	2014-08-29 12:02:46 +0000
+++ b/storage/xtradb/include/sync0sync.ic	2014-11-12 11:49:07 +0000
@@ -145,7 +145,6 @@ mutex_get_waiters(
 
 	ptr = &(mutex->waiters);
 
-        os_rmb;
 	return(*ptr);		/* Here we assume that the read of a single
 				word from memory is atomic */
 }
@@ -180,7 +179,7 @@ mutex_exit_func(
 	to wake up possible hanging threads if
 	they are missed in mutex_signal_object. */
 
-        os_isync;
+        os_sync;
 	if (mutex_get_waiters(mutex) != 0) {
 
 		mutex_signal_object(mutex);

=== modified file 'storage/xtradb/sync/sync0sync.c'
--- a/storage/xtradb/sync/sync0sync.c	2014-11-03 13:43:44 +0000
+++ b/storage/xtradb/sync/sync0sync.c	2014-11-12 11:49:07 +0000
@@ -467,26 +467,15 @@ mutex_set_waiters(
 	mutex_t*	mutex,	/*!< in: mutex */
 	ulint		n)	/*!< in: value to set */
 {
-#ifdef INNODB_RW_LOCKS_USE_ATOMICS
-	ut_ad(mutex);
-
-	if (n) {
-		os_compare_and_swap_ulint(&mutex->waiters, 0, 1);
-	} else {
-		os_compare_and_swap_ulint(&mutex->waiters, 1, 0);
-	}
-#else
 	volatile ulint*	ptr;		/* declared volatile to ensure that
 					the value is stored to memory */
 	ut_ad(mutex);
 
 	ptr = &(mutex->waiters);
 
-        os_wmb;
-
 	*ptr = n;		/* Here we assume that the write of a single
 				word in memory is atomic */
-#endif
+        os_sync;
 }
 
 /******************************************************************//**



More information about the commits mailing list