diff options
author | Dmitry Lenev <dlenev@mysql.com> | 2010-02-28 07:35:09 +0300 |
---|---|---|
committer | Dmitry Lenev <dlenev@mysql.com> | 2010-02-28 07:35:09 +0300 |
commit | 6b5c4a9ef61eff4768c6fdf04857ae8a1b219a6c (patch) | |
tree | 72819bde0c313c8ef3b67a20ff9ac4fe00833093 /include/my_pthread.h | |
parent | 093106f552ae890a0c6b4b183899a5d0affa1629 (diff) | |
download | mariadb-git-6b5c4a9ef61eff4768c6fdf04857ae8a1b219a6c.tar.gz |
Fix for bug #51105 "MDL deadlock in rqg_mdl_stability test
on Windows".
On platforms where read-write lock implementation does not
prefer readers by default (Windows, Solaris) server might
have deadlocked while detecting MDL deadlock.
MDL deadlock detector relies on the fact that read-write
locks which are used in its implementation prefer readers
(see new comment for MDL_lock::m_rwlock for details).
So far MDL code assumed that default implementation of
read/write locks for the system has this property.
Indeed, this turned out ot be wrong, for example, for
Windows or Solaris. Thus MDL deadlock detector might have
deadlocked on these systems.
This fix simply adds portable implementation of read/write
lock which prefer readers and changes MDL code to use this
new type of synchronization primitive.
No test case is added as existing rqg_mdl_stability test can
serve as one.
config.h.cmake:
Check for presence of pthread_rwlockattr_setkind_np to be
able to determine if system natively supports read-write
locks for which we can specify if readers or writers should
be preferred.
configure.cmake:
Check for presence of pthread_rwlockattr_setkind_np to be
able to determine if system natively supports read-write
locks for which we can specify if readers or writers should
be preferred.
configure.in:
Check for presence of pthread_rwlockattr_setkind_np to be
able to determine if system natively supports read-write
locks for which we can specify if readers or writers should
be preferred.
include/my_pthread.h:
Added support for portable read-write locks which prefer
readers.
To do so extended existing my_rw_lock_t implementation to
support selection of whom to prefer depending on a flag.
mysys/thr_rwlock.c:
Extended existing my_rw_lock_t implementation to support
selection of whom to prefer depending on a flag.
Added rw_pr_init() function implementing initialization of
read-write locks preferring readers.
sql/mdl.cc:
Use portable read-write locks which prefer readers instead of
relying on that system implementation of read-write locks has
this property (this was true for Linux/NPTL but was false,
for example, for Windows and Solaris).
Added comment explaining why preferring readers is important
for MDL deadlock detector (thanks to Serg for example!).
sql/mdl.h:
Use portable read-write locks which prefer readers instead of
relying on that system implementation of read-write locks has
this property (this was true for Linux/NPTL but was false,
for example, for Windows and Solaris).
Diffstat (limited to 'include/my_pthread.h')
-rw-r--r-- | include/my_pthread.h | 70 |
1 files changed, 58 insertions, 12 deletions
diff --git a/include/my_pthread.h b/include/my_pthread.h index 0e421f678b0..0b55c70b0fa 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -600,30 +600,76 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp); #define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0) #else /* Use our own version of read/write locks */ -typedef struct _my_rw_lock_t { - pthread_mutex_t lock; /* lock for structure */ - pthread_cond_t readers; /* waiting readers */ - pthread_cond_t writers; /* waiting writers */ - int state; /* -1:writer,0:free,>0:readers */ - int waiters; /* number of waiting writers */ -} my_rw_lock_t; - +#define NEED_MY_RW_LOCK 1 #define rw_lock_t my_rw_lock_t +#define my_rwlock_init(A,B) my_rw_init((A), 0) #define rw_rdlock(A) my_rw_rdlock((A)) #define rw_wrlock(A) my_rw_wrlock((A)) #define rw_tryrdlock(A) my_rw_tryrdlock((A)) #define rw_trywrlock(A) my_rw_trywrlock((A)) #define rw_unlock(A) my_rw_unlock((A)) -#define rwlock_destroy(A) my_rwlock_destroy((A)) +#define rwlock_destroy(A) my_rw_destroy((A)) +#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */ -extern int my_rwlock_init(my_rw_lock_t *, void *); -extern int my_rwlock_destroy(my_rw_lock_t *); + +/* + Portable read-write locks which prefer readers. + + Required by some algorithms in order to provide correctness. +*/ + +#if defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) +/* + On systems which have a way to specify that readers should + be preferred through attribute mechanism (e.g. Linux) we use + system implementation of read/write locks. +*/ +#define rw_pr_lock_t pthread_rwlock_t +extern int rw_pr_init(rw_pr_lock_t *); +#define rw_pr_rdlock(A) pthread_rwlock_rdlock(A) +#define rw_pr_wrlock(A) pthread_rwlock_wrlock(A) +#define rw_pr_tryrdlock(A) pthread_rwlock_tryrdlock(A) +#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) +#else +/* Otherwise we have to use our own implementation of read/write locks. */ +#define NEED_MY_RW_LOCK 1 +struct st_my_rw_lock_t; +#define rw_pr_lock_t my_rw_lock_t +extern int rw_pr_init(struct st_my_rw_lock_t *); +#define rw_pr_rdlock(A) my_rw_rdlock((A)) +#define rw_pr_wrlock(A) my_rw_wrlock((A)) +#define rw_pr_tryrdlock(A) my_rw_tryrdlock((A)) +#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)) +#endif /* defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) */ + + +#ifdef NEED_MY_RW_LOCK +/* + On systems which don't support native read/write locks, or don't support + read/write locks which prefer readers we have to use own implementation. +*/ +typedef struct st_my_rw_lock_t { + pthread_mutex_t lock; /* lock for structure */ + pthread_cond_t readers; /* waiting readers */ + pthread_cond_t writers; /* waiting writers */ + int state; /* -1:writer,0:free,>0:readers */ + int waiters; /* number of waiting writers */ + my_bool prefer_readers; +} my_rw_lock_t; + +extern int my_rw_init(my_rw_lock_t *, my_bool *); +extern int my_rw_destroy(my_rw_lock_t *); extern int my_rw_rdlock(my_rw_lock_t *); 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 *); -#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */ +#endif /* NEED_MY_RW_LOCK */ + #define GETHOSTBYADDR_BUFF_SIZE 2048 |