summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_pthread.h20
-rw-r--r--include/mysql/psi/mysql_thread.h8
-rw-r--r--mysys/thr_rwlock.c18
-rw-r--r--sql/sql_base.cc2
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,