#pragma once
#include <inttypes.h>
+#include <stdlib.h>
/*! \file isc/rwlock.h */
#include <isc/condition.h>
#include <isc/lang.h>
#include <isc/types.h>
+#include <isc/util.h>
ISC_LANG_BEGINDECLS
atomic_bool downgrade;
};
+#if ISC_TRACK_PTHREADS_OBJECTS
+
+typedef struct isc_rwlock *isc_rwlock_t;
+typedef struct isc_rwlock isc__rwlock_t;
+
+#define isc_rwlock_init(rwl, rq, wq) \
+ { \
+ *rwl = malloc(sizeof(**rwl)); \
+ 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_unlock(rwl, type) isc___rwlock_unlock(*rwl, type)
+#define isc_rwlock_tryupgrade(rwl) isc___rwlock_tryupgrade(*rwl)
+#define isc_rwlock_downgrade(rwl) isc___rwlock_downgrade(*rwl)
+#define isc_rwlock_destroy(rwl) \
+ { \
+ isc___rwlock_destroy(*rwl); \
+ free(*rwl); \
+ }
+
+#else /* ISC_TRACK_PTHREADS_OBJECTS */
+
+typedef struct isc_rwlock isc_rwlock_t;
+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_unlock(rwl, type) isc___rwlock_unlock(rwl, type)
+#define isc_rwlock_tryupgrade(rwl) isc___rwlock_tryupgrade(rwl)
+#define isc_rwlock_downgrade(rwl) isc___rwlock_downgrade(rwl)
+#define isc_rwlock_destroy(rwl) isc___rwlock_destroy(rwl)
+
+#endif /* ISC_TRACK_PTHREADS_OBJECTS */
+
#else /* USE_PTHREAD_RWLOCK */
struct isc_rwlock {
unsigned int write_quota;
};
+typedef struct isc_rwlock isc_rwlock_t;
+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_unlock(rwl, type) isc___rwlock_unlock(rwl, type)
+#define isc_rwlock_tryupgrade(rwl) isc___rwlock_tryupgrade(rwl)
+#define isc_rwlock_downgrade(rwl) isc___rwlock_downgrade(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);
+#define isc__rwlock_init(rwl, rq, wq) \
+ { \
+ int _ret = isc___rwlock_init(rwl, rq, wq); \
+ ERRNO_CHECK(isc___rwlock_init, _ret); \
+ }
+
+int
+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___rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type);
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);
void
-isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+isc___rwlock_unlock(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);
void
-isc_rwlock_downgrade(isc_rwlock_t *rwl);
+isc___rwlock_downgrade(isc__rwlock_t *rwl);
void
-isc_rwlock_destroy(isc_rwlock_t *rwl);
+isc___rwlock_destroy(isc__rwlock_t *rwl);
ISC_LANG_ENDDECLS
#include <errno.h>
#include <pthread.h>
-void
-isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
- unsigned int write_quota) {
+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->rwlock, NULL);
- ERRNO_CHECK(pthread_rwlock_init, ret);
atomic_init(&rwl->downgrade, false);
+
+ return (ret);
}
void
-isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+isc___rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
switch (type) {
case isc_rwlocktype_read:
RUNTIME_CHECK(pthread_rwlock_rdlock(&rwl->rwlock) == 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) {
int ret = 0;
switch (type) {
case isc_rwlocktype_read:
}
void
-isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+isc___rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
UNUSED(type);
RUNTIME_CHECK(pthread_rwlock_unlock(&rwl->rwlock) == 0);
}
isc_result_t
-isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+isc___rwlock_tryupgrade(isc__rwlock_t *rwl) {
UNUSED(rwl);
return (ISC_R_LOCKBUSY);
}
void
-isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+isc___rwlock_downgrade(isc__rwlock_t *rwl) {
atomic_store_release(&rwl->downgrade, true);
RUNTIME_CHECK(pthread_rwlock_unlock(&rwl->rwlock) == 0);
RUNTIME_CHECK(pthread_rwlock_rdlock(&rwl->rwlock) == 0);
}
void
-isc_rwlock_destroy(isc_rwlock_t *rwl) {
+isc___rwlock_destroy(isc__rwlock_t *rwl) {
pthread_rwlock_destroy(&rwl->rwlock);
}
#define isc_rwlock_pause()
#endif /* if defined(_MSC_VER) */
-static void
-isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
-
#ifdef ISC_RWLOCK_TRACE
#include <stdio.h> /* Required for fprintf/stderr. */
#include <isc/thread.h> /* Required for isc_thread_self(). */
static void
-print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+print_lock(const char *operation, isc__rwlock_t *rwl, isc_rwlocktype_t type) {
fprintf(stderr,
"rwlock %p thread %" PRIuPTR " %s(%s): "
"write_requests=%u, write_completions=%u, "
}
#endif /* ISC_RWLOCK_TRACE */
-void
-isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
- unsigned int write_quota) {
+int
+isc___rwlock_init(isc__rwlock_t *rwl, unsigned int read_quota,
+ unsigned int write_quota) {
REQUIRE(rwl != NULL);
/*
isc_condition_init(&rwl->writeable);
rwl->magic = RWLOCK_MAGIC;
+
+ return (0);
}
void
-isc_rwlock_destroy(isc_rwlock_t *rwl) {
+isc___rwlock_destroy(isc__rwlock_t *rwl) {
REQUIRE(VALID_RWLOCK(rwl));
REQUIRE(atomic_load_acquire(&rwl->write_requests) ==
#define READER_INCR 0x2
static void
-isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+rwlock_lock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
int32_t cntflag;
REQUIRE(VALID_RWLOCK(rwl));
}
void
-isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+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);
do {
if (cnt++ >= max_cnt) {
- isc__rwlock_lock(rwl, type);
+ rwlock_lock(rwl, type);
break;
}
isc_rwlock_pause();
}
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));
}
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;
}
void
-isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+isc___rwlock_downgrade(isc__rwlock_t *rwl) {
int32_t prev_readers;
REQUIRE(VALID_RWLOCK(rwl));
}
void
-isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+isc___rwlock_unlock(isc__rwlock_t *rwl, isc_rwlocktype_t type) {
int32_t prev_cnt;
REQUIRE(VALID_RWLOCK(rwl));