diff options
-rw-r--r-- | include/my_pthread.h | 20 | ||||
-rw-r--r-- | include/mysql/psi/mysql_thread.h | 8 | ||||
-rw-r--r-- | mysys/thr_rwlock.c | 18 | ||||
-rw-r--r-- | sql/sql_base.cc | 2 |
4 files changed, 48 insertions, 0 deletions
diff --git a/include/my_pthread.h b/include/my_pthread.h index 0c89a2ed384..5cf181596ad 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -601,6 +601,8 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp); #define rw_trywrlock(A) my_rw_trywrlock((A)) #define rw_unlock(A) my_rw_unlock((A)) #define rwlock_destroy(A) my_rw_destroy((A)) +#define rw_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A)) +#define rw_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A)) #endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */ @@ -624,6 +626,8 @@ extern int rw_pr_init(rw_pr_lock_t *); #define rw_pr_trywrlock(A) pthread_rwlock_trywrlock(A) #define rw_pr_unlock(A) pthread_rwlock_unlock(A) #define rw_pr_destroy(A) pthread_rwlock_destroy(A) +#define rw_pr_lock_assert_write_owner(A) +#define rw_pr_lock_assert_not_write_owner(A) #else /* Otherwise we have to use our own implementation of read/write locks. */ #define NEED_MY_RW_LOCK 1 @@ -636,6 +640,8 @@ extern int rw_pr_init(struct st_my_rw_lock_t *); #define rw_pr_trywrlock(A) my_rw_trywrlock((A)) #define rw_pr_unlock(A) my_rw_unlock((A)) #define rw_pr_destroy(A) my_rw_destroy((A)) +#define rw_pr_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A)) +#define rw_pr_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A)) #endif /* defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) */ @@ -651,6 +657,9 @@ typedef struct st_my_rw_lock_t { int state; /* -1:writer,0:free,>0:readers */ int waiters; /* number of waiting writers */ my_bool prefer_readers; +#ifdef SAFE_MUTEX + pthread_t write_thread; +#endif } my_rw_lock_t; extern int my_rw_init(my_rw_lock_t *, my_bool *); @@ -660,6 +669,17 @@ extern int my_rw_wrlock(my_rw_lock_t *); extern int my_rw_unlock(my_rw_lock_t *); extern int my_rw_tryrdlock(my_rw_lock_t *); extern int my_rw_trywrlock(my_rw_lock_t *); +#ifdef SAFE_MUTEX +#define my_rw_lock_assert_write_owner(A) \ + DBUG_ASSERT((A)->state == -1 && pthread_equal(pthread_self(), \ + (A)->write_thread)) +#define my_rw_lock_assert_not_write_owner(A) \ + DBUG_ASSERT((A)->state >= 0 || ! pthread_equal(pthread_self(), \ + (A)->write_thread)) +#else +#define my_rw_lock_assert_write_owner(A) +#define my_rw_lock_assert_not_write_owner(A) +#endif #endif /* NEED_MY_RW_LOCK */ diff --git a/include/mysql/psi/mysql_thread.h b/include/mysql/psi/mysql_thread.h index d133f2655fb..60b4f5d6ef4 100644 --- a/include/mysql/psi/mysql_thread.h +++ b/include/mysql/psi/mysql_thread.h @@ -215,6 +215,14 @@ typedef struct st_mysql_cond mysql_cond_t; #define mysql_mutex_assert_not_owner(M) \ safe_mutex_assert_not_owner(&(M)->m_mutex) +/** Wrappers for instrumented prlock objects. */ + +#define mysql_prlock_assert_write_owner(M) \ + rw_pr_lock_assert_write_owner(&(M)->m_prlock) + +#define mysql_prlock_assert_not_write_owner(M) \ + rw_pr_lock_assert_not_write_owner(&(M)->m_prlock) + /** @def mysql_mutex_init(K, M, A) Instrumented mutex_init. diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c index 2ac4a00695e..ba5fe86f1d7 100644 --- a/mysys/thr_rwlock.c +++ b/mysys/thr_rwlock.c @@ -71,6 +71,9 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr) rwp->state = 0; rwp->waiters = 0; +#ifdef SAFE_MUTEX + rwp->write_thread = 0; +#endif /* If attribute argument is NULL use default value - prefer writers. */ rwp->prefer_readers= prefer_readers_attr ? *prefer_readers_attr : FALSE; @@ -80,6 +83,7 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr) int my_rw_destroy(my_rw_lock_t *rwp) { + DBUG_ASSERT(rwp->state == 0); pthread_mutex_destroy( &rwp->lock ); pthread_cond_destroy( &rwp->readers ); pthread_cond_destroy( &rwp->writers ); @@ -123,10 +127,15 @@ int my_rw_wrlock(my_rw_lock_t *rwp) pthread_mutex_lock(&rwp->lock); rwp->waiters++; /* another writer queued */ + my_rw_lock_assert_not_owner(rwp); + while (rwp->state) pthread_cond_wait(&rwp->writers, &rwp->lock); rwp->state = -1; rwp->waiters--; +#ifdef SAFE_MUTEX + rwp->write_thread= pthread_self(); +#endif pthread_mutex_unlock(&rwp->lock); return(0); } @@ -142,6 +151,9 @@ int my_rw_trywrlock(my_rw_lock_t *rwp) { res=0; rwp->state = -1; +#ifdef SAFE_MUTEX + rwp->write_thread= pthread_self(); +#endif } pthread_mutex_unlock(&rwp->lock); return(res); @@ -154,9 +166,15 @@ int my_rw_unlock(my_rw_lock_t *rwp) ("state: %d waiters: %d", rwp->state, rwp->waiters)); pthread_mutex_lock(&rwp->lock); + DBUG_ASSERT(rwp->state != 0); + if (rwp->state == -1) /* writer releasing */ { + my_rw_lock_assert_write_owner(rwp); rwp->state= 0; /* mark as available */ +#ifdef SAFE_MUTEX + rwp->write_thread= 0; +#endif if ( rwp->waiters ) /* writers queued */ pthread_cond_signal( &rwp->writers ); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9aea868a197..a4b66220dd1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8654,7 +8654,9 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, if (! has_lock) mysql_mutex_lock(&LOCK_open); else + { mysql_mutex_assert_owner(&LOCK_open); + } DBUG_ASSERT(remove_type == TDC_RT_REMOVE_UNUSED || thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name, |