[Commits] Rev 4304: MDEV-6483 - Deadlock around rw_lock_debug_mutex on PPC64 in lp:maria/10.0

Sergey Vojtovich svoj at mariadb.org
Thu Jul 24 17:12:43 EEST 2014


At lp:maria/10.0

------------------------------------------------------------
revno: 4304
revision-id: svoj at mariadb.org-20140724141232-l1ynr5pjyjqz1c63
parent: svoj at mariadb.org-20140723085526-i0v39faneybs7m4p
committer: Sergey Vojtovich <svoj at mariadb.org>
branch nick: 10.0
timestamp: Thu 2014-07-24 18:12:32 +0400
message:
  MDEV-6483 - Deadlock around rw_lock_debug_mutex on PPC64
  
  This problem affects only debug builds on PPC64.
  
  There are at least two race conditions around
  rw_lock_debug_mutex_enter and rw_lock_debug_mutex_exit:
  
  - rw_lock_debug_waiters was loaded/stored without setting
    appropriate locks/memory barriers.
  - there is a gap between calls to os_event_reset() and
    os_event_wait() and in such case we're supposed to pass
    return value of the former to the latter.
  
  Fixed by replacing self-cooked spinlocks with system mutexes.
  These days system mutexes offer much better performance. OTOH
  performance is not that critical for debug builds.
=== modified file 'storage/innobase/include/sync0rw.h'
--- a/storage/innobase/include/sync0rw.h	2014-05-06 07:57:39 +0000
+++ b/storage/innobase/include/sync0rw.h	2014-07-24 14:12:32 +0000
@@ -108,14 +108,8 @@ extern ib_mutex_t		rw_lock_list_mutex;
 #ifdef UNIV_SYNC_DEBUG
 /* The global mutex which protects debug info lists of all rw-locks.
 To modify the debug info list of an rw-lock, this mutex has to be
-
 acquired in addition to the mutex protecting the lock. */
-extern ib_mutex_t		rw_lock_debug_mutex;
-extern os_event_t	rw_lock_debug_event;	/*!< If deadlock detection does
-					not get immediately the mutex it
-					may wait for this event */
-extern ibool		rw_lock_debug_waiters;	/*!< This is set to TRUE, if
-					there may be waiters for the event */
+extern os_fast_mutex_t		rw_lock_debug_mutex;
 #endif /* UNIV_SYNC_DEBUG */
 
 /** Counters for RW locks. */

=== modified file 'storage/innobase/sync/sync0rw.cc'
--- a/storage/innobase/sync/sync0rw.cc	2014-02-26 18:36:33 +0000
+++ b/storage/innobase/sync/sync0rw.cc	2014-07-24 14:12:32 +0000
@@ -151,18 +151,12 @@ UNIV_INTERN mysql_pfs_key_t	rw_lock_mute
 To modify the debug info list of an rw-lock, this mutex has to be
 acquired in addition to the mutex protecting the lock. */
 
-UNIV_INTERN ib_mutex_t		rw_lock_debug_mutex;
+UNIV_INTERN os_fast_mutex_t	rw_lock_debug_mutex;
 
 # ifdef UNIV_PFS_MUTEX
 UNIV_INTERN mysql_pfs_key_t	rw_lock_debug_mutex_key;
 # endif
 
-/* If deadlock detection does not get immediately the mutex,
-it may wait for this event */
-UNIV_INTERN os_event_t		rw_lock_debug_event;
-/* This is set to TRUE, if there may be waiters for the event */
-UNIV_INTERN ibool		rw_lock_debug_waiters;
-
 /******************************************************************//**
 Creates a debug info struct. */
 static
@@ -690,22 +684,7 @@ void
 rw_lock_debug_mutex_enter(void)
 /*===========================*/
 {
-loop:
-	if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
-		return;
-	}
-
-	os_event_reset(rw_lock_debug_event);
-
-	rw_lock_debug_waiters = TRUE;
-
-	if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
-		return;
-	}
-
-	os_event_wait(rw_lock_debug_event);
-
-	goto loop;
+	os_fast_mutex_lock(&rw_lock_debug_mutex);
 }
 
 /******************************************************************//**
@@ -715,12 +694,7 @@ void
 rw_lock_debug_mutex_exit(void)
 /*==========================*/
 {
-	mutex_exit(&rw_lock_debug_mutex);
-
-	if (rw_lock_debug_waiters) {
-		rw_lock_debug_waiters = FALSE;
-		os_event_set(rw_lock_debug_event);
-	}
+	os_fast_mutex_unlock(&rw_lock_debug_mutex);
 }
 
 /******************************************************************//**

=== modified file 'storage/innobase/sync/sync0sync.cc'
--- a/storage/innobase/sync/sync0sync.cc	2014-05-06 07:57:39 +0000
+++ b/storage/innobase/sync/sync0sync.cc	2014-07-24 14:12:32 +0000
@@ -1472,11 +1472,7 @@ sync_init(void)
 		     SYNC_NO_ORDER_CHECK);
 
 #ifdef UNIV_SYNC_DEBUG
-	mutex_create(rw_lock_debug_mutex_key, &rw_lock_debug_mutex,
-		     SYNC_NO_ORDER_CHECK);
-
-	rw_lock_debug_event = os_event_create();
-	rw_lock_debug_waiters = FALSE;
+	os_fast_mutex_init(rw_lock_debug_mutex_key, &rw_lock_debug_mutex);
 #endif /* UNIV_SYNC_DEBUG */
 }
 
