mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-04 00:25:29 +00:00
Merge branch '3054-1-misc-pthreads-cleanups' into 'main'
[1/3] Miscellaneous pthreads cleanups See merge request isc-projects/bind9!6570
This commit is contained in:
@@ -160,18 +160,16 @@ dig_lookup_t *current_lookup = NULL;
|
|||||||
* Apply and clear locks at the event level in global task.
|
* Apply and clear locks at the event level in global task.
|
||||||
* Can I get rid of these using shutdown events? XXX
|
* Can I get rid of these using shutdown events? XXX
|
||||||
*/
|
*/
|
||||||
#define LOCK_LOOKUP \
|
#define LOCK_LOOKUP \
|
||||||
{ \
|
{ \
|
||||||
debug("lock_lookup %s:%d", __FILE__, __LINE__); \
|
debug("lock_lookup %s:%d", __FILE__, __LINE__); \
|
||||||
check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_" \
|
isc_mutex_lock((&lookup_lock)); \
|
||||||
"lock"); \
|
debug("success"); \
|
||||||
debug("success"); \
|
|
||||||
}
|
}
|
||||||
#define UNLOCK_LOOKUP \
|
#define UNLOCK_LOOKUP \
|
||||||
{ \
|
{ \
|
||||||
debug("unlock_lookup %s:%d", __FILE__, __LINE__); \
|
debug("unlock_lookup %s:%d", __FILE__, __LINE__); \
|
||||||
check_result(isc_mutex_unlock((&lookup_lock)), "isc_mutex_" \
|
isc_mutex_unlock((&lookup_lock)); \
|
||||||
"unlock"); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -154,6 +154,7 @@ libisc_la_SOURCES = \
|
|||||||
mem_p.h \
|
mem_p.h \
|
||||||
meminfo.c \
|
meminfo.c \
|
||||||
mutex.c \
|
mutex.c \
|
||||||
|
mutex_p.h \
|
||||||
mutexblock.c \
|
mutexblock.c \
|
||||||
net.c \
|
net.c \
|
||||||
netaddr.c \
|
netaddr.c \
|
||||||
|
@@ -21,34 +21,27 @@
|
|||||||
#include <isc/lang.h>
|
#include <isc/lang.h>
|
||||||
#include <isc/mutex.h>
|
#include <isc/mutex.h>
|
||||||
#include <isc/result.h>
|
#include <isc/result.h>
|
||||||
#include <isc/strerr.h>
|
|
||||||
#include <isc/string.h>
|
#include <isc/string.h>
|
||||||
#include <isc/types.h>
|
#include <isc/types.h>
|
||||||
|
#include <isc/util.h>
|
||||||
|
|
||||||
typedef pthread_cond_t isc_condition_t;
|
typedef pthread_cond_t isc_condition_t;
|
||||||
|
|
||||||
#define isc_condition_init(cond) \
|
#define isc_condition_init(cond) \
|
||||||
if (pthread_cond_init(cond, NULL) != 0) { \
|
{ \
|
||||||
char isc_condition_strbuf[ISC_STRERRORSIZE]; \
|
int _ret = pthread_cond_init(cond, NULL); \
|
||||||
strerror_r(errno, isc_condition_strbuf, \
|
ERRNO_CHECK(pthread_cond_init, _ret); \
|
||||||
sizeof(isc_condition_strbuf)); \
|
|
||||||
isc_error_fatal(__FILE__, __LINE__, \
|
|
||||||
"pthread_cond_init failed: %s", \
|
|
||||||
isc_condition_strbuf); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define isc_condition_wait(cp, mp) \
|
#define isc_condition_wait(cp, mp) \
|
||||||
((pthread_cond_wait((cp), (mp)) == 0) ? ISC_R_SUCCESS \
|
RUNTIME_CHECK(pthread_cond_wait((cp), (mp)) == 0)
|
||||||
: ISC_R_UNEXPECTED)
|
|
||||||
|
|
||||||
#define isc_condition_signal(cp) \
|
#define isc_condition_signal(cp) RUNTIME_CHECK(pthread_cond_signal((cp)) == 0)
|
||||||
((pthread_cond_signal((cp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
|
|
||||||
|
|
||||||
#define isc_condition_broadcast(cp) \
|
#define isc_condition_broadcast(cp) \
|
||||||
((pthread_cond_broadcast((cp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
|
RUNTIME_CHECK(pthread_cond_broadcast((cp)) == 0)
|
||||||
|
|
||||||
#define isc_condition_destroy(cp) \
|
#define isc_condition_destroy(cp) RUNTIME_CHECK(pthread_cond_destroy((cp)) == 0)
|
||||||
((pthread_cond_destroy((cp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
|
|
||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
|
@@ -26,15 +26,13 @@ ISC_LANG_BEGINDECLS
|
|||||||
typedef pthread_mutex_t isc_mutex_t;
|
typedef pthread_mutex_t isc_mutex_t;
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line);
|
isc__mutex_init(isc_mutex_t *mp);
|
||||||
|
|
||||||
#define isc_mutex_init(mp) isc__mutex_init((mp), __FILE__, __LINE__)
|
#define isc_mutex_init(mp) isc__mutex_init((mp))
|
||||||
|
|
||||||
#define isc_mutex_lock(mp) \
|
#define isc_mutex_lock(mp) RUNTIME_CHECK(pthread_mutex_lock((mp)) == 0)
|
||||||
((pthread_mutex_lock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
|
|
||||||
|
|
||||||
#define isc_mutex_unlock(mp) \
|
#define isc_mutex_unlock(mp) RUNTIME_CHECK(pthread_mutex_unlock((mp)) == 0)
|
||||||
((pthread_mutex_unlock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
|
|
||||||
|
|
||||||
#define isc_mutex_trylock(mp) \
|
#define isc_mutex_trylock(mp) \
|
||||||
((pthread_mutex_trylock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY)
|
((pthread_mutex_trylock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY)
|
||||||
|
@@ -82,13 +82,13 @@ void
|
|||||||
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
||||||
unsigned int write_quota);
|
unsigned int write_quota);
|
||||||
|
|
||||||
isc_result_t
|
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_result_t
|
||||||
isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
|
isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
|
||||||
|
|
||||||
isc_result_t
|
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_result_t
|
||||||
|
@@ -122,8 +122,6 @@
|
|||||||
/*%
|
/*%
|
||||||
* We use macros instead of calling the routines directly because
|
* We use macros instead of calling the routines directly because
|
||||||
* the capital letters make the locking stand out.
|
* the capital letters make the locking stand out.
|
||||||
* We RUNTIME_CHECK for success since in general there's no way
|
|
||||||
* for us to continue if they fail.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef ISC_UTIL_TRACEON
|
#ifdef ISC_UTIL_TRACEON
|
||||||
@@ -136,42 +134,40 @@
|
|||||||
#include <isc/result.h> /* Contractual promise. */
|
#include <isc/result.h> /* Contractual promise. */
|
||||||
|
|
||||||
#define LOCK(lp) \
|
#define LOCK(lp) \
|
||||||
do { \
|
{ \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "LOCKING %p %s %d\n", (lp), \
|
ISC_UTIL_TRACE(fprintf(stderr, "LOCKING %p %s %d\n", (lp), \
|
||||||
__FILE__, __LINE__)); \
|
__FILE__, __LINE__)); \
|
||||||
RUNTIME_CHECK(isc_mutex_lock((lp)) == ISC_R_SUCCESS); \
|
isc_mutex_lock((lp)); \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "LOCKED %p %s %d\n", (lp), \
|
ISC_UTIL_TRACE(fprintf(stderr, "LOCKED %p %s %d\n", (lp), \
|
||||||
__FILE__, __LINE__)); \
|
__FILE__, __LINE__)); \
|
||||||
} while (0)
|
}
|
||||||
#define UNLOCK(lp) \
|
#define UNLOCK(lp) \
|
||||||
do { \
|
{ \
|
||||||
RUNTIME_CHECK(isc_mutex_unlock((lp)) == ISC_R_SUCCESS); \
|
isc_mutex_unlock((lp)); \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "UNLOCKED %p %s %d\n", (lp), \
|
ISC_UTIL_TRACE(fprintf(stderr, "UNLOCKED %p %s %d\n", (lp), \
|
||||||
__FILE__, __LINE__)); \
|
__FILE__, __LINE__)); \
|
||||||
} while (0)
|
}
|
||||||
|
|
||||||
#define BROADCAST(cvp) \
|
#define BROADCAST(cvp) \
|
||||||
do { \
|
{ \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "BROADCAST %p %s %d\n", (cvp), \
|
ISC_UTIL_TRACE(fprintf(stderr, "BROADCAST %p %s %d\n", (cvp), \
|
||||||
__FILE__, __LINE__)); \
|
__FILE__, __LINE__)); \
|
||||||
RUNTIME_CHECK(isc_condition_broadcast((cvp)) == \
|
isc_condition_broadcast((cvp)); \
|
||||||
ISC_R_SUCCESS); \
|
}
|
||||||
} while (0)
|
#define SIGNAL(cvp) \
|
||||||
#define SIGNAL(cvp) \
|
{ \
|
||||||
do { \
|
ISC_UTIL_TRACE(fprintf(stderr, "SIGNAL %p %s %d\n", (cvp), \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "SIGNAL %p %s %d\n", (cvp), \
|
__FILE__, __LINE__)); \
|
||||||
__FILE__, __LINE__)); \
|
isc_condition_signal((cvp)); \
|
||||||
RUNTIME_CHECK(isc_condition_signal((cvp)) == ISC_R_SUCCESS); \
|
}
|
||||||
} while (0)
|
|
||||||
#define WAIT(cvp, lp) \
|
#define WAIT(cvp, lp) \
|
||||||
do { \
|
{ \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "WAIT %p LOCK %p %s %d\n", \
|
ISC_UTIL_TRACE(fprintf(stderr, "WAIT %p LOCK %p %s %d\n", \
|
||||||
(cvp), (lp), __FILE__, __LINE__)); \
|
(cvp), (lp), __FILE__, __LINE__)); \
|
||||||
RUNTIME_CHECK(isc_condition_wait((cvp), (lp)) == \
|
isc_condition_wait((cvp), (lp)); \
|
||||||
ISC_R_SUCCESS); \
|
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "WAITED %p LOCKED %p %s %d\n", \
|
ISC_UTIL_TRACE(fprintf(stderr, "WAITED %p LOCKED %p %s %d\n", \
|
||||||
(cvp), (lp), __FILE__, __LINE__)); \
|
(cvp), (lp), __FILE__, __LINE__)); \
|
||||||
} while (0)
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
|
* isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
|
||||||
@@ -183,19 +179,19 @@
|
|||||||
#define WAITUNTIL(cvp, lp, tp) isc_condition_waituntil((cvp), (lp), (tp))
|
#define WAITUNTIL(cvp, lp, tp) isc_condition_waituntil((cvp), (lp), (tp))
|
||||||
|
|
||||||
#define RWLOCK(lp, t) \
|
#define RWLOCK(lp, t) \
|
||||||
do { \
|
{ \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "RWLOCK %p, %d %s %d\n", (lp), \
|
ISC_UTIL_TRACE(fprintf(stderr, "RWLOCK %p, %d %s %d\n", (lp), \
|
||||||
(t), __FILE__, __LINE__)); \
|
(t), __FILE__, __LINE__)); \
|
||||||
RUNTIME_CHECK(isc_rwlock_lock((lp), (t)) == ISC_R_SUCCESS); \
|
isc_rwlock_lock((lp), (t)); \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "RWLOCKED %p, %d %s %d\n", \
|
ISC_UTIL_TRACE(fprintf(stderr, "RWLOCKED %p, %d %s %d\n", \
|
||||||
(lp), (t), __FILE__, __LINE__)); \
|
(lp), (t), __FILE__, __LINE__)); \
|
||||||
} while (0)
|
}
|
||||||
#define RWUNLOCK(lp, t) \
|
#define RWUNLOCK(lp, t) \
|
||||||
do { \
|
{ \
|
||||||
ISC_UTIL_TRACE(fprintf(stderr, "RWUNLOCK %p, %d %s %d\n", \
|
ISC_UTIL_TRACE(fprintf(stderr, "RWUNLOCK %p, %d %s %d\n", \
|
||||||
(lp), (t), __FILE__, __LINE__)); \
|
(lp), (t), __FILE__, __LINE__)); \
|
||||||
RUNTIME_CHECK(isc_rwlock_unlock((lp), (t)) == ISC_R_SUCCESS); \
|
isc_rwlock_unlock((lp), (t)); \
|
||||||
} while (0)
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List Macros.
|
* List Macros.
|
||||||
@@ -309,7 +305,10 @@ mock_assert(const int result, const char *const expression,
|
|||||||
/*
|
/*
|
||||||
* Errors
|
* Errors
|
||||||
*/
|
*/
|
||||||
#include <isc/error.h> /* Contractual promise. */
|
#include <errno.h> /* for errno */
|
||||||
|
|
||||||
|
#include <isc/error.h> /* Contractual promise. */
|
||||||
|
#include <isc/strerr.h> /* for ISC_STRERRORSIZE */
|
||||||
|
|
||||||
/*% Unexpected Error */
|
/*% Unexpected Error */
|
||||||
#define UNEXPECTED_ERROR isc_error_unexpected
|
#define UNEXPECTED_ERROR isc_error_unexpected
|
||||||
@@ -330,6 +329,15 @@ mock_assert(const int result, const char *const expression,
|
|||||||
|
|
||||||
#endif /* UNIT_TESTING */
|
#endif /* UNIT_TESTING */
|
||||||
|
|
||||||
|
/*% Runtime check which logs the error string corresponding to errno */
|
||||||
|
#define ERRNO_CHECK(func, ret) \
|
||||||
|
if ((ret) != 0) { \
|
||||||
|
char _strerrorbuf[ISC_STRERRORSIZE]; \
|
||||||
|
strerror_r(errno, _strerrorbuf, sizeof(_strerrorbuf)); \
|
||||||
|
isc_error_fatal(__FILE__, __LINE__, "%s() failed in %s(): %s", \
|
||||||
|
#func, __func__, _strerrorbuf); \
|
||||||
|
}
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* Time
|
* Time
|
||||||
*/
|
*/
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "mem_p.h"
|
#include "mem_p.h"
|
||||||
|
#include "mutex_p.h"
|
||||||
#include "os_p.h"
|
#include "os_p.h"
|
||||||
#include "tls_p.h"
|
#include "tls_p.h"
|
||||||
#include "trampoline_p.h"
|
#include "trampoline_p.h"
|
||||||
@@ -41,6 +42,7 @@ isc__shutdown(void) ISC_DESTRUCTOR;
|
|||||||
void
|
void
|
||||||
isc__initialize(void) {
|
isc__initialize(void) {
|
||||||
isc__os_initialize();
|
isc__os_initialize();
|
||||||
|
isc__mutex_initialize();
|
||||||
isc__mem_initialize();
|
isc__mem_initialize();
|
||||||
isc__tls_initialize();
|
isc__tls_initialize();
|
||||||
isc__trampoline_initialize();
|
isc__trampoline_initialize();
|
||||||
@@ -52,5 +54,6 @@ isc__shutdown(void) {
|
|||||||
isc__trampoline_shutdown();
|
isc__trampoline_shutdown();
|
||||||
isc__tls_shutdown();
|
isc__tls_shutdown();
|
||||||
isc__mem_shutdown();
|
isc__mem_shutdown();
|
||||||
|
isc__mutex_shutdown();
|
||||||
isc__os_shutdown();
|
isc__os_shutdown();
|
||||||
}
|
}
|
||||||
|
@@ -26,37 +26,36 @@
|
|||||||
#include <isc/string.h>
|
#include <isc/string.h>
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
|
#include "mutex_p.h"
|
||||||
static bool attr_initialized = false;
|
|
||||||
static pthread_mutexattr_t attr;
|
pthread_mutexattr_t isc__mutex_init_attr;
|
||||||
static isc_once_t once_attr = ISC_ONCE_INIT;
|
static isc_once_t init_once = ISC_ONCE_INIT;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
initialize_attr(void) {
|
mutex_initialize(void) {
|
||||||
RUNTIME_CHECK(pthread_mutexattr_init(&attr) == 0);
|
RUNTIME_CHECK(pthread_mutexattr_init(&isc__mutex_init_attr) == 0);
|
||||||
RUNTIME_CHECK(pthread_mutexattr_settype(
|
#ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
|
||||||
&attr, PTHREAD_MUTEX_ADAPTIVE_NP) == 0);
|
RUNTIME_CHECK(pthread_mutexattr_settype(&isc__mutex_init_attr,
|
||||||
attr_initialized = true;
|
PTHREAD_MUTEX_ADAPTIVE_NP) ==
|
||||||
}
|
0);
|
||||||
#endif /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
|
#endif /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
|
isc__mutex_initialize(void) {
|
||||||
|
RUNTIME_CHECK(isc_once_do(&init_once, mutex_initialize) ==
|
||||||
|
ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__mutex_init(isc_mutex_t *mp) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
|
err = pthread_mutex_init(mp, &isc__mutex_init_attr);
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
ERRNO_CHECK(pthread_mutex_init, err);
|
||||||
result = isc_once_do(&once_attr, initialize_attr);
|
}
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
||||||
|
void
|
||||||
err = pthread_mutex_init(mp, &attr);
|
isc__mutex_shutdown(void) {
|
||||||
#else /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
|
/* noop */;
|
||||||
err = pthread_mutex_init(mp, NULL);
|
|
||||||
#endif /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
|
|
||||||
if (err != 0) {
|
|
||||||
char strbuf[ISC_STRERRORSIZE];
|
|
||||||
strerror_r(err, strbuf, sizeof(strbuf));
|
|
||||||
isc_error_fatal(file, line, "pthread_mutex_init failed: %s",
|
|
||||||
strbuf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
22
lib/isc/mutex_p.h
Normal file
22
lib/isc/mutex_p.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* See the COPYRIGHT file distributed with this work for additional
|
||||||
|
* information regarding copyright ownership.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*! \file */
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__mutex_initialize(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__mutex_shutdown(void);
|
@@ -35,25 +35,29 @@
|
|||||||
void
|
void
|
||||||
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
||||||
unsigned int write_quota) {
|
unsigned int write_quota) {
|
||||||
|
int ret;
|
||||||
UNUSED(read_quota);
|
UNUSED(read_quota);
|
||||||
UNUSED(write_quota);
|
UNUSED(write_quota);
|
||||||
REQUIRE(pthread_rwlock_init(&rwl->rwlock, NULL) == 0);
|
|
||||||
|
ret = pthread_rwlock_init(&rwl->rwlock, NULL);
|
||||||
|
ERRNO_CHECK(pthread_rwlock_init, ret);
|
||||||
|
|
||||||
atomic_init(&rwl->downgrade, false);
|
atomic_init(&rwl->downgrade, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
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) {
|
switch (type) {
|
||||||
case isc_rwlocktype_read:
|
case isc_rwlocktype_read:
|
||||||
REQUIRE(pthread_rwlock_rdlock(&rwl->rwlock) == 0);
|
RUNTIME_CHECK(pthread_rwlock_rdlock(&rwl->rwlock) == 0);
|
||||||
break;
|
break;
|
||||||
case isc_rwlocktype_write:
|
case isc_rwlocktype_write:
|
||||||
while (true) {
|
while (true) {
|
||||||
REQUIRE(pthread_rwlock_wrlock(&rwl->rwlock) == 0);
|
RUNTIME_CHECK(pthread_rwlock_wrlock(&rwl->rwlock) == 0);
|
||||||
/* Unlock if in middle of downgrade operation */
|
/* Unlock if in middle of downgrade operation */
|
||||||
if (atomic_load_acquire(&rwl->downgrade)) {
|
if (atomic_load_acquire(&rwl->downgrade)) {
|
||||||
REQUIRE(pthread_rwlock_unlock(&rwl->rwlock) ==
|
RUNTIME_CHECK(pthread_rwlock_unlock(
|
||||||
0);
|
&rwl->rwlock) == 0);
|
||||||
while (atomic_load_acquire(&rwl->downgrade)) {
|
while (atomic_load_acquire(&rwl->downgrade)) {
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -64,7 +68,6 @@ isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@@ -77,7 +80,7 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||||||
case isc_rwlocktype_write:
|
case isc_rwlocktype_write:
|
||||||
ret = pthread_rwlock_trywrlock(&rwl->rwlock);
|
ret = pthread_rwlock_trywrlock(&rwl->rwlock);
|
||||||
if ((ret == 0) && atomic_load_acquire(&rwl->downgrade)) {
|
if ((ret == 0) && atomic_load_acquire(&rwl->downgrade)) {
|
||||||
isc_rwlock_unlock(rwl, type);
|
RUNTIME_CHECK(pthread_rwlock_unlock(&rwl->rwlock) == 0);
|
||||||
return (ISC_R_LOCKBUSY);
|
return (ISC_R_LOCKBUSY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -97,11 +100,10 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
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);
|
UNUSED(type);
|
||||||
REQUIRE(pthread_rwlock_unlock(&rwl->rwlock) == 0);
|
RUNTIME_CHECK(pthread_rwlock_unlock(&rwl->rwlock) == 0);
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@@ -112,12 +114,9 @@ isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
||||||
isc_result_t result;
|
|
||||||
atomic_store_release(&rwl->downgrade, true);
|
atomic_store_release(&rwl->downgrade, true);
|
||||||
result = isc_rwlock_unlock(rwl, isc_rwlocktype_write);
|
RUNTIME_CHECK(pthread_rwlock_unlock(&rwl->rwlock) == 0);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(pthread_rwlock_rdlock(&rwl->rwlock) == 0);
|
||||||
result = isc_rwlock_lock(rwl, isc_rwlocktype_read);
|
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
||||||
atomic_store_release(&rwl->downgrade, false);
|
atomic_store_release(&rwl->downgrade, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +165,7 @@ isc_rwlock_destroy(isc_rwlock_t *rwl) {
|
|||||||
#define isc_rwlock_pause()
|
#define isc_rwlock_pause()
|
||||||
#endif /* if defined(_MSC_VER) */
|
#endif /* if defined(_MSC_VER) */
|
||||||
|
|
||||||
static isc_result_t
|
static void
|
||||||
isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
|
isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
|
||||||
|
|
||||||
#ifdef ISC_RWLOCK_TRACE
|
#ifdef ISC_RWLOCK_TRACE
|
||||||
@@ -234,8 +233,8 @@ isc_rwlock_destroy(isc_rwlock_t *rwl) {
|
|||||||
rwl->readers_waiting == 0);
|
rwl->readers_waiting == 0);
|
||||||
|
|
||||||
rwl->magic = 0;
|
rwl->magic = 0;
|
||||||
(void)isc_condition_destroy(&rwl->readable);
|
isc_condition_destroy(&rwl->readable);
|
||||||
(void)isc_condition_destroy(&rwl->writeable);
|
isc_condition_destroy(&rwl->writeable);
|
||||||
isc_mutex_destroy(&rwl->lock);
|
isc_mutex_destroy(&rwl->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +303,7 @@ isc_rwlock_destroy(isc_rwlock_t *rwl) {
|
|||||||
#define WRITER_ACTIVE 0x1
|
#define WRITER_ACTIVE 0x1
|
||||||
#define READER_INCR 0x2
|
#define READER_INCR 0x2
|
||||||
|
|
||||||
static isc_result_t
|
static 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 cntflag;
|
int32_t cntflag;
|
||||||
|
|
||||||
@@ -419,28 +418,23 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||||||
#ifdef ISC_RWLOCK_TRACE
|
#ifdef ISC_RWLOCK_TRACE
|
||||||
print_lock("postlock", rwl, type);
|
print_lock("postlock", rwl, type);
|
||||||
#endif /* ifdef ISC_RWLOCK_TRACE */
|
#endif /* ifdef ISC_RWLOCK_TRACE */
|
||||||
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
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 cnt = 0;
|
||||||
int32_t spins = atomic_load_acquire(&rwl->spins) * 2 + 10;
|
int32_t spins = atomic_load_acquire(&rwl->spins) * 2 + 10;
|
||||||
int32_t max_cnt = ISC_MAX(spins, RWLOCK_MAX_ADAPTIVE_COUNT);
|
int32_t max_cnt = ISC_MAX(spins, RWLOCK_MAX_ADAPTIVE_COUNT);
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (cnt++ >= max_cnt) {
|
if (cnt++ >= max_cnt) {
|
||||||
result = isc__rwlock_lock(rwl, type);
|
isc__rwlock_lock(rwl, type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
isc_rwlock_pause();
|
isc_rwlock_pause();
|
||||||
} while (isc_rwlock_trylock(rwl, type) != ISC_R_SUCCESS);
|
} while (isc_rwlock_trylock(rwl, type) != ISC_R_SUCCESS);
|
||||||
|
|
||||||
atomic_fetch_add_release(&rwl->spins, (cnt - spins) / 8);
|
atomic_fetch_add_release(&rwl->spins, (cnt - spins) / 8);
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@@ -563,7 +557,7 @@ isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
|||||||
UNLOCK(&rwl->lock);
|
UNLOCK(&rwl->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
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;
|
int32_t prev_cnt;
|
||||||
|
|
||||||
@@ -634,8 +628,6 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||||||
#ifdef ISC_RWLOCK_TRACE
|
#ifdef ISC_RWLOCK_TRACE
|
||||||
print_lock("postunlock", rwl, type);
|
print_lock("postunlock", rwl, type);
|
||||||
#endif /* ifdef ISC_RWLOCK_TRACE */
|
#endif /* ifdef ISC_RWLOCK_TRACE */
|
||||||
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* USE_PTHREAD_RWLOCK */
|
#endif /* USE_PTHREAD_RWLOCK */
|
||||||
|
@@ -38,13 +38,6 @@
|
|||||||
#define THREAD_MINSTACKSIZE (1024U * 1024)
|
#define THREAD_MINSTACKSIZE (1024U * 1024)
|
||||||
#endif /* ifndef THREAD_MINSTACKSIZE */
|
#endif /* ifndef THREAD_MINSTACKSIZE */
|
||||||
|
|
||||||
#define _FATAL(r, f) \
|
|
||||||
{ \
|
|
||||||
char strbuf[ISC_STRERRORSIZE]; \
|
|
||||||
strerror_r(r, strbuf, sizeof(strbuf)); \
|
|
||||||
isc_error_fatal(__FILE__, __LINE__, f " failed: %s", strbuf); \
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
isc_thread_create(isc_threadfunc_t func, isc_threadarg_t arg,
|
isc_thread_create(isc_threadfunc_t func, isc_threadarg_t arg,
|
||||||
isc_thread_t *thread) {
|
isc_thread_t *thread) {
|
||||||
@@ -65,24 +58,18 @@ isc_thread_create(isc_threadfunc_t func, isc_threadarg_t arg,
|
|||||||
#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
|
#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
|
||||||
defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
|
defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
|
||||||
ret = pthread_attr_getstacksize(&attr, &stacksize);
|
ret = pthread_attr_getstacksize(&attr, &stacksize);
|
||||||
if (ret != 0) {
|
ERRNO_CHECK(pthread_attr_getstacksize, ret);
|
||||||
_FATAL(ret, "pthread_attr_getstacksize()");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stacksize < THREAD_MINSTACKSIZE) {
|
if (stacksize < THREAD_MINSTACKSIZE) {
|
||||||
ret = pthread_attr_setstacksize(&attr, THREAD_MINSTACKSIZE);
|
ret = pthread_attr_setstacksize(&attr, THREAD_MINSTACKSIZE);
|
||||||
if (ret != 0) {
|
ERRNO_CHECK(pthread_attr_setstacksize, ret);
|
||||||
_FATAL(ret, "pthread_attr_setstacksize()");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
|
#endif /* if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
|
||||||
* defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) */
|
* defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) */
|
||||||
|
|
||||||
ret = pthread_create(thread, &attr, isc__trampoline_run,
|
ret = pthread_create(thread, &attr, isc__trampoline_run,
|
||||||
trampoline_arg);
|
trampoline_arg);
|
||||||
if (ret != 0) {
|
ERRNO_CHECK(pthread_create, ret);
|
||||||
_FATAL(ret, "pthread_create()");
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_attr_destroy(&attr);
|
pthread_attr_destroy(&attr);
|
||||||
|
|
||||||
@@ -92,9 +79,8 @@ isc_thread_create(isc_threadfunc_t func, isc_threadarg_t arg,
|
|||||||
void
|
void
|
||||||
isc_thread_join(isc_thread_t thread, isc_threadresult_t *result) {
|
isc_thread_join(isc_thread_t thread, isc_threadresult_t *result) {
|
||||||
int ret = pthread_join(thread, result);
|
int ret = pthread_join(thread, result);
|
||||||
if (ret != 0) {
|
|
||||||
_FATAL(ret, "pthread_join()");
|
ERRNO_CHECK(pthread_join, ret);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -570,7 +570,7 @@ isc__timermgr_destroy(isc_timermgr_t **managerp) {
|
|||||||
/*
|
/*
|
||||||
* Clean up.
|
* Clean up.
|
||||||
*/
|
*/
|
||||||
(void)isc_condition_destroy(&manager->wakeup);
|
isc_condition_destroy(&manager->wakeup);
|
||||||
isc_mutex_destroy(&manager->lock);
|
isc_mutex_destroy(&manager->lock);
|
||||||
isc_heap_destroy(&manager->heap);
|
isc_heap_destroy(&manager->heap);
|
||||||
manager->magic = 0;
|
manager->magic = 0;
|
||||||
|
@@ -74,19 +74,12 @@ _teardown(void **state) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
test_shutdown(void) {
|
test_shutdown(void) {
|
||||||
isc_result_t result;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signal shutdown processing complete.
|
* Signal shutdown processing complete.
|
||||||
*/
|
*/
|
||||||
result = isc_mutex_lock(&mx);
|
LOCK(&mx);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
SIGNAL(&cv);
|
||||||
|
UNLOCK(&mx);
|
||||||
result = isc_condition_signal(&cv);
|
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
|
||||||
|
|
||||||
result = isc_mutex_unlock(&mx);
|
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -109,9 +102,9 @@ setup_test(isc_timertype_t timertype, isc_interval_t *interval,
|
|||||||
result = isc_task_create(taskmgr, 0, &task, 0);
|
result = isc_task_create(taskmgr, 0, &task, 0);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
isc_mutex_lock(&lasttime_mx);
|
LOCK(&lasttime_mx);
|
||||||
result = isc_time_now(&lasttime);
|
result = isc_time_now(&lasttime);
|
||||||
isc_mutex_unlock(&lasttime_mx);
|
UNLOCK(&lasttime_mx);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
isc_timer_create(timermgr, task, action, (void *)timertype, &timer);
|
isc_timer_create(timermgr, task, action, (void *)timertype, &timer);
|
||||||
@@ -122,7 +115,7 @@ setup_test(isc_timertype_t timertype, isc_interval_t *interval,
|
|||||||
* Wait for shutdown processing to complete.
|
* Wait for shutdown processing to complete.
|
||||||
*/
|
*/
|
||||||
while (atomic_load(&eventcnt) != nevents) {
|
while (atomic_load(&eventcnt) != nevents) {
|
||||||
result = isc_condition_wait(&cv, &mx);
|
WAIT(&cv, &mx);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +125,7 @@ setup_test(isc_timertype_t timertype, isc_interval_t *interval,
|
|||||||
|
|
||||||
isc_task_detach(&task);
|
isc_task_detach(&task);
|
||||||
isc_mutex_destroy(&mx);
|
isc_mutex_destroy(&mx);
|
||||||
(void)isc_condition_destroy(&cv);
|
isc_condition_destroy(&cv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Reference in New Issue
Block a user