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

Reply via email to