Changeset: f1e2746a546e for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/f1e2746a546e Modified Files: gdk/gdk_system.h Branch: Jul2021 Log Message:
Work around a bug in the pthreads implementation of read-write locks. There is a potential deadlock situation in the implementation of the two "try" functions pthread_rwlock_tryrdlock and pthread_rwlock_trywrlock which was fixed in version 2.30. diffs (92 lines): diff --git a/gdk/gdk_system.h b/gdk/gdk_system.h --- a/gdk/gdk_system.h +++ b/gdk/gdk_system.h @@ -439,6 +439,8 @@ typedef struct MT_Lock { pthread_mutex_destroy(&(l)->lock); \ } while (0) +#if !defined(__GLIBC__) || __GLIBC__ > 2 || (__GLIBC__ == 2 && defined(__GLIBC_MINOR__) && __GLIBC_MINOR__ >= 30) +/* this is the normal implementation of our pthreads-based read-write lock */ typedef struct MT_RWLock { pthread_rwlock_t lock; char name[MT_NAME_LEN]; @@ -465,6 +467,79 @@ typedef struct MT_RWLock { #define MT_rwlock_wrunlock(l) pthread_rwlock_unlock(&(l)->lock) +#else +/* in glibc before 2.30, there was a deadlock condition in the tryrdlock + * and trywrlock functions, we work around that by not using the + * implementation at all + * see https://sourceware.org/bugzilla/show_bug.cgi?id=23844 for a + * discussion and comment 14 for the analysis */ +typedef struct MT_RWLock { + pthread_mutex_t lock; + ATOMIC_TYPE readers; + char name[MT_NAME_LEN]; +} MT_RWLock; + +#define MT_RWLOCK_INITIALIZER(n) \ + { .lock = PTHREAD_MUTEX_INITIALIZER, .readers = ATOMIC_VAR_INIT(0), .name = #n, } + +#define MT_rwlock_init(l, n) \ + do { \ + pthread_mutex_init(&(l)->lock, 0); \ + ATOMIC_INIT(&(l)->readers, 0); \ + strcpy_len((l)->name, (n), sizeof((l)->name)); \ + } while (0) + +#define MT_rwlock_destroy(l) \ + do { \ + pthread_mutex_destroy(&(l)->lock); \ + ATOMIC_DESTROY(&(l)->readers); \ + } while (0) + +#define MT_rwlock_rdlock(l) \ + do { \ + pthread_mutex_lock(&(l)->lock); \ + (void) ATOMIC_INC(&(l)->readers); \ + pthread_mutex_unlock(&(l)->lock); \ + } while (0) + +static inline bool +MT_rwlock_rdtry(MT_RWLock *l) +{ + if (pthread_mutex_trylock(&l->lock) != 0) + return false; + (void) ATOMIC_INC(&(l)->readers); + pthread_mutex_unlock(&l->lock); + return true; +} + +#define MT_rwlock_rdunlock(l) \ + do { \ + (void) ATOMIC_DEC(&(l)->readers); \ + } while (0) + +#define MT_rwlock_wrlock(l) \ + do { \ + pthread_mutex_lock(&(l)->lock); \ + while (ATOMIC_GET(&(l)->readers) > 0) \ + MT_sleep_ms(1); \ + } while (0) + +static inline bool +MT_rwlock_wrtry(MT_RWLock *l) +{ + if (pthread_mutex_trylock(&l->lock) != 0) + return false; + if (ATOMIC_GET(&l->readers) > 0) { + pthread_mutex_unlock(&l->lock); + return false; + } + return true; +} + +#define MT_rwlock_wrunlock(l) pthread_mutex_unlock(&(l)->lock); + +#endif + #endif #ifdef LOCK_STATS _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list