@@ -1544,6 +1540,7 @@ sync_close(void)
 	sync_order_checks_on = FALSE;
 
 	sync_thread_level_arrays_free();
+	os_fast_mutex_free(&rw_lock_debug_mutex);
 #endif /* UNIV_SYNC_DEBUG */
 
 	sync_initialized = FALSE;

=== modified file 'storage/xtradb/include/sync0rw.h'
--- a/storage/xtradb/include/sync0rw.h	2014-05-06 08:21:34 +0000
+++ b/storage/xtradb/include/sync0rw.h	2014-07-24 14:12:32 +0000
@@ -109,14 +109,8 @@ extern ib_mutex_t		rw_lock_list_mutex;
 #ifdef UNIV_SYNC_DEBUG
 /* The global mutex which protects debug info lists of all rw-locks.
 To modify the debug info list of an rw-lock, this mutex has to be
-
 acquired in addition to the mutex protecting the lock. */
-extern ib_mutex_t		rw_lock_debug_mutex;
-extern os_event_t	rw_lock_debug_event;	/*!< If deadlock detection does
-					not get immediately the mutex it
-					may wait for this event */
-extern ibool		rw_lock_debug_waiters;	/*!< This is set to TRUE, if
-					there may be waiters for the event */
+extern os_fast_mutex_t		rw_lock_debug_mutex;
 #endif /* UNIV_SYNC_DEBUG */
 
 /** Counters for RW locks. */

=== modified file 'storage/xtradb/sync/sync0rw.cc'
--- a/storage/xtradb/sync/sync0rw.cc	2014-02-26 18:21:23 +0000
+++ b/storage/xtradb/sync/sync0rw.cc	2014-07-24 14:12:32 +0000
@@ -151,18 +151,12 @@ UNIV_INTERN mysql_pfs_key_t	rw_lock_mute
 To modify the debug info list of an rw-lock, this mutex has to be
 acquired in addition to the mutex protecting the lock. */
 
-UNIV_INTERN ib_mutex_t		rw_lock_debug_mutex;
+UNIV_INTERN os_fast_mutex_t	rw_lock_debug_mutex;
 
 # ifdef UNIV_PFS_MUTEX
 UNIV_INTERN mysql_pfs_key_t	rw_lock_debug_mutex_key;
 # endif
 
-/* If deadlock detection does not get immediately the mutex,
-it may wait for this event */
-UNIV_INTERN os_event_t		rw_lock_debug_event;
-/* This is set to TRUE, if there may be waiters for the event */
-UNIV_INTERN ibool		rw_lock_debug_waiters;
-
 /******************************************************************//**
 Creates a debug info struct. */
 static
@@ -920,22 +914,7 @@ void
 rw_lock_debug_mutex_enter(void)
 /*===========================*/
 {
-loop:
-	if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
-		return;
-	}
-
-	os_event_reset(rw_lock_debug_event);
-
-	rw_lock_debug_waiters = TRUE;
-
-	if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
-		return;
-	}
-
-	os_event_wait(rw_lock_debug_event);
-
-	goto loop;
+	os_fast_mutex_lock(&rw_lock_debug_mutex);
 }
 
 /******************************************************************//**
@@ -945,12 +924,7 @@ void
 rw_lock_debug_mutex_exit(void)
 /*==========================*/
 {
-	mutex_exit(&rw_lock_debug_mutex);
-
-	if (rw_lock_debug_waiters) {
-		rw_lock_debug_waiters = FALSE;
-		os_event_set(rw_lock_debug_event);
-	}
+	os_fast_mutex_unlock(&rw_lock_debug_mutex);
 }
 
 /******************************************************************//**

=== modified file 'storage/xtradb/sync/sync0sync.cc'
--- a/storage/xtradb/sync/sync0sync.cc	2014-05-07 15:33:33 +0000
+++ b/storage/xtradb/sync/sync0sync.cc	2014-07-24 14:12:32 +0000
@@ -1598,11 +1598,7 @@ sync_init(void)
 		     SYNC_NO_ORDER_CHECK);
 
 #ifdef UNIV_SYNC_DEBUG
-	mutex_create(rw_lock_debug_mutex_key, &rw_lock_debug_mutex,
-		     SYNC_NO_ORDER_CHECK);
-
-	rw_lock_debug_event = os_event_create();
-	rw_lock_debug_waiters = FALSE;
+	os_fast_mutex_init(rw_lock_debug_mutex_key, &rw_lock_debug_mutex);
 #endif /* UNIV_SYNC_DEBUG */
 }
 
@@ -1676,6 +1672,7 @@ sync_close(void)
 	sync_order_checks_on = FALSE;
 
 	sync_thread_level_arrays_free();
+	os_fast_mutex_free(&rw_lock_debug_mutex);
 #endif /* UNIV_SYNC_DEBUG */
 
 	sync_initialized = FALSE;



More information about the commits mailing list