]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Make the pthread_rwlock implementation header-only macros [2/2]
authorOndřej Surý <ondrej@isc.org>
Fri, 14 Oct 2022 10:54:57 +0000 (12:54 +0200)
committerOndřej Surý <ondrej@isc.org>
Wed, 2 Nov 2022 09:34:10 +0000 (10:34 +0100)
While using mutrace, the phtread-rwlock based isc_rwlock implementation
would be all tracked in the rwlock.c unit losing all useful information
as all rwlocks would be traced in a single place.  Rewrite the
pthread_rwlock based implementation to be header-only macros, so we can
use mutrace to properly track the rwlock contention without heavily
patching mutrace to understand the libisc synchronization primitives.

configure.ac
lib/isc/Makefile.am
lib/isc/include/isc/condition.h
lib/isc/include/isc/mutex.h
lib/isc/include/isc/rwlock.h
lib/isc/rwlock.c

index e3cbb6a3965a4c46b09512b602eb56baa767b4b9..8cbd3e65d0cc2e6477cb4ddafeba733080ae97db 100644 (file)
@@ -622,6 +622,7 @@ AS_IF([test "$enable_pthread_rwlock" = "yes"],
                      [AC_MSG_ERROR([pthread_rwlock_rdlock requested but not found])])
        AC_DEFINE([USE_PTHREAD_RWLOCK],[1],[Define if you want to use pthread rwlock implementation])
       ])
+AM_CONDITIONAL([USE_ISC_RWLOCK], [test "$enable_pthread_rwlock" != "yes"])
 
 CRYPTO=OpenSSL
 
index e8ad720d03281fcb66080b7ab099bf2e147c40ca..4ff086b42037d42b0b752cd3e484de764dd736cc 100644 (file)
@@ -189,7 +189,6 @@ libisc_la_SOURCES =         \
        region.c                \
        resource.c              \
        result.c                \
-       rwlock.c                \
        safe.c                  \
        serial.c                \
        signal.c                \
@@ -216,6 +215,11 @@ libisc_la_SOURCES =                \
        xml.c                   \
        work.c
 
+if USE_ISC_RWLOCK
+libisc_la_SOURCES +=           \
+       rwlock.c
+endif USE_ISC_RWLOCK
+
 libisc_la_CPPFLAGS =           \
        $(AM_CPPFLAGS)          \
        $(LIBISC_CFLAGS)        \
index 09302b35a96235da7b8741d1a97389b084d8ed37..4d820ab4b8cc1e0b133bd14d67ae671ee845d747 100644 (file)
 
 ISC_LANG_BEGINDECLS
 
+/*
+ * We use macros instead of static inline functions so that the exact code
+ * location can be reported when PTHREADS_RUNTIME_CHECK() fails or when mutrace
+ * reports lock contention.
+ */
+
 #ifdef ISC_TRACK_PTHREADS_OBJECTS
 
 typedef pthread_cond_t *isc_condition_t;
index 78aa153707d2287b4b16a2c587b3455770acfec2..df249223365eb5e44caba2d92d151be4fb1bd7c0 100644 (file)
 
 ISC_LANG_BEGINDECLS
 
+/*
+ * We use macros instead of static inline functions so that the exact code
+ * location can be reported when PTHREADS_RUNTIME_CHECK() fails or when mutrace
+ * reports lock contention.
+ */
+
 #ifdef ISC_TRACK_PTHREADS_OBJECTS
 
 typedef pthread_mutex_t *isc_mutex_t;
