mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch 'ondrej-rework-pthread-rwlock-3' into 'main'
Make the pthread_rwlock implementation header-only macros [3/3] See merge request isc-projects/bind9!6909
This commit is contained in:
commit
0e04156f4b
6 changed files with 148 additions and 150 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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) \
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@
|
|||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -46,13 +52,13 @@ typedef pthread_rwlock_t isc__rwlock_t;
|
|||
isc__rwlock_init(*rwl, rq, wq); \
|
||||
}
|
||||
#define isc_rwlock_lock(rwl, type) isc__rwlock_lock(*rwl, type)
|
||||
#define isc_rwlock_trylock(rwl, type) isc___rwlock_trylock(*rwl, type)
|
||||
#define isc_rwlock_trylock(rwl, type) isc__rwlock_trylock(*rwl, type)
|
||||
#define isc_rwlock_unlock(rwl, type) isc__rwlock_unlock(*rwl, type)
|
||||
#define isc_rwlock_tryupgrade(rwl) isc___rwlock_tryupgrade(*rwl)
|
||||
#define isc_rwlock_destroy(rwl) \
|
||||
{ \
|
||||
isc___rwlock_destroy(*rwl); \
|
||||
free(*rwl); \
|
||||
#define isc_rwlock_tryupgrade(rwl) isc__rwlock_tryupgrade(*rwl)
|
||||
#define isc_rwlock_destroy(rwl) \
|
||||
{ \
|
||||
isc__rwlock_destroy(*rwl); \
|
||||
free(*rwl); \
|
||||
}
|
||||
|
||||
#else /* ISC_TRACK_PTHREADS_OBJECTS */
|
||||
|
|
@ -62,13 +68,96 @@ typedef pthread_rwlock_t isc__rwlock_t;
|
|||
|
||||
#define isc_rwlock_init(rwl, rq, wq) isc__rwlock_init(rwl, rq, wq)
|
||||
#define isc_rwlock_lock(rwl, type) isc__rwlock_lock(rwl, type)
|
||||
#define isc_rwlock_trylock(rwl, type) isc___rwlock_trylock(rwl, type)
|
||||
#define isc_rwlock_trylock(rwl, type) isc__rwlock_trylock(rwl, type)
|
||||
#define isc_rwlock_unlock(rwl, type) isc__rwlock_unlock(rwl, type)
|
||||
#define isc_rwlock_tryupgrade(rwl) isc___rwlock_tryupgrade(rwl)
|
||||
#define isc_rwlock_tryupgrade(rwl) isc__rwlock_tryupgrade(rwl)
|
||||
#define isc_rwlock_destroy(rwl) isc__rwlock_destroy(rwl)
|
||||
|
||||
#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 {
|
||||
|
|
@ -112,54 +201,30 @@ typedef struct isc_rwlock isc__rwlock_t;
|
|||
|
||||
#define isc_rwlock_init(rwl, rq, wq) isc__rwlock_init(rwl, rq, wq)
|
||||
#define isc_rwlock_lock(rwl, type) isc__rwlock_lock(rwl, type)
|
||||
#define isc_rwlock_trylock(rwl, type) isc___rwlock_trylock(rwl, type)
|
||||
#define isc_rwlock_trylock(rwl, type) isc__rwlock_trylock(rwl, type)
|
||||
#define isc_rwlock_unlock(rwl, type) isc__rwlock_unlock(rwl, type)
|
||||
#define isc_rwlock_tryupgrade(rwl) isc___rwlock_tryupgrade(rwl)
|
||||
#define isc_rwlock_tryupgrade(rwl) isc__rwlock_tryupgrade(rwl)
|
||||
#define isc_rwlock_destroy(rwl) isc__rwlock_destroy(rwl)
|
||||
|
||||
void
|
||||
isc__rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
|
||||
unsigned int write_quota);
|
||||
|
||||
void
|
||||
isc__rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type);
|
||||
|
||||
isc_result_t
|
||||
isc__rwlock_trylock(isc__rwlock_t *rwl, isc_rwlocktype_t type);
|
||||
|
||||
void
|
||||
isc__rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type);
|
||||
|
||||
isc_result_t
|
||||
isc__rwlock_tryupgrade(isc__rwlock_t *rwl);
|
||||
|
||||
void
|
||||
isc__rwlock_destroy(isc__rwlock_t *rwl);
|
||||
|
||||
#endif /* USE_PTHREAD_RWLOCK */
|
||||
|
||||
#define isc__rwlock_init(rwl, rq, wq) \
|
||||
{ \
|
||||
int _ret = isc___rwlock_init(rwl, rq, wq); \
|
||||
PTHREADS_RUNTIME_CHECK(isc___rwlock_init, _ret); \
|
||||
}
|
||||
|
||||
#define isc__rwlock_lock(rwl, type) \
|
||||
{ \
|
||||
int _ret = isc___rwlock_lock(rwl, type); \
|
||||
PTHREADS_RUNTIME_CHECK(isc___rwlock_lock, _ret); \
|
||||
}
|
||||
|
||||
#define isc__rwlock_unlock(rwl, type) \
|
||||
{ \
|
||||
int _ret = isc___rwlock_unlock(rwl, type); \
|
||||
PTHREADS_RUNTIME_CHECK(isc___rwlock_unlock, _ret); \
|
||||
}
|
||||
|
||||
#define isc__rwlock_destroy(rwl) \
|
||||
{ \
|
||||
int _ret = isc___rwlock_destroy(rwl); \
|
||||
PTHREADS_RUNTIME_CHECK(isc___rwlock_destroy, _ret); \
|
||||
}
|
||||
|
||||
int
|
||||
isc___rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
|
||||
unsigned int write_quota);
|
||||
|
||||
int
|
||||
isc___rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type);
|
||||
|
||||
isc_result_t
|
||||
isc___rwlock_trylock(isc__rwlock_t *rwl, isc_rwlocktype_t type);
|
||||
|
||||
int
|
||||
isc___rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type);
|
||||
|
||||
isc_result_t
|
||||
isc___rwlock_tryupgrade(isc__rwlock_t *rwl);
|
||||
|
||||
int
|
||||
isc___rwlock_destroy(isc__rwlock_t *rwl);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
108
lib/isc/rwlock.c
108
lib/isc/rwlock.c
|
|
@ -27,80 +27,6 @@
|
|||
#include <isc/rwlock.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#if USE_PTHREAD_RWLOCK
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int
|
||||
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);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
isc___rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
switch (type) {
|
||||
case isc_rwlocktype_read:
|
||||
return (pthread_rwlock_rdlock(rwl));
|
||||
case isc_rwlocktype_write:
|
||||
return (pthread_rwlock_wrlock(rwl));
|
||||
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:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
isc___rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
UNUSED(type);
|
||||
return (pthread_rwlock_unlock(rwl));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc___rwlock_tryupgrade(isc__rwlock_t *rwl) {
|
||||
UNUSED(rwl);
|
||||
return (ISC_R_LOCKBUSY);
|
||||
}
|
||||
|
||||
int
|
||||
isc___rwlock_destroy(isc__rwlock_t *rwl) {
|
||||
return (pthread_rwlock_destroy(rwl));
|
||||
}
|
||||
|
||||
#else /* if USE_PTHREAD_RWLOCK */
|
||||
|
||||
#define RWLOCK_MAGIC ISC_MAGIC('R', 'W', 'L', 'k')
|
||||
#define VALID_RWLOCK(rwl) ISC_MAGIC_VALID(rwl, RWLOCK_MAGIC)
|
||||
|
||||
|
|
@ -158,11 +84,11 @@ 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 */
|
||||
|
||||
int
|
||||
isc___rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
|
||||
unsigned int write_quota) {
|
||||
void
|
||||
isc__rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
|
||||
unsigned int write_quota) {
|
||||
REQUIRE(rwl != NULL);
|
||||
|
||||
/*
|
||||
|
|
@ -191,12 +117,10 @@ isc___rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
|
|||
isc_condition_init(&rwl->writeable);
|
||||
|
||||
rwl->magic = RWLOCK_MAGIC;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
isc___rwlock_destroy(isc__rwlock_t *rwl) {
|
||||
void
|
||||
isc__rwlock_destroy(isc__rwlock_t *rwl) {
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
REQUIRE(atomic_load_acquire(&rwl->write_requests) ==
|
||||
|
|
@ -208,8 +132,6 @@ isc___rwlock_destroy(isc__rwlock_t *rwl) {
|
|||
isc_condition_destroy(&rwl->readable);
|
||||
isc_condition_destroy(&rwl->writeable);
|
||||
isc_mutex_destroy(&rwl->lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -394,8 +316,8 @@ rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||
#endif /* ifdef ISC_RWLOCK_TRACE */
|
||||
}
|
||||
|
||||
int
|
||||
isc___rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
void
|
||||
isc__rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
int32_t cnt = 0;
|
||||
int32_t spins = atomic_load_acquire(&rwl->spins) * 2 + 10;
|
||||
int32_t max_cnt = ISC_MAX(spins, RWLOCK_MAX_ADAPTIVE_COUNT);
|
||||
|
|
@ -409,12 +331,10 @@ isc___rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||
} while (isc_rwlock_trylock(rwl, type) != ISC_R_SUCCESS);
|
||||
|
||||
atomic_fetch_add_release(&rwl->spins, (cnt - spins) / 8);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc___rwlock_trylock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
isc__rwlock_trylock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
int32_t cntflag;
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
|
@ -481,7 +401,7 @@ isc___rwlock_trylock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||
}
|
||||
|
||||
isc_result_t
|
||||
isc___rwlock_tryupgrade(isc__rwlock_t *rwl) {
|
||||
isc__rwlock_tryupgrade(isc__rwlock_t *rwl) {
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
int_fast32_t reader_incr = READER_INCR;
|
||||
|
|
@ -509,8 +429,8 @@ isc___rwlock_tryupgrade(isc__rwlock_t *rwl) {
|
|||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
isc___rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
void
|
||||
isc__rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
int32_t prev_cnt;
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
|
@ -580,8 +500,4 @@ isc___rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock("postunlock", rwl, type);
|
||||
#endif /* ifdef ISC_RWLOCK_TRACE */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* USE_PTHREAD_RWLOCK */
|
||||
|
|
|
|||
Loading…
Reference in a new issue