[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
region.c \
resource.c \
result.c \
- rwlock.c \
safe.c \
serial.c \
signal.c \
xml.c \
work.c
+if USE_ISC_RWLOCK
+libisc_la_SOURCES += \
+ rwlock.c
+endif USE_ISC_RWLOCK
+
libisc_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(LIBISC_CFLAGS) \
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;
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;
#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;
#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 {
#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);
void
isc__rwlock_destroy(isc__rwlock_t *rwl);
+#endif /* USE_PTHREAD_RWLOCK */
+
ISC_LANG_ENDDECLS
#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)
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,
print_lock("postunlock", rwl, type);
#endif /* ifdef ISC_RWLOCK_TRACE */
}
-
-#endif /* USE_PTHREAD_RWLOCK */