index 0984eed943e8ec7ab351e3ee6a066d7cc3233f90..44a44a86ccc671858a3ab05f7dd71ee24037111d 100644 (file)
@@ -35,6 +35,12 @@ typedef enum {
 #if USE_PTHREAD_RWLOCK
 #include <pthread.h>
 
+/*
+ * We use macros instead of static inline functions so that the exact code
+ * location can be reported when PTHREADS_RUNTIME_CHECK() fails or when mutrace
+ * reports lock contention.
+ */
+
 #if ISC_TRACK_PTHREADS_OBJECTS
 
 typedef pthread_rwlock_t *isc_rwlock_t;
@@ -69,6 +75,89 @@ typedef pthread_rwlock_t isc__rwlock_t;
 
 #endif /* ISC_TRACK_PTHREADS_OBJECTS */
 
+#define isc__rwlock_init(rwl, read_quota, write_quote)             \
+       {                                                          \
+               int _ret = pthread_rwlock_init(rwl, NULL);         \
+               PTHREADS_RUNTIME_CHECK(pthread_rwlock_init, _ret); \
+       }
+
+#define isc__rwlock_lock(rwl, type)                                          \
+       {                                                                    \
+               int _ret;                                                    \
+               switch (type) {                                              \
+               case isc_rwlocktype_read:                                    \
+                       _ret = pthread_rwlock_rdlock(rwl);                   \
+                       PTHREADS_RUNTIME_CHECK(pthread_rwlock_rdlock, _ret); \
+                       break;                                               \
+               case isc_rwlocktype_write:                                   \
+                       _ret = pthread_rwlock_wrlock(rwl);                   \
+                       PTHREADS_RUNTIME_CHECK(pthread_rwlock_rwlock, _ret); \
+                       break;                                               \
+               default:                                                     \
+                       UNREACHABLE();                                       \
+               }                                                            \
+       }
+
+#define isc__rwlock_trylock(rwl, type)                                   \
+       ({                                                               \
+               int          _ret = 0;                                   \
+               isc_result_t _res = ISC_R_UNSET;                         \
+                                                                         \
+               switch (type) {                                          \
+               case isc_rwlocktype_read:                                \
+                       _ret = pthread_rwlock_tryrdlock(rwl);            \
+                       break;                                           \
+               case isc_rwlocktype_write:                               \
+                       _ret = pthread_rwlock_trywrlock(rwl);            \
+                       break;                                           \
+               default:                                                 \
+                       UNREACHABLE();                                   \
+               }                                                        \
+                                                                         \
+               switch (_ret) {                                          \
+               case 0:                                                  \
+                       _res = ISC_R_SUCCESS;                            \
+                       break;                                           \
+               case EBUSY:                                              \
+               case EAGAIN:                                             \
+                       _res = ISC_R_LOCKBUSY;                           \
+                       break;                                           \
+               default:                                                 \
+                       switch (type) {                                  \
+                       case isc_rwlocktype_read:                        \
+                               PTHREADS_RUNTIME_CHECK(                  \
+                                       pthread_rwlock_tryrdlock, _ret); \
+                               break;                                   \
+                       case isc_rwlocktype_write:                       \
+                               PTHREADS_RUNTIME_CHECK(                  \
+                                       pthread_rwlock_trywrlock, _ret); \
+                               break;                                   \
+                       default:                                         \
+                               UNREACHABLE();                           \
+                       }                                                \
+                       UNREACHABLE();                                   \
+               }                                                        \
+               _res;                                                    \
+       })
+
+#define isc__rwlock_unlock(rwl, type)                                \
+       {                                                            \
+               int _ret = pthread_rwlock_unlock(rwl);               \
+               PTHREADS_RUNTIME_CHECK(pthread_rwlock_rwlock, _ret); \
+       }
+
+#define isc__rwlock_tryupgrade(rwl) \
+       ({                          \
+               UNUSED(rwl);        \
+               ISC_R_LOCKBUSY;     \
+       })
+
+#define isc__rwlock_destroy(rwl)                                      \
+       {                                                             \
+               int _ret = pthread_rwlock_destroy(rwl);               \
+               PTHREADS_RUNTIME_CHECK(pthread_rwlock_destroy, _ret); \
+       }
+
 #else /* USE_PTHREAD_RWLOCK */
 
 struct isc_rwlock {
@@ -117,8 +206,6 @@ typedef struct isc_rwlock isc__rwlock_t;
 #define isc_rwlock_tryupgrade(rwl)    isc__rwlock_tryupgrade(rwl)
 #define isc_rwlock_destroy(rwl)              isc__rwlock_destroy(rwl)
 
-#endif /* USE_PTHREAD_RWLOCK */
-
 void
 isc__rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
                 unsigned int write_quota);
@@ -138,4 +225,6 @@ isc__rwlock_tryupgrade(isc__rwlock_t *rwl);
 void
 isc__rwlock_destroy(isc__rwlock_t *rwl);
 
+#endif /* USE_PTHREAD_RWLOCK */
+
 ISC_LANG_ENDDECLS
index c04bae257185de19a5428f1299d12d324692ed33..59ec0bffc22a7948f44a6acf85826d530055cf9a 100644 (file)
 #include <isc/rwlock.h>
 #include <isc/util.h>
 
-#if USE_PTHREAD_RWLOCK
-
-#include <errno.h>
-#include <pthread.h>
-
-void
-isc__rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
-                unsigned int write_quota) {
-       int ret;
-       UNUSED(read_quota);
-       UNUSED(write_quota);
-
-       ret = pthread_rwlock_init(rwl, NULL);
-       PTHREADS_RUNTIME_CHECK(pthread_rwlock_init, ret);
-}
-
-void
-isc__rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
-       int ret;
-       switch (type) {
-       case isc_rwlocktype_read:
-               ret = pthread_rwlock_rdlock(rwl);
-               PTHREADS_RUNTIME_CHECK(pthread_rwlock_rdlock, ret);
-               break;
-       case isc_rwlocktype_write:
-               ret = pthread_rwlock_wrlock(rwl);
-               PTHREADS_RUNTIME_CHECK(pthread_rwlock_rwlock, ret);
-               break;
-       default:
-               UNREACHABLE();
-       }
-}
-
-isc_result_t
-isc__rwlock_trylock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
-       int ret = 0;
-       switch (type) {
-       case isc_rwlocktype_read:
-               ret = pthread_rwlock_tryrdlock(rwl);
-               break;
-       case isc_rwlocktype_write:
-               ret = pthread_rwlock_trywrlock(rwl);
-               break;
-       default:
-               UNREACHABLE();
-       }
-
-       switch (ret) {
-       case 0:
-               return (ISC_R_SUCCESS);
-       case EBUSY:
-               return (ISC_R_LOCKBUSY);
-       case EAGAIN:
-               return (ISC_R_LOCKBUSY);
-       default:
-               break;
-       }
-
-       switch (type) {
-       case isc_rwlocktype_read:
-               PTHREADS_RUNTIME_CHECK(pthread_rwlock_tryrdlock, ret);
-               break;
-       case isc_rwlocktype_write:
-               PTHREADS_RUNTIME_CHECK(pthread_rwlock_trywrlock, ret);
-               break;
-       default:
-               break;
-       }
-       UNREACHABLE();
-}
-
-void
-isc__rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
-       int ret;
-       UNUSED(type);
-       ret = pthread_rwlock_unlock(rwl);
-       PTHREADS_RUNTIME_CHECK(pthread_rwlock_rwlock, ret);
-}
-
-isc_result_t
-isc__rwlock_tryupgrade(isc__rwlock_t *rwl) {
-       UNUSED(rwl);
-       return (ISC_R_LOCKBUSY);
-}
-
-void
-isc__rwlock_destroy(isc__rwlock_t *rwl) {
-       int ret = pthread_rwlock_destroy(rwl);
-
-       PTHREADS_RUNTIME_CHECK(pthread_rwlock_destroy, ret);
-}
-
-#else /* if USE_PTHREAD_RWLOCK */
-
 #define RWLOCK_MAGIC     ISC_MAGIC('R', 'W', 'L', 'k')
 #define VALID_RWLOCK(rwl) ISC_MAGIC_VALID(rwl, RWLOCK_MAGIC)
 
@@ -178,7 +84,7 @@ print_lock(const char *operation, isc__rwlock_t *rwl, isc_rwlocktype_t type) {
                atomic_load_acquire(&rwl->cnt_and_flag), rwl->readers_waiting,
                atomic_load_acquire(&rwl->write_granted), rwl->write_quota);
 }
-#endif                 /* ISC_RWLOCK_TRACE */
+#endif /* ISC_RWLOCK_TRACE */
 
 void
 isc__rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
@@ -595,5 +501,3 @@ isc__rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
        print_lock("postunlock", rwl, type);
 #endif /* ifdef ISC_RWLOCK_TRACE */
 }
-
-#endif /* USE_PTHREAD_RWLOCK */