Commit 65d118b1 authored by Konstantin Osipov's avatar Konstantin Osipov

A pre-requisite patch for the fix for Bug#52044.

Implement a few simple asserts in my_rwlock_t locks.
parent 07a4e49a
......@@ -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 */
......
......@@ -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.
......
......@@ -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 );
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment