Merge branch '1038-proper-atomics-use' into 'master'

Resolve "Make proper use of the atomics"

Closes #1038

See merge request isc-projects/bind9!1952
This commit is contained in:
Witold Krecicki 2019-07-09 11:14:49 -04:00
commit fcabb55942
40 changed files with 697 additions and 704 deletions

View file

@ -503,6 +503,29 @@ unit:rwlock:sid:amd64:
dependencies:
- rwlock:sid:amd64
# Jobs for mutex-based atomics on Debian SID (amd64)
mutexatomics:sid:amd64:
variables:
CC: gcc
CFLAGS: "-Wall -Wextra -O2 -g -DISC_MEM_USE_INTERNAL_MALLOC=0"
EXTRA_CONFIGURE: "--with-libidn2 --enable-mutex-atomics"
<<: *debian_sid_amd64_image
<<: *build_job
system:mutexatomics:sid:amd64:
<<: *debian_sid_amd64_image
<<: *system_test_job
dependencies:
- mutexatomics:sid:amd64
allow_failure: true
unit:mutexatomics:sid:amd64:
<<: *debian_sid_amd64_image
<<: *unit_test_job
dependencies:
- mutexatomics:sid:amd64
allow_failure: true
# Jobs for Clang builds on Debian Stretch (amd64)
clang:stretch:amd64:

View file

@ -1,3 +1,6 @@
5263. [cleanup] Use atomics and isc_refcount_t wherever possible.
[GL #1038]
5262. [func] Removed support for the legacy GeoIP API. [GL #1112]
5261. [cleanup] Remove SO_BSDCOMPAT socket option usage.

View file

@ -156,8 +156,8 @@ static unsigned char *gsalt = saltbuf;
static size_t salt_length = 0;
static isc_task_t *master = NULL;
static unsigned int ntasks = 0;
static atomic_bool shuttingdown = ATOMIC_VAR_INIT(false);
static atomic_bool finished = ATOMIC_VAR_INIT(false);
static atomic_bool shuttingdown;
static atomic_bool finished;
static bool nokeys = false;
static bool removefile = false;
static bool generateds = false;
@ -3216,6 +3216,9 @@ main(int argc, char *argv[]) {
bool set_iter = false;
bool nonsecify = false;
atomic_init(&shuttingdown, false);
atomic_init(&finished, false);
/* Unused letters: Bb G J q Yy (and F is reserved). */
#define CMDLINE_FLAGS \
"3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:M:n:N:o:O:PpQRr:s:ST:tuUv:VX:xzZ:"

View file

@ -480,6 +480,9 @@
/* Define to allow building of objects for dlopen(). */
#undef ISC_DLZ_DLOPEN
/* Define to emulate atomic variables with mutexes. */
#undef ISC_MUTEX_ATOMICS
/* define if the linker supports --wrap option */
#undef LD_WRAP

54
configure vendored
View file

@ -850,6 +850,7 @@ infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
@ -897,6 +898,7 @@ enable_warn_shadow
enable_warn_error
enable_developer
enable_fuzzing
enable_mutex_atomics
with_python
with_python_install_dir
enable_kqueue
@ -1018,6 +1020,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@ -1270,6 +1273,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@ -1407,7 +1419,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir
libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@ -1560,6 +1572,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@ -1611,6 +1624,8 @@ Optional Features:
--enable-fuzzing=<afl|libfuzzer>
Enable fuzzing using American Fuzzy Lop or libFuzzer
(default=no)
--enable-mutex-atomics emulate atomics by mutex-locked variables, useful
for debugging [default=no]
--enable-kqueue use BSD kqueue when available [default=yes]
--enable-epoll use Linux epoll when available [default=auto]
--enable-devpoll use /dev/poll when available [default=yes]
@ -3998,7 +4013,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -4044,7 +4059,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -4068,7 +4083,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -4113,7 +4128,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -4137,7 +4152,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@ -12314,6 +12329,33 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
# Check whether --enable-mutex_atomics was given.
if test "${enable_mutex_atomics+set}" = set; then :
enableval=$enable_mutex_atomics;
else
enable_mutex_atomics=no
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to emulate atomics with mutexes" >&5
$as_echo_n "checking whether to emulate atomics with mutexes... " >&6; }
case "$enable_mutex_atomics" in
yes)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define ISC_MUTEX_ATOMICS 1" >>confdefs.h
;;
no)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
;;
*)
as_fn_error $? "\"--enable-mutex-atomics requires yes or no\"" "$LINENO" 5
;;
esac
#
# Make very sure that these are the first files processed by
# config.status, since we use the processed output as the input for

View file

@ -132,6 +132,27 @@ AS_IF([test "$enable_fuzzing" = "afl"],
[AC_MSG_ERROR([set CC=afl-<gcc|clang> when --enable-fuzzing=afl is used])])
])
AC_ARG_ENABLE(mutex_atomics,
AS_HELP_STRING([--enable-mutex-atomics],
[emulate atomics by mutex-locked variables, useful for debugging
[default=no]]),
[],
[enable_mutex_atomics=no])
AC_MSG_CHECKING([whether to emulate atomics with mutexes])
case "$enable_mutex_atomics" in
yes)
AC_MSG_RESULT(yes)
AC_DEFINE(ISC_MUTEX_ATOMICS, 1, [Define to emulate atomic variables with mutexes.])
;;
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_ERROR("--enable-mutex-atomics requires yes or no")
;;
esac
#
# Make very sure that these are the first files processed by
# config.status, since we use the processed output as the input for

View file

@ -18,6 +18,7 @@
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/string.h>
#include <isc/stats.h>
#include <isc/task.h>
@ -130,9 +131,9 @@ struct dns_cache {
isc_mem_t *mctx; /* Main cache memory */
isc_mem_t *hmctx; /* Heap memory */
char *name;
isc_refcount_t references;
/* Locked by 'lock'. */
int references;
int live_tasks;
dns_rdataclass_t rdclass;
dns_db_t *db;
@ -214,7 +215,7 @@ dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
isc_mutex_init(&cache->lock);
isc_mutex_init(&cache->filelock);
cache->references = 1;
isc_refcount_init(&cache->references, 1);
cache->live_tasks = 0;
cache->rdclass = rdclass;
cache->serve_stale_ttl = 0;
@ -337,7 +338,7 @@ cache_free(dns_cache_t *cache) {
int i;
REQUIRE(VALID_CACHE(cache));
REQUIRE(cache->references == 0);
REQUIRE(isc_refcount_current(&cache->references) == 0);
isc_mem_setwater(cache->mctx, NULL, NULL, 0, 0);
@ -402,9 +403,7 @@ dns_cache_attach(dns_cache_t *cache, dns_cache_t **targetp) {
REQUIRE(VALID_CACHE(cache));
REQUIRE(targetp != NULL && *targetp == NULL);
LOCK(&cache->lock);
cache->references++;
UNLOCK(&cache->lock);
isc_refcount_increment(&cache->references);
*targetp = cache;
}
@ -417,18 +416,12 @@ dns_cache_detach(dns_cache_t **cachep) {
REQUIRE(cachep != NULL);
cache = *cachep;
REQUIRE(VALID_CACHE(cache));
LOCK(&cache->lock);
REQUIRE(cache->references > 0);
cache->references--;
if (cache->references == 0) {
cache->cleaner.overmem = false;
free_cache = true;
}
*cachep = NULL;
if (free_cache) {
if (isc_refcount_decrement(&cache->references) == 1) {
LOCK(&cache->lock);
free_cache = true;
cache->cleaner.overmem = false;
/*
* When the cache is shut down, dump it to a file if one is
* specified.
@ -447,12 +440,13 @@ dns_cache_detach(dns_cache_t **cachep) {
isc_task_shutdown(cache->cleaner.task);
free_cache = false;
}
UNLOCK(&cache->lock);
}
UNLOCK(&cache->lock);
if (free_cache)
if (free_cache) {
cache_free(cache);
}
}
void
@ -1030,8 +1024,9 @@ cleaner_shutdown_action(isc_task_t *task, isc_event_t *event) {
cache->live_tasks--;
INSIST(cache->live_tasks == 0);
if (cache->references == 0)
if (isc_refcount_current(&cache->references) == 0) {
should_free = true;
}
/* Make sure we don't reschedule anymore. */
(void)isc_task_purge(task, NULL, DNS_EVENT_CACHECLEAN, NULL);

View file

@ -25,10 +25,9 @@ struct dns_dbtable {
unsigned int magic;
isc_mem_t * mctx;
dns_rdataclass_t rdclass;
isc_mutex_t lock;
isc_rwlock_t tree_lock;
/* Locked by lock. */
unsigned int references;
/* Protected by atomics */
isc_refcount_t references;
/* Locked by tree_lock. */
dns_rbt_t * rbt;
dns_db_t * default_db;
@ -65,8 +64,6 @@ dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
if (result != ISC_R_SUCCESS)
goto clean1;
isc_mutex_init(&dbtable->lock);
result = isc_rwlock_init(&dbtable->tree_lock, 0, 0);
if (result != ISC_R_SUCCESS)
goto clean3;
@ -76,15 +73,13 @@ dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
isc_mem_attach(mctx, &dbtable->mctx);
dbtable->rdclass = rdclass;
dbtable->magic = DBTABLE_MAGIC;
dbtable->references = 1;
isc_refcount_init(&dbtable->references, 1);
*dbtablep = dbtable;
return (ISC_R_SUCCESS);
clean3:
isc_mutex_destroy(&dbtable->lock);
dns_rbt_destroy(&dbtable->rbt);
clean1:
@ -120,13 +115,7 @@ dns_dbtable_attach(dns_dbtable_t *source, dns_dbtable_t **targetp) {
REQUIRE(VALID_DBTABLE(source));
REQUIRE(targetp != NULL && *targetp == NULL);
LOCK(&source->lock);
INSIST(source->references > 0);
source->references++;
INSIST(source->references != 0);
UNLOCK(&source->lock);
isc_refcount_increment(&source->references);
*targetp = source;
}
@ -134,25 +123,15 @@ dns_dbtable_attach(dns_dbtable_t *source, dns_dbtable_t **targetp) {
void
dns_dbtable_detach(dns_dbtable_t **dbtablep) {
dns_dbtable_t *dbtable;
bool free_dbtable = false;
REQUIRE(dbtablep != NULL);
dbtable = *dbtablep;
REQUIRE(VALID_DBTABLE(dbtable));
LOCK(&dbtable->lock);
INSIST(dbtable->references > 0);
dbtable->references--;
if (dbtable->references == 0)
free_dbtable = true;
UNLOCK(&dbtable->lock);
if (free_dbtable)
dbtable_free(dbtable);
*dbtablep = NULL;
if (isc_refcount_decrement(&dbtable->references) == 1) {
dbtable_free(dbtable);
}
}
isc_result_t

View file

@ -174,7 +174,7 @@ struct dispsocket {
*/
struct dispportentry {
in_port_t port;
unsigned int refs;
isc_refcount_t refs;
ISC_LINK(struct dispportentry) link;
};
@ -578,7 +578,7 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) {
return (portentry);
portentry->port = port;
portentry->refs = 1;
isc_refcount_init(&portentry->refs, 1);
ISC_LINK_INIT(portentry, link);
qid = DNS_QID(disp);
LOCK(&qid->lock);
@ -598,26 +598,25 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
dns_qid_t *qid;
REQUIRE(disp->port_table != NULL);
REQUIRE(portentry != NULL && portentry->refs > 0);
REQUIRE(portentry != NULL && isc_refcount_current(&portentry->refs) > 0);
qid = DNS_QID(disp);
LOCK(&qid->lock);
portentry->refs--;
if (portentry->refs == 0) {
if (isc_refcount_decrement(&portentry->refs) == 1) {
qid = DNS_QID(disp);
LOCK(&qid->lock);
ISC_LIST_UNLINK(disp->port_table[portentry->port %
DNS_DISPATCH_PORTTABLESIZE],
portentry, link);
isc_mempool_put(disp->portpool, portentry);
UNLOCK(&qid->lock);
}
/*
* XXXWPK TODO: is it really necessary?
* Set '*portentryp' to NULL inside the lock so that
* dispsock->portentry does not change in socket_search.
*/
*portentryp = NULL;
UNLOCK(&qid->lock);
}
/*%
@ -736,9 +735,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
break;
}
} else {
LOCK(&qid->lock);
portentry->refs++;
UNLOCK(&qid->lock);
isc_refcount_increment(&portentry->refs);
}
break;
} else if (result == ISC_R_NOPERM) {

View file

@ -11,6 +11,7 @@
#include <stdbool.h>
#include <isc/refcount.h>
#include <isc/result.h>
#include <isc/util.h>
#include <isc/mutex.h>
@ -43,8 +44,10 @@ typedef struct dns_ecdb {
dns_db_t common;
isc_mutex_t lock;
/* Protected by atomics */
isc_refcount_t references;
/* Locked */
unsigned int references;
ISC_LIST(struct dns_ecdbnode) nodes;
} dns_ecdb_t;
@ -58,7 +61,9 @@ typedef struct dns_ecdbnode {
/* Locked */
ISC_LIST(struct rdatasetheader) rdatasets;
unsigned int references;
/* Protected by atomics */
isc_refcount_t references;
} dns_ecdbnode_t;
typedef struct rdatasetheader {
@ -156,9 +161,7 @@ attach(dns_db_t *source, dns_db_t **targetp) {
REQUIRE(VALID_ECDB(ecdb));
REQUIRE(targetp != NULL && *targetp == NULL);
LOCK(&ecdb->lock);
ecdb->references++;
UNLOCK(&ecdb->lock);
isc_refcount_increment(&ecdb->references);
*targetp = source;
}
@ -172,6 +175,7 @@ destroy_ecdb(dns_ecdb_t **ecdbp) {
dns_name_free(&ecdb->common.origin, mctx);
isc_mutex_destroy(&ecdb->lock);
isc_refcount_destroy(&ecdb->references);
ecdb->common.impmagic = 0;
ecdb->common.magic = 0;
@ -191,9 +195,10 @@ detach(dns_db_t **dbp) {
REQUIRE(VALID_ECDB(ecdb));
LOCK(&ecdb->lock);
ecdb->references--;
if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
if (isc_refcount_decrement(&ecdb->references) == 1 &&
ISC_LIST_EMPTY(ecdb->nodes)) {
need_destroy = true;
}
UNLOCK(&ecdb->lock);
if (need_destroy)
@ -211,11 +216,7 @@ attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
REQUIRE(VALID_ECDBNODE(node));
REQUIRE(targetp != NULL && *targetp == NULL);
LOCK(&node->lock);
INSIST(node->references > 0);
node->references++;
INSIST(node->references != 0); /* Catch overflow. */
UNLOCK(&node->lock);
isc_refcount_increment(&node->references);
*targetp = node;
}
@ -231,8 +232,10 @@ destroynode(dns_ecdbnode_t *node) {
LOCK(&ecdb->lock);
ISC_LIST_UNLINK(ecdb->nodes, node, link);
if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
if (isc_refcount_current(&ecdb->references) == 0 &&
ISC_LIST_EMPTY(ecdb->nodes)) {
need_destroydb = true;
}
UNLOCK(&ecdb->lock);
dns_name_free(&node->name, mctx);
@ -248,6 +251,7 @@ destroynode(dns_ecdbnode_t *node) {
}
isc_mutex_destroy(&node->lock);
isc_refcount_destroy(&node->references);
node->magic = 0;
isc_mem_put(mctx, node, sizeof(*node));
@ -260,26 +264,16 @@ static void
detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
dns_ecdbnode_t *node;
bool need_destroy = false;
REQUIRE(VALID_ECDB(ecdb));
REQUIRE(nodep != NULL);
node = (dns_ecdbnode_t *)*nodep;
REQUIRE(VALID_ECDBNODE(node));
UNUSED(ecdb); /* in case REQUIRE() is empty */
LOCK(&node->lock);
INSIST(node->references > 0);
node->references--;
if (node->references == 0)
need_destroy = true;
UNLOCK(&node->lock);
if (need_destroy)
destroynode(node);
*nodep = NULL;
if (isc_refcount_decrement(&node->references) == 1) {
destroynode(node);
}
}
static isc_result_t
@ -362,7 +356,7 @@ findnode(dns_db_t *db, const dns_name_t *name, bool create,
return (result);
}
node->ecdb= ecdb;
node->references = 1;
isc_refcount_init(&node->references, 1);
ISC_LIST_INIT(node->rdatasets);
ISC_LINK_INIT(node, link);
@ -413,8 +407,7 @@ bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node,
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
INSIST(node->references > 0);
node->references++;
isc_refcount_increment(&node->references);
}
static isc_result_t
@ -618,7 +611,7 @@ dns_ecdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
isc_mutex_init(&ecdb->lock);
ecdb->references = 1;
isc_refcount_init(&ecdb->references, 1);
ISC_LIST_INIT(ecdb->nodes);
ecdb->common.mctx = NULL;

View file

@ -50,8 +50,9 @@ struct dns_ntatable {
isc_taskmgr_t *taskmgr;
isc_timermgr_t *timermgr;
isc_task_t *task;
/* Protected by atomics */
isc_refcount_t references;
/* Locked by rwlock. */
uint32_t references;
dns_rbt_t *table;
};

View file

@ -67,7 +67,7 @@ struct dns_tsig_keyring {
unsigned int generated;
unsigned int maxgenerated;
ISC_LIST(dns_tsigkey_t) lru;
unsigned int references;
isc_refcount_t references;
};
struct dns_tsigkey {

View file

@ -18,6 +18,7 @@
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/once.h>
#include <isc/refcount.h>
#include <isc/util.h>
#include <dns/db.h>
@ -43,8 +44,7 @@ static isc_once_t init_once = ISC_ONCE_INIT;
static isc_mem_t *dns_g_mctx = NULL;
static dns_dbimplementation_t *dbimp = NULL;
static bool initialize_done = false;
static isc_mutex_t reflock;
static unsigned int references = 0;
static isc_refcount_t references;
static void
initialize(void) {
@ -52,6 +52,8 @@ initialize(void) {
REQUIRE(initialize_done == false);
isc_refcount_init(&references, 0);
result = isc_mem_create(0, 0, &dns_g_mctx);
if (result != ISC_R_SUCCESS)
return;
@ -64,8 +66,6 @@ initialize(void) {
if (result != ISC_R_SUCCESS)
goto cleanup_db;
isc_mutex_init(&reflock);
initialize_done = true;
return;
@ -93,29 +93,23 @@ dns_lib_init(void) {
if (!initialize_done)
return (ISC_R_FAILURE);
LOCK(&reflock);
references++;
UNLOCK(&reflock);
isc_refcount_increment(&references);
return (ISC_R_SUCCESS);
}
void
dns_lib_shutdown(void) {
bool cleanup_ok = false;
if (isc_refcount_decrement(&references) == 1) {
dst_lib_destroy();
LOCK(&reflock);
if (--references == 0)
cleanup_ok = true;
UNLOCK(&reflock);
isc_refcount_destroy(&references);
if (!cleanup_ok)
return;
dst_lib_destroy();
if (dbimp != NULL)
dns_ecdb_unregister(&dbimp);
if (dns_g_mctx != NULL)
isc_mem_detach(&dns_g_mctx);
if (dbimp != NULL) {
dns_ecdb_unregister(&dbimp);
}
if (dns_g_mctx != NULL) {
isc_mem_detach(&dns_g_mctx);
}
}
}

View file

@ -14,11 +14,13 @@
#include <inttypes.h>
#include <stdbool.h>
#include <isc/atomic.h>
#include <isc/event.h>
#include <isc/lex.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/serial.h>
#include <isc/stdio.h>
#include <isc/stdtime.h>
@ -136,11 +138,13 @@ struct dns_loadctx {
/* Which fixed buffers we are using? */
unsigned int loop_cnt; /*% records per quantum,
* 0 => all. */
bool canceled;
isc_mutex_t lock;
isc_result_t result;
/* Atomic */
isc_refcount_t references;
atomic_bool canceled;
/* locked by lock */
uint32_t references;
dns_incctx_t *inc;
uint32_t resign;
isc_stdtime_t now;
@ -389,11 +393,7 @@ dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
REQUIRE(target != NULL && *target == NULL);
REQUIRE(DNS_LCTX_VALID(source));
LOCK(&source->lock);
INSIST(source->references > 0);
source->references++;
INSIST(source->references != 0); /* Overflow? */
UNLOCK(&source->lock);
isc_refcount_increment(&source->references);
*target = source;
}
@ -401,22 +401,16 @@ dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
void
dns_loadctx_detach(dns_loadctx_t **lctxp) {
dns_loadctx_t *lctx;
bool need_destroy = false;
REQUIRE(lctxp != NULL);
lctx = *lctxp;
REQUIRE(DNS_LCTX_VALID(lctx));
LOCK(&lctx->lock);
INSIST(lctx->references > 0);
lctx->references--;
if (lctx->references == 0)
need_destroy = true;
UNLOCK(&lctx->lock);
if (need_destroy)
loadctx_destroy(lctx);
*lctxp = NULL;
if (isc_refcount_decrement(&lctx->references) == 1) {
loadctx_destroy(lctx);
}
}
static void
@ -461,7 +455,6 @@ loadctx_destroy(dns_loadctx_t *lctx) {
if (lctx->task != NULL)
isc_task_detach(&lctx->task);
isc_mutex_destroy(&lctx->lock);
mctx = NULL;
isc_mem_attach(lctx->mctx, &mctx);
isc_mem_detach(&lctx->mctx);
@ -532,7 +525,6 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
lctx = isc_mem_get(mctx, sizeof(*lctx));
if (lctx == NULL)
return (ISC_R_NOMEMORY);
isc_mutex_init(&lctx->lock);
lctx->inc = NULL;
result = incctx_create(mctx, origin, &lctx->inc);
@ -613,10 +605,12 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
isc_task_attach(task, &lctx->task);
lctx->done = done;
lctx->done_arg = done_arg;
lctx->canceled = false;
atomic_init(&lctx->canceled, false);
lctx->mctx = NULL;
isc_mem_attach(mctx, &lctx->mctx);
lctx->references = 1; /* Implicit attach. */
isc_refcount_init(&lctx->references, 1); /* Implicit attach. */
lctx->magic = DNS_LCTX_MAGIC;
*lctxp = lctx;
return (ISC_R_SUCCESS);
@ -3099,10 +3093,11 @@ load_quantum(isc_task_t *task, isc_event_t *event) {
lctx = event->ev_arg;
REQUIRE(DNS_LCTX_VALID(lctx));
if (lctx->canceled)
if (atomic_load_acquire(&lctx->canceled)) {
result = ISC_R_CANCELED;
else
} else {
result = (lctx->load)(lctx);
}
if (result == DNS_R_CONTINUE) {
event->ev_arg = lctx;
isc_task_send(task, &event);
@ -3130,9 +3125,7 @@ void
dns_loadctx_cancel(dns_loadctx_t *lctx) {
REQUIRE(DNS_LCTX_VALID(lctx));
LOCK(&lctx->lock);
lctx->canceled = true;
UNLOCK(&lctx->lock);
atomic_store_release(&lctx->canceled, true);
}
void

View file

@ -15,11 +15,13 @@
#include <stdbool.h>
#include <stdlib.h>
#include <isc/atomic.h>
#include <isc/buffer.h>
#include <isc/event.h>
#include <isc/file.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/refcount.h>
#include <isc/print.h>
#include <isc/stdio.h>
#include <isc/string.h>
@ -221,10 +223,10 @@ struct dns_dumpctx {
unsigned int magic;
isc_mem_t *mctx;
isc_mutex_t lock;
unsigned int references;
bool canceled;
bool first;
bool do_date;
isc_refcount_t references;
atomic_bool canceled;
bool first;
bool do_date;
isc_stdtime_t now;
FILE *f;
dns_db_t *db;
@ -1291,11 +1293,7 @@ dns_dumpctx_attach(dns_dumpctx_t *source, dns_dumpctx_t **target) {
REQUIRE(DNS_DCTX_VALID(source));
REQUIRE(target != NULL && *target == NULL);
LOCK(&source->lock);
INSIST(source->references > 0);
source->references++;
INSIST(source->references != 0); /* Overflow? */
UNLOCK(&source->lock);
isc_refcount_increment(&source->references);
*target = source;
}
@ -1303,7 +1301,6 @@ dns_dumpctx_attach(dns_dumpctx_t *source, dns_dumpctx_t **target) {
void
dns_dumpctx_detach(dns_dumpctx_t **dctxp) {
dns_dumpctx_t *dctx;
bool need_destroy = false;
REQUIRE(dctxp != NULL);
dctx = *dctxp;
@ -1311,14 +1308,9 @@ dns_dumpctx_detach(dns_dumpctx_t **dctxp) {
*dctxp = NULL;
LOCK(&dctx->lock);
INSIST(dctx->references != 0);
dctx->references--;
if (dctx->references == 0)
need_destroy = true;
UNLOCK(&dctx->lock);
if (need_destroy)
if (isc_refcount_decrement(&dctx->references) == 1) {
dumpctx_destroy(dctx);
}
}
dns_dbversion_t *
@ -1337,9 +1329,7 @@ void
dns_dumpctx_cancel(dns_dumpctx_t *dctx) {
REQUIRE(DNS_DCTX_VALID(dctx));
LOCK(&dctx->lock);
dctx->canceled = true;
UNLOCK(&dctx->lock);
atomic_store_release(&dctx->canceled, true);
}
static isc_result_t
@ -1421,10 +1411,11 @@ dump_quantum(isc_task_t *task, isc_event_t *event) {
REQUIRE(event != NULL);
dctx = event->ev_arg;
REQUIRE(DNS_DCTX_VALID(dctx));
if (dctx->canceled)
if (atomic_load_acquire(&dctx->canceled)) {
result = ISC_R_CANCELED;
else
} else {
result = dumptostreaminc(dctx);
}
if (result == DNS_R_CONTINUE) {
event->ev_arg = dctx;
isc_task_send(task, &event);
@ -1478,7 +1469,7 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
dctx->task = NULL;
dctx->nodes = 0;
dctx->first = true;
dctx->canceled = false;
atomic_init(&dctx->canceled, false);
dctx->file = NULL;
dctx->tmpfile = NULL;
dctx->format = format;
@ -1540,7 +1531,8 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
else if (!dns_db_iscache(db))
dns_db_currentversion(dctx->db, &dctx->version);
isc_mem_attach(mctx, &dctx->mctx);
dctx->references = 1;
isc_refcount_init(&dctx->references, 1);
dctx->magic = DNS_DCTX_MAGIC;
*dctxp = dctx;
return (ISC_R_SUCCESS);

View file

@ -133,7 +133,7 @@ dns_ntatable_create(dns_view_t *view,
ntatable->taskmgr = taskmgr;
ntatable->view = view;
ntatable->references = 1;
isc_refcount_init(&ntatable->references, 1);
ntatable->magic = NTATABLE_MAGIC;
*ntatablep = ntatable;
@ -157,20 +157,13 @@ dns_ntatable_attach(dns_ntatable_t *source, dns_ntatable_t **targetp) {
REQUIRE(VALID_NTATABLE(source));
REQUIRE(targetp != NULL && *targetp == NULL);
RWLOCK(&source->rwlock, isc_rwlocktype_write);
INSIST(source->references > 0);
source->references++;
INSIST(source->references != 0);
RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
isc_refcount_increment(&source->references);
*targetp = source;
}
void
dns_ntatable_detach(dns_ntatable_t **ntatablep) {
bool destroy = false;
dns_ntatable_t *ntatable;
REQUIRE(ntatablep != NULL && VALID_NTATABLE(*ntatablep));
@ -178,16 +171,10 @@ dns_ntatable_detach(dns_ntatable_t **ntatablep) {
ntatable = *ntatablep;
*ntatablep = NULL;
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
INSIST(ntatable->references > 0);
ntatable->references--;
if (ntatable->references == 0)
destroy = true;
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
if (destroy) {
if (isc_refcount_decrement(&ntatable->references) == 1) {
dns_rbt_destroy(&ntatable->table);
isc_rwlock_destroy(&ntatable->rwlock);
isc_refcount_destroy(&ntatable->references);
if (ntatable->task != NULL)
isc_task_detach(&ntatable->task);
ntatable->timermgr = NULL;

View file

@ -268,12 +268,15 @@ struct fetchctx {
isc_mem_t * mctx;
isc_stdtime_t now;
/* Atomic */
isc_refcount_t references;
/*% Locked by appropriate bucket lock. */
fetchstate state;
bool want_shutdown;
bool cloned;
bool spilled;
unsigned int references;
bool want_shutdown;
bool cloned;
bool spilled;
isc_event_t control_event;
ISC_LINK(struct fetchctx) link;
ISC_LIST(dns_fetchevent_t) events;
@ -434,7 +437,7 @@ typedef struct fctxbucket {
isc_task_t * task;
isc_mutex_t lock;
ISC_LIST(fetchctx_t) fctxs;
bool exiting;
atomic_bool exiting;
isc_mem_t * mctx;
} fctxbucket_t;
@ -472,7 +475,6 @@ struct dns_resolver {
unsigned int magic;
isc_mem_t * mctx;
isc_mutex_t lock;
isc_mutex_t nlock;
isc_mutex_t primelock;
dns_rdataclass_t rdclass;
isc_socketmgr_t * socketmgr;
@ -516,12 +518,14 @@ struct dns_resolver {
unsigned int retryinterval; /* in milliseconds */
unsigned int nonbackofftries;
/* Atomic */
isc_refcount_t references;
atomic_bool exiting;
/* Locked by lock. */
unsigned int references;
bool exiting;
isc_eventlist_t whenshutdown;
unsigned int activebuckets;
bool priming;
bool priming;
unsigned int spillat; /* clients-per-query */
unsigned int zspill; /* fetches-per-zone */
@ -529,8 +533,9 @@ struct dns_resolver {
/* Locked by primelock. */
dns_fetch_t * primefetch;
/* Locked by nlock. */
unsigned int nfctx;
/* Atomic. */
isc_refcount_t nfctx;
};
#define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
@ -1641,7 +1646,8 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
fctx->spilled &&
(count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
LOCK(&fctx->res->lock);
if (count == fctx->res->spillat && !fctx->res->exiting) {
if (count == fctx->res->spillat &&
!atomic_load_acquire(&fctx->res->exiting)) {
old_spillat = fctx->res->spillat;
fctx->res->spillat += 5;
if (fctx->res->spillat > fctx->res->spillatmax &&
@ -3067,7 +3073,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
} else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
if (fctx->references == 0) {
if (isc_refcount_current(&fctx->references) == 0) {
bucket_empty = fctx_unlink(fctx);
dodestroy = true;
}
@ -4282,24 +4288,26 @@ fctx_unlink(fetchctx_t *fctx) {
REQUIRE(ISC_LIST_EMPTY(fctx->finds));
REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
REQUIRE(fctx->pending == 0);
REQUIRE(fctx->references == 0);
REQUIRE(ISC_LIST_EMPTY(fctx->validators));
FCTXTRACE("unlink");
isc_refcount_destroy(&fctx->references);
res = fctx->res;
bucketnum = fctx->bucketnum;
ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
LOCK(&res->nlock);
res->nfctx--;
UNLOCK(&res->nlock);
isc_refcount_decrement(&res->nfctx);
dec_stats(res, dns_resstatscounter_nfetch);
if (res->buckets[bucketnum].exiting &&
if (atomic_load_acquire(&res->buckets[bucketnum].exiting) &&
ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
{
return (true);
}
return (false);
}
@ -4317,12 +4325,13 @@ fctx_destroy(fetchctx_t *fctx) {
REQUIRE(ISC_LIST_EMPTY(fctx->finds));
REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
REQUIRE(fctx->pending == 0);
REQUIRE(fctx->references == 0);
REQUIRE(ISC_LIST_EMPTY(fctx->validators));
REQUIRE(!ISC_LINK_LINKED(fctx, link));
FCTXTRACE("destroy");
isc_refcount_destroy(&fctx->references);
/*
* Free bad.
*/
@ -4527,8 +4536,11 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
}
if (fctx->references == 0 && fctx->pending == 0 &&
fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
if (isc_refcount_current(&fctx->references) == 0 &&
fctx->pending == 0 &&
fctx->nqueries == 0 &&
ISC_LIST_EMPTY(fctx->validators))
{
bucket_empty = fctx_unlink(fctx);
dodestroy = true;
}
@ -4577,7 +4589,7 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
INSIST(fctx->pending == 0);
INSIST(fctx->nqueries == 0);
INSIST(ISC_LIST_EMPTY(fctx->validators));
if (fctx->references == 0) {
if (isc_refcount_current(&fctx->references) == 0) {
/*
* It's now safe to destroy this fctx.
*/
@ -4669,7 +4681,9 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, const isc_sockaddr_t *client,
ISC_LIST_PREPEND(fctx->events, event, ev_link);
else
ISC_LIST_APPEND(fctx->events, event, ev_link);
fctx->references++;
fctx_increference(fctx);
fctx->client = client;
fetch->magic = DNS_FETCH_MAGIC;
@ -4762,7 +4776,7 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
* using it.
*/
fctx->res = res;
fctx->references = 0;
isc_refcount_init(&fctx->references, 0);
fctx->bucketnum = bucketnum;
fctx->dbucketnum = RES_NOBUCKET;
fctx->state = fetchstate_init;
@ -5011,9 +5025,8 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
LOCK(&res->nlock);
res->nfctx++;
UNLOCK(&res->nlock);
isc_refcount_increment(&res->nfctx);
inc_stats(res, dns_resstatscounter_nfetch);
*fctxp = fctx;
@ -5311,7 +5324,9 @@ maybe_destroy(fetchctx_t *fctx, bool locked) {
dns_validator_cancel(validator);
}
if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) {
if (isc_refcount_current(&fctx->references) == 0 &&
ISC_LIST_EMPTY(fctx->validators))
{
bucket_empty = fctx_unlink(fctx);
dodestroy = true;
}
@ -7009,9 +7024,7 @@ static void
fctx_increference(fetchctx_t *fctx) {
REQUIRE(VALID_FCTX(fctx));
LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
fctx->references++;
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
isc_refcount_increment(&fctx->references);
}
static bool
@ -7020,9 +7033,7 @@ fctx_decreference(fetchctx_t *fctx) {
REQUIRE(VALID_FCTX(fctx));
INSIST(fctx->references > 0);
fctx->references--;
if (fctx->references == 0) {
if (isc_refcount_decrement(&fctx->references) == 1) {
/*
* No one cares about the result of this fetch anymore.
*/
@ -7051,8 +7062,6 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
fetchctx_t *fctx;
isc_result_t result;
bool bucket_empty;
bool locked = false;
unsigned int bucketnum;
dns_rdataset_t nameservers;
dns_fixedname_t fixed;
dns_name_t *domain;
@ -7073,8 +7082,6 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
dns_rdataset_init(&nameservers);
bucketnum = fctx->bucketnum;
/*
* Note: fevent->rdataset must be disassociated and
* isc_event_free(&event) be called before resuming
@ -7184,23 +7191,20 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
}
fctx_done(fctx, result, __LINE__);
} else {
LOCK(&res->buckets[bucketnum].lock);
locked = true;
fctx->references++;
fctx_increference(fctx);
}
}
cleanup:
INSIST(event == NULL);
INSIST(fevent == NULL);
if (dns_rdataset_isassociated(&nameservers))
if (dns_rdataset_isassociated(&nameservers)) {
dns_rdataset_disassociate(&nameservers);
if (!locked)
LOCK(&res->buckets[bucketnum].lock);
}
bucket_empty = fctx_decreference(fctx);
UNLOCK(&res->buckets[bucketnum].lock);
if (bucket_empty)
if (bucket_empty) {
empty_bucket(res);
}
}
static inline void
@ -7359,7 +7363,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
rctx_respinit(task, devent, query, fctx, &rctx);
if (fctx->res->exiting) {
if (atomic_load_acquire(&fctx->res->exiting)) {
result = ISC_R_SHUTTINGDOWN;
FCTXTRACE("resolver shutting down");
rctx_done(&rctx, result);
@ -9395,9 +9399,7 @@ rctx_resend(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo) {
}
fctx_done(fctx, result, __LINE__);
LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
bucket_empty = fctx_decreference(fctx);
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
if (bucket_empty) {
empty_bucket(fctx->res);
}
@ -9812,16 +9814,15 @@ destroy(dns_resolver_t *res) {
unsigned int i;
alternate_t *a;
REQUIRE(res->references == 0);
REQUIRE(atomic_load(&res->references) == 0);
REQUIRE(!res->priming);
REQUIRE(res->primefetch == NULL);
RTRACE("destroy");
INSIST(res->nfctx == 0);
isc_refcount_destroy(&res->nfctx);
isc_mutex_destroy(&res->primelock);
isc_mutex_destroy(&res->nlock);
isc_mutex_destroy(&res->lock);
for (i = 0; i < res->nbuckets; i++) {
INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
@ -9910,7 +9911,7 @@ spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
UNUSED(task);
LOCK(&res->lock);
INSIST(!res->exiting);
INSIST(!atomic_load_acquire(&res->exiting));
if (res->spillat > res->spillatmin) {
res->spillat--;
logit = true;
@ -10038,7 +10039,7 @@ dns_resolver_create(dns_view_t *view,
isc_mem_setname(res->buckets[i].mctx, name, NULL);
isc_task_setname(res->buckets[i].task, name, res);
ISC_LIST_INIT(res->buckets[i].fctxs);
res->buckets[i].exiting = false;
atomic_init(&res->buckets[i].exiting, false);
buckets_created++;
}
@ -10074,16 +10075,16 @@ dns_resolver_create(dns_view_t *view,
res->querydscp4 = -1;
res->querydscp6 = -1;
res->references = 1;
res->exiting = false;
isc_refcount_init(&res->references, 1);
atomic_init(&res->exiting, false);
res->frozen = false;
ISC_LIST_INIT(res->whenshutdown);
res->priming = false;
res->primefetch = NULL;
res->nfctx = 0;
isc_refcount_init(&res->nfctx, 0);
isc_mutex_init(&res->lock);
isc_mutex_init(&res->nlock);
isc_mutex_init(&res->primelock);
task = NULL;
@ -10132,7 +10133,6 @@ dns_resolver_create(dns_view_t *view,
cleanup_primelock:
isc_mutex_destroy(&res->primelock);
isc_mutex_destroy(&res->nlock);
isc_mutex_destroy(&res->lock);
if (res->dispatches6 != NULL)
@ -10229,7 +10229,8 @@ dns_resolver_prime(dns_resolver_t *res) {
LOCK(&res->lock);
if (!res->exiting && !res->priming) {
/* XXXOND: cas needs to be used here */
if (!atomic_load_acquire(&res->exiting) && !res->priming) {
INSIST(res->primefetch == NULL);
res->priming = true;
want_priming = true;
@ -10295,13 +10296,9 @@ dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
REQUIRE(targetp != NULL && *targetp == NULL);
RRTRACE(source, "attach");
LOCK(&source->lock);
REQUIRE(!source->exiting);
INSIST(source->references > 0);
source->references++;
INSIST(source->references != 0);
UNLOCK(&source->lock);
REQUIRE(!atomic_load_acquire(&source->exiting));
isc_refcount_increment(&source->references);
*targetp = source;
}
@ -10321,7 +10318,7 @@ dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
LOCK(&res->lock);
if (res->exiting && res->activebuckets == 0) {
if (atomic_load_acquire(&res->exiting) && res->activebuckets == 0) {
/*
* We're already shutdown. Send the event.
*/
@ -10342,16 +10339,14 @@ dns_resolver_shutdown(dns_resolver_t *res) {
unsigned int i;
fetchctx_t *fctx;
isc_result_t result;
bool is_false = false;
REQUIRE(VALID_RESOLVER(res));
RTRACE("shutdown");
LOCK(&res->lock);
if (!res->exiting) {
if (atomic_compare_exchange_strong(&res->exiting, &is_false, true)) {
RTRACE("exiting");
res->exiting = true;
for (i = 0; i < res->nbuckets; i++) {
LOCK(&res->buckets[i].lock);
@ -10367,7 +10362,7 @@ dns_resolver_shutdown(dns_resolver_t *res) {
dns_dispatchset_cancelall(res->dispatches6,
res->buckets[i].task);
}
res->buckets[i].exiting = true;
atomic_store(&res->buckets[i].exiting, true);
if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
INSIST(res->activebuckets > 0);
res->activebuckets--;
@ -10381,14 +10376,11 @@ dns_resolver_shutdown(dns_resolver_t *res) {
NULL, true);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
UNLOCK(&res->lock);
}
void
dns_resolver_detach(dns_resolver_t **resp) {
dns_resolver_t *res;
bool need_destroy = false;
REQUIRE(resp != NULL);
res = *resp;
@ -10396,21 +10388,13 @@ dns_resolver_detach(dns_resolver_t **resp) {
RTRACE("detach");
LOCK(&res->lock);
INSIST(res->references > 0);
res->references--;
if (res->references == 0) {
INSIST(res->exiting && res->activebuckets == 0);
need_destroy = true;
}
UNLOCK(&res->lock);
if (need_destroy)
destroy(res);
*resp = NULL;
if (isc_refcount_decrement(&res->references) == 1) {
INSIST(atomic_load_acquire(&res->exiting));
INSIST(res->activebuckets == 0);
destroy(res);
}
}
static inline bool
@ -10599,7 +10583,7 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
UNLOCK(&res->lock);
LOCK(&res->buckets[bucketnum].lock);
if (res->buckets[bucketnum].exiting) {
if (atomic_load(&res->buckets[bucketnum].exiting)) {
result = ISC_R_SHUTTINGDOWN;
goto unlock;
}
@ -10767,11 +10751,10 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
RUNTIME_CHECK(event->fetch != fetch);
}
}
UNLOCK(&res->buckets[bucketnum].lock);
bucket_empty = fctx_decreference(fctx);
UNLOCK(&res->buckets[bucketnum].lock);
isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
*fetchp = NULL;
@ -10865,11 +10848,7 @@ dns_resolver_setlamettl(dns_resolver_t *resolver, uint32_t lame_ttl) {
unsigned int
dns_resolver_nrunning(dns_resolver_t *resolver) {
unsigned int n;
LOCK(&resolver->nlock);
n = resolver->nfctx;
UNLOCK(&resolver->nlock);
return (n);
return (isc_refcount_current(&resolver->nfctx));
}
isc_result_t

View file

@ -22,6 +22,7 @@
#include <isc/mem.h>
#include <isc/once.h>
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/region.h>
#include <isc/util.h>
@ -56,9 +57,9 @@ struct dns_sdb {
char *zone;
dns_sdbimplementation_t *implementation;
void *dbdata;
isc_mutex_t lock;
/* Locked */
unsigned int references;
/* Atomic */
isc_refcount_t references;
};
struct dns_sdblookup {
@ -69,10 +70,10 @@ struct dns_sdblookup {
ISC_LIST(isc_buffer_t) buffers;
dns_name_t *name;
ISC_LINK(dns_sdblookup_t) link;
isc_mutex_t lock;
dns_rdatacallbacks_t callbacks;
/* Locked */
unsigned int references;
/* Atomic */
isc_refcount_t references;
};
typedef struct dns_sdblookup dns_sdbnode_t;
@ -529,10 +530,7 @@ attach(dns_db_t *source, dns_db_t **targetp) {
REQUIRE(VALID_SDB(sdb));
LOCK(&sdb->lock);
REQUIRE(sdb->references > 0);
sdb->references++;
UNLOCK(&sdb->lock);
isc_refcount_increment(&sdb->references);
*targetp = source;
}
@ -552,7 +550,6 @@ destroy(dns_sdb_t *sdb) {
}
isc_mem_free(mctx, sdb->zone);
isc_mutex_destroy(&sdb->lock);
sdb->common.magic = 0;
sdb->common.impmagic = 0;
@ -566,20 +563,14 @@ destroy(dns_sdb_t *sdb) {
static void
detach(dns_db_t **dbp) {
dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
bool need_destroy = false;
REQUIRE(VALID_SDB(sdb));
LOCK(&sdb->lock);
REQUIRE(sdb->references > 0);
sdb->references--;
if (sdb->references == 0)
need_destroy = true;
UNLOCK(&sdb->lock);
if (need_destroy)
destroy(sdb);
*dbp = NULL;
if (isc_refcount_decrement(&sdb->references) == 1) {
destroy(sdb);
}
}
static isc_result_t
@ -661,9 +652,10 @@ createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
ISC_LIST_INIT(node->buffers);
ISC_LINK_INIT(node, link);
node->name = NULL;
isc_mutex_init(&node->lock);
dns_rdatacallbacks_init(&node->callbacks);
node->references = 1;
isc_refcount_init(&node->references, 1);
node->magic = SDBLOOKUP_MAGIC;
*nodep = node;
@ -702,7 +694,7 @@ destroynode(dns_sdbnode_t *node) {
dns_name_free(node->name, mctx);
isc_mem_put(mctx, node->name, sizeof(dns_name_t));
}
isc_mutex_destroy(&node->lock);
node->magic = 0;
isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
detach((dns_db_t **) (void *)&sdb);
@ -1001,11 +993,7 @@ attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
UNUSED(sdb);
LOCK(&node->lock);
INSIST(node->references > 0);
node->references++;
INSIST(node->references != 0); /* Catch overflow. */
UNLOCK(&node->lock);
isc_refcount_increment(&node->references);
*targetp = source;
}
@ -1014,7 +1002,6 @@ static void
detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
dns_sdb_t *sdb = (dns_sdb_t *)db;
dns_sdbnode_t *node;
bool need_destroy = false;
REQUIRE(VALID_SDB(sdb));
REQUIRE(targetp != NULL && *targetp != NULL);
@ -1023,17 +1010,11 @@ detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
node = (dns_sdbnode_t *)(*targetp);
LOCK(&node->lock);
INSIST(node->references > 0);
node->references--;
if (node->references == 0)
need_destroy = true;
UNLOCK(&node->lock);
if (need_destroy)
destroynode(node);
*targetp = NULL;
if (isc_refcount_decrement(&node->references) == 1) {
destroynode(node);
}
}
static isc_result_t
@ -1323,8 +1304,6 @@ dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
isc_mem_attach(mctx, &sdb->common.mctx);
isc_mutex_init(&sdb->lock);
result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
if (result != ISC_R_SUCCESS)
goto cleanup_lock;
@ -1351,7 +1330,7 @@ dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
goto cleanup_zonestr;
}
sdb->references = 1;
isc_refcount_init(&sdb->references, 1);
sdb->common.magic = DNS_DB_MAGIC;
sdb->common.impmagic = SDB_MAGIC;
@ -1365,7 +1344,6 @@ dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
cleanup_origin:
dns_name_free(&sdb->common.origin, mctx);
cleanup_lock:
isc_mutex_destroy(&sdb->lock);
isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
isc_mem_detach(&mctx);

View file

@ -98,9 +98,11 @@ struct dns_sdlz_db {
dns_db_t common;
void *dbdata;
dns_sdlzimplementation_t *dlzimp;
isc_mutex_t refcnt_lock;
/* Atomic */
isc_refcount_t references;
/* Locked */
unsigned int references;
dns_dbversion_t *future_version;
int dummy_version;
};
@ -113,10 +115,10 @@ struct dns_sdlzlookup {
ISC_LIST(isc_buffer_t) buffers;
dns_name_t *name;
ISC_LINK(dns_sdlzlookup_t) link;
isc_mutex_t lock;
dns_rdatacallbacks_t callbacks;
/* Locked */
unsigned int references;
/* Atomic */
isc_refcount_t references;
};
typedef struct dns_sdlzlookup dns_sdlznode_t;
@ -318,47 +320,33 @@ attach(dns_db_t *source, dns_db_t **targetp) {
REQUIRE(VALID_SDLZDB(sdlz));
LOCK(&sdlz->refcnt_lock);
REQUIRE(sdlz->references > 0);
sdlz->references++;
UNLOCK(&sdlz->refcnt_lock);
isc_refcount_increment(&sdlz->references);
*targetp = source;
}
static void
destroy(dns_sdlz_db_t *sdlz) {
isc_mem_t *mctx;
mctx = sdlz->common.mctx;
sdlz->common.magic = 0;
sdlz->common.impmagic = 0;
isc_mutex_destroy(&sdlz->refcnt_lock);
dns_name_free(&sdlz->common.origin, sdlz->common.mctx);
dns_name_free(&sdlz->common.origin, mctx);
isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
isc_mem_detach(&mctx);
isc_refcount_destroy(&sdlz->references);
isc_mem_putanddetach(&sdlz->common.mctx, sdlz, sizeof(dns_sdlz_db_t));
}
static void
detach(dns_db_t **dbp) {
dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
bool need_destroy = false;
REQUIRE(VALID_SDLZDB(sdlz));
LOCK(&sdlz->refcnt_lock);
REQUIRE(sdlz->references > 0);
sdlz->references--;
if (sdlz->references == 0)
need_destroy = true;
UNLOCK(&sdlz->refcnt_lock);
if (need_destroy)
destroy(sdlz);
*dbp = NULL;
if (isc_refcount_decrement(&sdlz->references) == 1) {
destroy(sdlz);
}
}
static isc_result_t
@ -476,9 +464,9 @@ createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
ISC_LIST_INIT(node->buffers);
ISC_LINK_INIT(node, link);
node->name = NULL;
isc_mutex_init(&node->lock);
dns_rdatacallbacks_init(&node->callbacks);
node->references = 1;
isc_refcount_init(&node->references, 1);
node->magic = SDLZLOOKUP_MAGIC;
*nodep = node;
@ -518,7 +506,8 @@ destroynode(dns_sdlznode_t *node) {
dns_name_free(node->name, mctx);
isc_mem_put(mctx, node->name, sizeof(dns_name_t));
}
isc_mutex_destroy(&node->lock);
isc_refcount_destroy(&node->references);
node->magic = 0;
isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
db = &sdlz->common;
@ -652,6 +641,7 @@ getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
result = ISC_R_SUCCESS;
if (result != ISC_R_SUCCESS) {
isc_refcount_decrement(&node->references);
destroynode(node);
return (result);
}
@ -665,6 +655,7 @@ getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
if (result != ISC_R_SUCCESS &&
result != ISC_R_NOTIMPLEMENTED)
{
isc_refcount_decrement(&node->references);
destroynode(node);
return (result);
}
@ -673,18 +664,9 @@ getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
if (node->name == NULL) {
node->name = isc_mem_get(sdlz->common.mctx,
sizeof(dns_name_t));
if (node->name == NULL) {
destroynode(node);
return (ISC_R_NOMEMORY);
}
dns_name_init(node->name, NULL);
result = dns_name_dup(name, sdlz->common.mctx, node->name);
if (result != ISC_R_SUCCESS) {
isc_mem_put(sdlz->common.mctx, node->name,
sizeof(dns_name_t));
destroynode(node);
return (result);
}
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
*nodep = node;
@ -734,11 +716,7 @@ attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
UNUSED(sdlz);
LOCK(&node->lock);
INSIST(node->references > 0);
node->references++;
INSIST(node->references != 0); /* Catch overflow. */
UNLOCK(&node->lock);
isc_refcount_increment(&node->references);
*targetp = source;
}
@ -747,7 +725,6 @@ static void
detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
dns_sdlznode_t *node;
bool need_destroy = false;
REQUIRE(VALID_SDLZDB(sdlz));
REQUIRE(targetp != NULL && *targetp != NULL);
@ -755,18 +732,11 @@ detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
UNUSED(sdlz);
node = (dns_sdlznode_t *)(*targetp);
LOCK(&node->lock);
INSIST(node->references > 0);
node->references--;
if (node->references == 0)
need_destroy = true;
UNLOCK(&node->lock);
if (need_destroy)
destroynode(node);
*targetp = NULL;
if (isc_refcount_decrement(&node->references) == 1) {
destroynode(node);
}
}
static isc_result_t
@ -989,7 +959,7 @@ findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
* and try again.
*/
if (i < nlabels) {
destroynode(node);
detachnode(db, &node);
node = NULL;
continue;
}
@ -1035,10 +1005,12 @@ findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
xresult = dns_name_copy(xname, foundname, NULL);
if (xresult != ISC_R_SUCCESS) {
if (node != NULL)
destroynode(node);
if (dns_rdataset_isassociated(rdataset))
if (node != NULL) {
detachnode(db, &node);
}
if (dns_rdataset_isassociated(rdataset)) {
dns_rdataset_disassociate(rdataset);
}
return (DNS_R_BADDB);
}
}
@ -1349,6 +1321,7 @@ dbiterator_destroy(dns_dbiterator_t **iteratorp) {
dns_sdlznode_t *node;
node = ISC_LIST_HEAD(sdlziter->nodelist);
ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
isc_refcount_decrement(&node->references);
destroynode(node);
}
@ -1543,9 +1516,6 @@ dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
if (result != ISC_R_SUCCESS)
goto mem_cleanup;
/* initialize the reference count mutex */
isc_mutex_init(&sdlzdb->refcnt_lock);
/* set the rest of the database structure attributes */
sdlzdb->dlzimp = imp;
sdlzdb->common.methods = &sdlzdb_methods;
@ -1553,7 +1523,7 @@ dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
sdlzdb->common.rdclass = rdclass;
sdlzdb->common.mctx = NULL;
sdlzdb->dbdata = dbdata;
sdlzdb->references = 1;
isc_refcount_init(&sdlzdb->references, 1);
/* attach to the memory context */
isc_mem_attach(mctx, &sdlzdb->common.mctx);
@ -1999,17 +1969,9 @@ dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
if (result != ISC_R_SUCCESS)
return (result);
sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
if (sdlznode->name == NULL) {
destroynode(sdlznode);
return (ISC_R_NOMEMORY);
}
dns_name_init(sdlznode->name, NULL);
result = dns_name_dup(newname, mctx, sdlznode->name);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
destroynode(sdlznode);
return (result);
}
RUNTIME_CHECK(result == ISC_R_SUCCESS);
ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
if (allnodes->origin == NULL &&
dns_name_equal(newname, &sdlz->common.origin))

View file

@ -17,6 +17,7 @@
#include <isc/mem.h>
#include <isc/netaddr.h>
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/result.h>
#include <isc/string.h>
#include <isc/util.h>
@ -51,8 +52,7 @@ struct dns_ssurule {
struct dns_ssutable {
unsigned int magic;
isc_mem_t *mctx;
unsigned int references;
isc_mutex_t lock;
isc_refcount_t references;
dns_dlzdb_t *dlzdatabase;
ISC_LIST(dns_ssurule_t) rules;
};
@ -65,10 +65,7 @@ dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) {
REQUIRE(mctx != NULL);
table = isc_mem_get(mctx, sizeof(dns_ssutable_t));
if (table == NULL)
return (ISC_R_NOMEMORY);
isc_mutex_init(&table->lock);
table->references = 1;
isc_refcount_init(&table->references, 1);
table->mctx = NULL;
isc_mem_attach(mctx, &table->mctx);
ISC_LIST_INIT(table->rules);
@ -101,7 +98,7 @@ destroy(dns_ssutable_t *table) {
rule->magic = 0;
isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
}
isc_mutex_destroy(&table->lock);
isc_refcount_destroy(&table->references);
table->magic = 0;
isc_mem_putanddetach(&table->mctx, table, sizeof(dns_ssutable_t));
}
@ -111,13 +108,7 @@ dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) {
REQUIRE(VALID_SSUTABLE(source));
REQUIRE(targetp != NULL && *targetp == NULL);
LOCK(&source->lock);
INSIST(source->references > 0);
source->references++;
INSIST(source->references != 0);
UNLOCK(&source->lock);
isc_refcount_increment(&source->references);
*targetp = source;
}
@ -125,23 +116,15 @@ dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) {
void
dns_ssutable_detach(dns_ssutable_t **tablep) {
dns_ssutable_t *table;
bool done = false;
REQUIRE(tablep != NULL);
table = *tablep;
REQUIRE(VALID_SSUTABLE(table));
LOCK(&table->lock);
INSIST(table->references > 0);
if (--table->references == 0)
done = true;
UNLOCK(&table->lock);
*tablep = NULL;
if (done)
if (isc_refcount_decrement(&table->references) == 1) {
destroy(table);
}
}
isc_result_t

View file

@ -17,6 +17,7 @@
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/refcount.h>
#include <isc/stats.h>
#include <isc/util.h>
@ -64,15 +65,11 @@ enum {
};
struct dns_stats {
/*% Unlocked */
unsigned int magic;
dns_statstype_t type;
isc_mem_t *mctx;
isc_mutex_t lock;
isc_stats_t *counters;
/*% Locked by lock */
unsigned int references;
isc_refcount_t references;
};
typedef struct rdatadumparg {
@ -99,9 +96,7 @@ dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) {
REQUIRE(DNS_STATS_VALID(stats));
REQUIRE(statsp != NULL && *statsp == NULL);
LOCK(&stats->lock);
stats->references++;
UNLOCK(&stats->lock);
isc_refcount_increment(&stats->references);
*statsp = stats;
}
@ -115,13 +110,8 @@ dns_stats_detach(dns_stats_t **statsp) {
stats = *statsp;
*statsp = NULL;
LOCK(&stats->lock);
stats->references--;
UNLOCK(&stats->lock);
if (stats->references == 0) {
if (isc_refcount_decrement(&stats->references) == 1) {
isc_stats_detach(&stats->counters);
isc_mutex_destroy(&stats->lock);
isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
}
}
@ -141,9 +131,7 @@ create_stats(isc_mem_t *mctx, dns_statstype_t type, int ncounters,
return (ISC_R_NOMEMORY);
stats->counters = NULL;
stats->references = 1;
isc_mutex_init(&stats->lock);
isc_refcount_init(&stats->references, 1);
result = isc_stats_create(mctx, &stats->counters, ncounters);
if (result != ISC_R_SUCCESS)
@ -158,7 +146,6 @@ create_stats(isc_mem_t *mctx, dns_statstype_t type, int ncounters,
return (ISC_R_SUCCESS);
clean_mutex:
isc_mutex_destroy(&stats->lock);
isc_mem_put(mctx, stats, sizeof(*stats));
return (result);

View file

@ -611,21 +611,15 @@ dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
dns_rbtnode_t *node;
dns_tsigkey_t *tkey;
dns_tsig_keyring_t *ring;
unsigned int references;
REQUIRE(ringp != NULL && *ringp != NULL);
ring = *ringp;
*ringp = NULL;
RWLOCK(&ring->lock, isc_rwlocktype_write);
INSIST(ring->references > 0);
ring->references--;
references = ring->references;
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
if (references != 0)
if (isc_refcount_decrement(&ring->references) > 1) {
return (DNS_R_CONTINUE);
}
isc_stdtime_get(&now);
dns_name_init(&foundname, NULL);
@ -1804,7 +1798,7 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
ISC_LIST_INIT(ring->lru);
isc_mem_attach(mctx, &ring->mctx);
ring->references = 1;
isc_refcount_init(&ring->references, 1);
*ringp = ring;
return (ISC_R_SUCCESS);
@ -1829,18 +1823,14 @@ dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
REQUIRE(source != NULL);
REQUIRE(target != NULL && *target == NULL);
RWLOCK(&source->lock, isc_rwlocktype_write);
INSIST(source->references > 0);
source->references++;
INSIST(source->references > 0);
isc_refcount_increment(&source->references);
*target = source;
RWUNLOCK(&source->lock, isc_rwlocktype_write);
}
void
dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
dns_tsig_keyring_t *ring;
unsigned int references;
REQUIRE(ringp != NULL);
REQUIRE(*ringp != NULL);
@ -1848,14 +1838,9 @@ dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
ring = *ringp;
*ringp = NULL;
RWLOCK(&ring->lock, isc_rwlocktype_write);
INSIST(ring->references > 0);
ring->references--;
references = ring->references;
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
if (references == 0)
if (isc_refcount_decrement(&ring->references) == 1) {
destroyring(ring);
}
}
void

View file

@ -17392,7 +17392,7 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
if (zmgr->unreachable[i].expire >= seconds &&
if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
atomic_store_relaxed(&zmgr->unreachable[i].last,

View file

@ -15,6 +15,7 @@
#include <inttypes.h>
#include <stdbool.h>
#include <isc/atomic.h>
#include <isc/file.h>
#include <isc/magic.h>
#include <isc/mem.h>
@ -45,10 +46,13 @@ struct dns_zt {
dns_zt_allloaded_t loaddone;
void * loaddone_arg;
struct zt_load_params *loadparams;
/* Atomic */
atomic_bool flush;
isc_refcount_t references;
isc_refcount_t loads_pending;
/* Locked by lock. */
bool flush;
uint32_t references;
unsigned int loads_pending;
dns_rbt_t *table;
};
@ -93,14 +97,14 @@ dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) {
zt->mctx = NULL;
isc_mem_attach(mctx, &zt->mctx);
zt->references = 1;
zt->flush = false;
isc_refcount_init(&zt->references, 1);
atomic_init(&zt->flush, false);
zt->rdclass = rdclass;
zt->magic = ZTMAGIC;
zt->loaddone = NULL;
zt->loaddone_arg = NULL;
zt->loadparams = NULL;
zt->loads_pending = 0;
isc_refcount_init(&zt->loads_pending, 0);
*ztp = zt;
return (ISC_R_SUCCESS);
@ -209,13 +213,7 @@ dns_zt_attach(dns_zt_t *zt, dns_zt_t **ztp) {
REQUIRE(VALID_ZT(zt));
REQUIRE(ztp != NULL && *ztp == NULL);
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
INSIST(zt->references > 0);
zt->references++;
INSIST(zt->references != 0);
RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
isc_refcount_increment(&zt->references);
*ztp = zt;
}
@ -228,8 +226,9 @@ flush(dns_zone_t *zone, void *uap) {
static void
zt_destroy(dns_zt_t *zt) {
if (zt->flush)
if (atomic_load_acquire(&zt->flush)) {
(void)dns_zt_apply(zt, false, NULL, flush, NULL);
}
dns_rbt_destroy(&zt->table);
isc_rwlock_destroy(&zt->rwlock);
zt->magic = 0;
@ -238,28 +237,20 @@ zt_destroy(dns_zt_t *zt) {
static void
zt_flushanddetach(dns_zt_t **ztp, bool need_flush) {
bool destroy = false;
dns_zt_t *zt;
REQUIRE(ztp != NULL && VALID_ZT(*ztp));
zt = *ztp;
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
INSIST(zt->references > 0);
zt->references--;
if (zt->references == 0)
destroy = true;
if (need_flush)
zt->flush = true;
RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
if (destroy)
zt_destroy(zt);
*ztp = NULL;
if (need_flush) {
atomic_store_release(&zt->flush, true);
}
if (isc_refcount_decrement(&zt->references) == 1) {
zt_destroy(zt);
}
}
void
@ -309,11 +300,15 @@ dns_zt_asyncload(dns_zt_t *zt, bool newonly,
}
zt->loadparams->dl = doneloading;
zt->loadparams->newonly = newonly;
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
INSIST(zt->loads_pending == 0);
INSIST(isc_refcount_current(&zt->loads_pending) == 0);
result = dns_zt_apply(zt, false, NULL, asyncload, zt);
pending = zt->loads_pending;
pending = isc_refcount_current(&zt->loads_pending);
if (pending != 0) {
zt->loaddone = alldone;
zt->loaddone_arg = arg;
@ -340,15 +335,16 @@ asyncload(dns_zone_t *zone, void *zt_) {
isc_result_t result;
struct dns_zt *zt = (dns_zt_t*) zt_;
REQUIRE(zone != NULL);
INSIST(zt->references > 0);
zt->references++;
zt->loads_pending++;
isc_refcount_increment(&zt->references);
isc_refcount_increment(&zt->loads_pending);
result = dns_zone_asyncload(zone, zt->loadparams->newonly, *zt->loadparams->dl, zt);
if (result != ISC_R_SUCCESS) {
zt->references--;
zt->loads_pending--;
INSIST(zt->references > 0);
isc_refcount_decrement(&zt->references);
isc_refcount_decrement(&zt->loads_pending);
}
return (ISC_R_SUCCESS);
}
@ -537,7 +533,6 @@ dns_zt_apply(dns_zt_t *zt, bool stop, isc_result_t *sub,
*/
static isc_result_t
doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
bool destroy = false;
dns_zt_allloaded_t alldone = NULL;
void *arg = NULL;
@ -546,28 +541,21 @@ doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
REQUIRE(VALID_ZT(zt));
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
INSIST(zt->loads_pending != 0);
INSIST(zt->references != 0);
zt->references--;
if (zt->references == 0)
destroy = true;
zt->loads_pending--;
if (zt->loads_pending == 0) {
if (isc_refcount_decrement(&zt->loads_pending) == 1) {
alldone = zt->loaddone;
arg = zt->loaddone_arg;
zt->loaddone = NULL;
zt->loaddone_arg = NULL;
isc_mem_put(zt->mctx, zt->loadparams, sizeof(struct zt_load_params));
zt->loadparams = NULL;
if (alldone != NULL) {
alldone(arg);
}
}
RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
if (alldone != NULL)
alldone(arg);
if (destroy)
if (isc_refcount_decrement(&zt->references) == 1) {
zt_destroy(zt);
}
return (ISC_R_SUCCESS);
}

View file

@ -18,6 +18,7 @@
#include <isc/counter.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/refcount.h>
#include <isc/util.h>
#define COUNTER_MAGIC ISC_MAGIC('C', 'n', 't', 'r')
@ -26,7 +27,7 @@
struct isc_counter {
unsigned int magic;
isc_mem_t *mctx;
atomic_uint_fast32_t references;
isc_refcount_t references;
atomic_uint_fast32_t limit;
atomic_uint_fast32_t used;
};
@ -44,9 +45,9 @@ isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) {
counter->mctx = NULL;
isc_mem_attach(mctx, &counter->mctx);
atomic_store(&counter->references, 1);
atomic_store(&counter->limit, limit);
atomic_store(&counter->used, 0);
isc_refcount_init(&counter->references, 1);
atomic_init(&counter->limit, limit);
atomic_init(&counter->used, 0);
counter->magic = COUNTER_MAGIC;
*counterp = counter;
@ -55,22 +56,21 @@ isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) {
isc_result_t
isc_counter_increment(isc_counter_t *counter) {
isc_result_t result = ISC_R_SUCCESS;
uint32_t used = atomic_fetch_add_relaxed(&counter->used, 1) + 1;
uint32_t limit = atomic_load_acquire(&counter->limit);
uint32_t used = atomic_fetch_add(&counter->used, 1) + 1;
if (atomic_load(&counter->limit) != 0 &&
used >= atomic_load(&counter->limit)) {
result = ISC_R_QUOTA;
if (limit != 0 && used >= limit) {
return (ISC_R_QUOTA);
}
return (result);
return (ISC_R_SUCCESS);
}
unsigned int
isc_counter_used(isc_counter_t *counter) {
REQUIRE(VALID_COUNTER(counter));
return (atomic_load(&counter->used));
return (atomic_load_acquire(&counter->used));
}
void
@ -85,7 +85,7 @@ isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) {
REQUIRE(VALID_COUNTER(source));
REQUIRE(targetp != NULL && *targetp == NULL);
INSIST(atomic_fetch_add(&source->references, 1) > 0);
isc_refcount_increment(&source->references);
*targetp = source;
}
@ -99,7 +99,6 @@ destroy(isc_counter_t *counter) {
void
isc_counter_detach(isc_counter_t **counterp) {
isc_counter_t *counter;
uint32_t oldrefs;
REQUIRE(counterp != NULL && *counterp != NULL);
counter = *counterp;
@ -107,10 +106,7 @@ isc_counter_detach(isc_counter_t **counterp) {
*counterp = NULL;
oldrefs = atomic_fetch_sub(&counter->references, 1);
INSIST(oldrefs > 0);
if (oldrefs == 1) {
if (isc_refcount_decrement(&counter->references) == 1) {
destroy(counter);
}
}

View file

@ -11,11 +11,15 @@
#pragma once
#ifdef ISC_MUTEX_ATOMICS
#include <isc/mutexatomic.h>
#else
#if HAVE_STDATOMIC_H
#include <stdatomic.h>
#else
#include <isc/stdatomic.h>
#endif
#endif
/*
* We define a few additional macros to make things easier

View file

@ -0,0 +1,132 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* 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 http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <inttypes.h>
#include <stdbool.h>
#include <isc/mutex.h>
#if !defined(__has_feature)
#define __has_feature(x) 0
#endif
#if !defined(__has_extension)
#define __has_extension(x) __has_feature(x)
#endif
#if !defined(__GNUC_PREREQ__)
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
#define __GNUC_PREREQ__(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
#define __GNUC_PREREQ__(maj, min) 0
#endif
#endif
#if !defined(__CLANG_ATOMICS) && !defined(__GNUC_ATOMICS)
#if __has_extension(c_atomic) || __has_extension(cxx_atomic)
#define __CLANG_ATOMICS
#elif __GNUC_PREREQ__(4, 7)
#define __GNUC_ATOMICS
#elif !defined(__GNUC__)
#error "isc/stdatomic.h does not support your compiler"
#endif
#endif
#ifndef __ATOMIC_RELAXED
#define __ATOMIC_RELAXED 0
#endif
#ifndef __ATOMIC_CONSUME
#define __ATOMIC_CONSUME 1
#endif
#ifndef __ATOMIC_ACQUIRE
#define __ATOMIC_ACQUIRE 2
#endif
#ifndef __ATOMIC_RELEASE
#define __ATOMIC_RELEASE 3
#endif
#ifndef __ATOMIC_ACQ_REL
#define __ATOMIC_ACQ_REL 4
#endif
#ifndef __ATOMIC_SEQ_CST
#define __ATOMIC_SEQ_CST 5
#endif
enum memory_order {
memory_order_relaxed = __ATOMIC_RELAXED,
memory_order_consume = __ATOMIC_CONSUME,
memory_order_acquire = __ATOMIC_ACQUIRE,
memory_order_release = __ATOMIC_RELEASE,
memory_order_acq_rel = __ATOMIC_ACQ_REL,
memory_order_seq_cst = __ATOMIC_SEQ_CST
};
typedef enum memory_order memory_order;
typedef struct atomic_int_fast32 {
isc_mutex_t m;
int32_t v;
} atomic_int_fast32_t;
typedef struct atomic_int_fast64 {
isc_mutex_t m;
int64_t v;
} atomic_int_fast64_t;
typedef struct atomic_uint_fast32 {
isc_mutex_t m;
uint32_t v;
} atomic_uint_fast32_t;
typedef struct atomic_uint_fast64 {
isc_mutex_t m;
uint64_t v;
} atomic_uint_fast64_t;
typedef struct atomic_bool_s {
isc_mutex_t m;
bool v;
} atomic_bool;
#define atomic_init(obj, desired) \
{ isc_mutex_init(&(obj)->m); isc_mutex_lock(&(obj)->m); (obj)->v = desired; isc_mutex_unlock(&(obj)->m); }
#define atomic_load_explicit(obj, order) \
({ typeof((obj)->v) __v; isc_mutex_lock(&(obj)->m); __v= (obj)->v; isc_mutex_unlock(&(obj)->m); __v;} )
#define atomic_store_explicit(obj, desired, order) \
{isc_mutex_lock(&(obj)->m); (obj)->v = desired; isc_mutex_unlock(&(obj)->m); }
#define atomic_fetch_add_explicit(obj, arg, order) \
({ typeof((obj)->v) __v; isc_mutex_lock(&(obj)->m); __v= (obj)->v; (obj)->v += arg; isc_mutex_unlock(&(obj)->m); __v;} )
#define atomic_fetch_sub_explicit(obj, arg, order) \
({ typeof((obj)->v) __v; isc_mutex_lock(&(obj)->m); __v= (obj)->v; (obj)->v -= arg; isc_mutex_unlock(&(obj)->m); __v;} )
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \
({ bool __v; isc_mutex_lock(&(obj)->m); __v = ((obj)->v == *expected); *expected = (obj)->v; (obj)->v = __v ? desired : (obj)->v; isc_mutex_unlock(&(obj)->m); __v;} )
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail) \
({ bool __v; isc_mutex_lock(&(obj)->m); __v = ((obj)->v == *expected); *expected = (obj)->v; (obj)->v = __v ? desired : (obj)->v; isc_mutex_unlock(&(obj)->m); __v;} )
#define atomic_load(obj) \
atomic_load_explicit(obj, memory_order_seq_cst)
#define atomic_store(obj, arg) \
atomic_store_explicit(obj, arg, memory_order_seq_cst)
#define atomic_fetch_add(obj, arg) \
atomic_fetch_add_explicit(obj, arg, memory_order_seq_cst)
#define atomic_fetch_sub(obj, arg) \
atomic_fetch_sub_explicit(obj, arg, memory_order_seq_cst)
#define atomic_compare_exchange_strong(obj, expected, desired) \
atomic_compare_exchange_strong_explicit(obj, expected, desired, memory_order_seq_cst, memory_order_seq_cst)
#define atomic_compare_exchange_weak(obj, expected, desired) \
atomic_compare_exchange_weak_explicit(obj, expected, desired, memory_order_seq_cst, memory_order_seq_cst)

View file

@ -21,27 +21,27 @@
void
isc_quota_init(isc_quota_t *quota, unsigned int max) {
atomic_store(&quota->max, max);
atomic_store(&quota->used, 0);
atomic_store(&quota->soft, 0);
atomic_init(&quota->max, max);
atomic_init(&quota->used, 0);
atomic_init(&quota->soft, 0);
}
void
isc_quota_destroy(isc_quota_t *quota) {
INSIST(atomic_load(&quota->used) == 0);
atomic_store(&quota->max, 0);
atomic_store(&quota->used, 0);
atomic_store(&quota->soft, 0);
atomic_store_release(&quota->max, 0);
atomic_store_release(&quota->used, 0);
atomic_store_release(&quota->soft, 0);
}
void
isc_quota_soft(isc_quota_t *quota, unsigned int soft) {
atomic_store(&quota->soft, soft);
atomic_store_release(&quota->soft, soft);
}
void
isc_quota_max(isc_quota_t *quota, unsigned int max) {
atomic_store(&quota->max, max);
atomic_store_release(&quota->max, max);
}
unsigned int
@ -62,9 +62,9 @@ isc_quota_getused(isc_quota_t *quota) {
isc_result_t
isc_quota_reserve(isc_quota_t *quota) {
isc_result_t result;
uint32_t max = atomic_load(&quota->max);
uint32_t soft = atomic_load(&quota->soft);
uint32_t used = atomic_fetch_add(&quota->used, 1);
uint32_t max = atomic_load_acquire(&quota->max);
uint32_t soft = atomic_load_acquire(&quota->soft);
uint32_t used = atomic_fetch_add_relaxed(&quota->used, 1);
if (max == 0 || used < max) {
if (soft == 0 || used < soft) {
result = ISC_R_SUCCESS;
@ -72,7 +72,7 @@ isc_quota_reserve(isc_quota_t *quota) {
result = ISC_R_SOFTQUOTA;
}
} else {
INSIST(atomic_fetch_sub(&quota->used, 1) > 0);
INSIST(atomic_fetch_sub_release(&quota->used, 1) > 0);
result = ISC_R_QUOTA;
}
return (result);
@ -80,7 +80,7 @@ isc_quota_reserve(isc_quota_t *quota) {
void
isc_quota_release(isc_quota_t *quota) {
INSIST(atomic_fetch_sub(&quota->used, 1) > 0);
INSIST(atomic_fetch_sub_release(&quota->used, 1) > 0);
}
static isc_result_t
@ -93,7 +93,7 @@ doattach(isc_quota_t *quota, isc_quota_t **p, bool force) {
*p = quota;
} else if (result == ISC_R_QUOTA && force) {
/* attach anyway */
atomic_fetch_add(&quota->used, 1);
atomic_fetch_add_relaxed(&quota->used, 1);
*p = quota;
result = ISC_R_SUCCESS;
}

View file

@ -37,7 +37,7 @@ typedef atomic_int_fast64_t isc_stat_t;
struct isc_stats {
unsigned int magic;
isc_mem_t *mctx;
isc_refcount_t refs;
isc_refcount_t references;
int ncounters;
isc_stat_t *counters;
};
@ -50,7 +50,7 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
stats = isc_mem_get(mctx, sizeof(*stats));
stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters);
isc_refcount_init(&stats->refs, 1);
isc_refcount_init(&stats->references, 1);
memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters);
stats->mctx = NULL;
isc_mem_attach(mctx, &stats->mctx);
@ -66,7 +66,7 @@ isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp) {
REQUIRE(ISC_STATS_VALID(stats));
REQUIRE(statsp != NULL && *statsp == NULL);
isc_refcount_increment(&stats->refs);
isc_refcount_increment(&stats->references);
*statsp = stats;
}
@ -79,7 +79,7 @@ isc_stats_detach(isc_stats_t **statsp) {
stats = *statsp;
*statsp = NULL;
if (isc_refcount_decrement(&stats->refs) == 1) {
if (isc_refcount_decrement(&stats->references) == 1) {
isc_mem_put(stats->mctx, stats->counters,
sizeof(isc_stat_t) * stats->ncounters);
isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));

View file

@ -29,6 +29,7 @@
#include <isc/print.h>
#include <isc/string.h>
#include <isc/random.h>
#include <isc/refcount.h>
#include <isc/task.h>
#include <isc/thread.h>
#include <isc/time.h>
@ -101,7 +102,7 @@ struct isc__task {
isc_mutex_t lock;
/* Locked by task lock. */
task_state_t state;
unsigned int references;
isc_refcount_t references;
isc_eventlist_t events;
isc_eventlist_t on_shutdown;
unsigned int nevents;
@ -228,7 +229,7 @@ task_finished(isc__task_t *task) {
REQUIRE(EMPTY(task->events));
REQUIRE(task->nevents == 0);
REQUIRE(EMPTY(task->on_shutdown));
REQUIRE(task->references == 0);
REQUIRE(atomic_load(&task->references) == 0);
REQUIRE(task->state == task_state_done);
XTRACE("task_finished");
@ -295,7 +296,8 @@ isc_task_create_bound(isc_taskmgr_t *manager0, unsigned int quantum,
isc_mutex_init(&task->lock);
task->state = task_state_idle;
task->references = 1;
isc_refcount_init(&task->references, 1);
INIT_LIST(task->events);
INIT_LIST(task->on_shutdown);
task->nevents = 0;
@ -345,9 +347,7 @@ isc_task_attach(isc_task_t *source0, isc_task_t **targetp) {
XTTRACE(source, "isc_task_attach");
LOCK(&source->lock);
source->references++;
UNLOCK(&source->lock);
isc_refcount_increment(&source->references);
*targetp = (isc_task_t *)source;
}
@ -420,12 +420,11 @@ task_detach(isc__task_t *task) {
* Caller must be holding the task lock.
*/
REQUIRE(task->references > 0);
XTRACE("detach");
task->references--;
if (task->references == 0 && task->state == task_state_idle) {
if (isc_refcount_decrement(&task->references) == 1 &&
task->state == task_state_idle)
{
INSIST(EMPTY(task->events));
/*
* There are no references to this task, and no
@ -1140,7 +1139,7 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
dispatch_count++;
}
if (task->references == 0 &&
if (isc_refcount_current(&task->references) == 0 &&
EMPTY(task->events) &&
!TASK_SHUTTINGDOWN(task)) {
bool was_idle;
@ -1177,7 +1176,7 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
* right now.
*/
XTRACE("empty");
if (task->references == 0 &&
if (isc_refcount_current(&task->references) == 0 &&
TASK_SHUTTINGDOWN(task)) {
/*
* The task is done.
@ -1244,7 +1243,8 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
* we're stuck. Automatically drop privileges at that
* point and continue with the regular ready queue.
*/
if (manager->mode != isc_taskmgrmode_normal &&
if (atomic_load_relaxed(&manager->mode) !=
isc_taskmgrmode_normal &&
atomic_load_explicit(&manager->tasks_running,
memory_order_acquire) == 0)
{
@ -1257,7 +1257,8 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
* we'll end up in a deadlock over queue locks.
*
*/
if (manager->mode != isc_taskmgrmode_normal &&
if (atomic_load(&manager->mode) !=
isc_taskmgrmode_normal &&
atomic_load_explicit(&manager->tasks_running,
memory_order_acquire) == 0)
{
@ -1361,10 +1362,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
manager->queues = isc_mem_get(mctx, workers * sizeof(isc__taskqueue_t));
RUNTIME_CHECK(manager->queues != NULL);
manager->tasks_running = 0;
manager->tasks_ready = 0;
manager->curq = 0;
manager->exiting = false;
atomic_init(&manager->tasks_running, 0);
atomic_init(&manager->tasks_ready, 0);
atomic_init(&manager->curq, 0);
atomic_init(&manager->exiting, false);
manager->excl = NULL;
manager->halted = 0;
atomic_store_relaxed(&manager->exclusive_req, false);
@ -1530,8 +1531,8 @@ void
isc__taskmgr_resume(isc_taskmgr_t *manager0) {
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
LOCK(&manager->halt_lock);
if (manager->pause_req) {
manager->pause_req = false;
if (atomic_load(&manager->pause_req)) {
atomic_store(&manager->pause_req, false);
while (manager->halted > 0) {
BROADCAST(&manager->halt_cond);
WAIT(&manager->halt_cond, &manager->halt_lock);
@ -1732,8 +1733,8 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, void *writer0) {
TRY0(xmlTextWriterStartElement(writer,
ISC_XMLCHAR "references"));
TRY0(xmlTextWriterWriteFormatString(writer, "%d",
task->references));
TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIuFAST32,
isc_refcount_current(&task->references)));
TRY0(xmlTextWriterEndElement(writer)); /* references */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "id"));
@ -1843,7 +1844,7 @@ isc_taskmgr_renderjson(isc_taskmgr_t *mgr0, void *tasks0) {
json_object_object_add(taskobj, "name", obj);
}
obj = json_object_new_int(task->references);
obj = json_object_new_int(isc_refcount_current(&task->references));
CHECKMEM(obj);
json_object_object_add(taskobj, "references", obj);

View file

@ -23,6 +23,7 @@
#include <isc/once.h>
#include <isc/platform.h>
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/task.h>
#include <isc/thread.h>
#include <isc/time.h>
@ -61,8 +62,8 @@ struct isc__timer {
isc_timer_t common;
isc__timermgr_t * manager;
isc_mutex_t lock;
isc_refcount_t references;
/*! Locked by timer lock. */
unsigned int references;
isc_time_t idle;
/*! Locked by manager lock. */
isc_timertype_t type;
@ -284,7 +285,7 @@ isc_timer_create(isc_timermgr_t *manager0, isc_timertype_t type,
return (ISC_R_NOMEMORY);
timer->manager = manager;
timer->references = 1;
isc_refcount_init(&timer->references, 1);
if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
result = isc_time_add(&now, interval, &timer->idle);
@ -479,10 +480,7 @@ isc_timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) {
REQUIRE(VALID_TIMER(timer));
REQUIRE(timerp != NULL && *timerp == NULL);
LOCK(&timer->lock);
timer->references++;
UNLOCK(&timer->lock);
isc_refcount_increment(&timer->references);
*timerp = (isc_timer_t *)timer;
}
@ -490,7 +488,6 @@ isc_timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) {
void
isc_timer_detach(isc_timer_t **timerp) {
isc__timer_t *timer;
bool free_timer = false;
/*
* Detach *timerp from its timer.
@ -500,15 +497,9 @@ isc_timer_detach(isc_timer_t **timerp) {
timer = (isc__timer_t *)*timerp;
REQUIRE(VALID_TIMER(timer));
LOCK(&timer->lock);
REQUIRE(timer->references > 0);
timer->references--;
if (timer->references == 0)
free_timer = true;
UNLOCK(&timer->lock);
if (free_timer)
if (isc_refcount_decrement(&timer->references) == 1) {
destroy(timer);
}
*timerp = NULL;
}

View file

@ -232,7 +232,7 @@ struct isc_socket {
/* Locked by socket lock. */
ISC_LINK(isc_socket_t) link;
unsigned int references; /* EXTERNAL references */
isc_refcount_t references; /* EXTERNAL references */
SOCKET fd; /* file handle */
int pf; /* protocol family */
char name[16];
@ -392,7 +392,8 @@ sock_dump(isc_socket_t *sock) {
printf("\n\t\tSock Dump\n");
printf("\t\tfd: %Iu\n", sock->fd);
printf("\t\treferences: %u\n", sock->references);
printf("\t\treferences: %" PRIuFAST32 "\n",
isc_refcount_current(sock->references));
printf("\t\tpending_accept: %u\n", sock->pending_accept);
printf("\t\tconnecting: %u\n", sock->pending_connect);
printf("\t\tconnected: %u\n", sock->connected);
@ -1320,7 +1321,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
return (ISC_R_NOMEMORY);
sock->magic = 0;
sock->references = 0;
isc_refcount_init(&sock->references, 0);
sock->manager = manager;
sock->type = type;
@ -1449,7 +1450,7 @@ maybe_free_socket(isc_socket_t **socketp, int lineno) {
|| sock->pending_recv > 0
|| sock->pending_send > 0
|| sock->pending_accept > 0
|| sock->references > 0
|| isc_refcount_current(sock->references) > 0
|| sock->pending_connect == 1
|| !ISC_LIST_EMPTY(sock->recv_list)
|| !ISC_LIST_EMPTY(sock->send_list)
@ -1538,11 +1539,11 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
if (result != ISC_R_SUCCESS) {
socket_log(__LINE__, sock,
NULL, EVENT,
"closed %d %d %d "
"closed %d %d %" PRIuFAST32 " "
"con_reset_fix_failed",
sock->pending_recv,
sock->pending_send,
sock->references);
isc_refcount_current(sock->references));
closesocket(sock->fd);
_set_state(sock, SOCK_CLOSED);
sock->fd = INVALID_SOCKET;
@ -1590,10 +1591,11 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
result = make_nonblock(sock->fd);
if (result != ISC_R_SUCCESS) {
socket_log(__LINE__, sock, NULL, EVENT,
"closed %d %d %d make_nonblock_failed",
sock->pending_recv, sock->pending_send,
sock->references);
"closed %d %d %" PRIuFAST32 " make_nonblock_failed",
sock->pending_recv, sock->pending_send,
isc_refcount_current(sock->references));
closesocket(sock->fd);
sock->fd = INVALID_SOCKET;
free_socket(&sock, __LINE__);
@ -1647,7 +1649,7 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
_set_state(sock, SOCK_OPEN);
sock->references = 1;
isc_refcount_init(&sock->references, 1);
*socketp = sock;
iocompletionport_update(sock);
@ -1723,9 +1725,10 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
LOCK(&sock->lock);
CONSISTENT(sock);
sock->references++;
UNLOCK(&sock->lock);
isc_refcount_increment(&sock->references);
*socketp = sock;
}
@ -1736,6 +1739,7 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
void
isc_socket_detach(isc_socket_t **socketp) {
isc_socket_t *sock;
uint32_t refs;
REQUIRE(socketp != NULL);
sock = *socketp;
@ -1743,21 +1747,21 @@ isc_socket_detach(isc_socket_t **socketp) {
LOCK(&sock->lock);
CONSISTENT(sock);
REQUIRE(sock->references > 0);
sock->references--;
references = isc_refcount_decrement(&socket->references);
socket_log(__LINE__, sock, NULL, EVENT,
"detach_socket %d %d %d",
sock->pending_recv, sock->pending_send,
sock->references);
"detach_socket %d %d %" PRIuFAST32,
sock->pending_recv, sock->pending_send,
isc_refcount_current(sock->references));
if (sock->references == 0 && sock->fd != INVALID_SOCKET) {
if (references == 1 && sock->fd != INVALID_SOCKET) {
closesocket(sock->fd);
sock->fd = INVALID_SOCKET;
_set_state(sock, SOCK_CLOSED);
}
maybe_free_socket(&sock, __LINE__);
maybe_free_socket(&sock, __LINE__); /* Also unlocks the socket lock */
*socketp = NULL;
}
@ -2415,7 +2419,7 @@ SocketIoThread(LPVOID ThreadContext) {
if (acceptdone_is_active(sock, lpo->adev)) {
closesocket(lpo->adev->newsocket->fd);
lpo->adev->newsocket->fd = INVALID_SOCKET;
lpo->adev->newsocket->references--;
isc_refcount_decrement(&lpo->adev->newsocket->references);
free_socket(&lpo->adev->newsocket, __LINE__);
lpo->adev->result = isc_result;
socket_log(__LINE__, sock, NULL, EVENT,
@ -3109,7 +3113,7 @@ isc_socket_accept(isc_socket_t *sock,
UNLOCK(&sock->lock);
return (ISC_R_SHUTTINGDOWN);
}
nsock->references++;
isc_refcount_decrement(&nsock->references);
adev->ev_sender = ntask;
adev->newsocket = nsock;
@ -3446,7 +3450,7 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
if ((task == NULL) || (task == current_task)) {
dev->newsocket->references--;
isc_refcount_decrement(&dev->newsocket->references);
closesocket(dev->newsocket->fd);
dev->newsocket->fd = INVALID_SOCKET;
free_socket(&dev->newsocket, __LINE__);
@ -3670,8 +3674,8 @@ isc_socketmgr_renderxml(isc_socketmgr_t *mgr, void *writer0)
TRY0(xmlTextWriterStartElement(writer,
ISC_XMLCHAR "references"));
TRY0(xmlTextWriterWriteFormatString(writer, "%d",
sock->references));
TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIuFAST32,
isc_refcount_current(sock->references)));
TRY0(xmlTextWriterEndElement(writer));
TRY0(xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type",
@ -3791,7 +3795,7 @@ isc_socketmgr_renderjson(isc_socketmgr_t *mgr, void *stats0) {
json_object_object_add(entry, "name", obj);
}
obj = json_object_new_int(sock->references);
obj = json_object_new_int(isc_refcount_current(&sock->references));
CHECKMEM(obj);
json_object_object_add(entry, "references", obj);

View file

@ -489,7 +489,7 @@ exit_check(ns_client_t *client) {
}
if (! (client->nsends == 0 && client->nrecvs == 0 &&
client->references == 0))
isc_refcount_current(&client->references) == 0))
{
/*
* Still waiting for I/O cancel completion.
@ -3175,7 +3175,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
client->nrecvs = 0;
client->nupdates = 0;
client->nctls = 0;
client->references = 0;
isc_refcount_init(&client->references, 0);
client->attributes = 0;
client->view = NULL;
client->dispatch = NULL;
@ -3546,26 +3546,28 @@ client_udprecv(ns_client_t *client) {
void
ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
uint32_t oldrefs;
REQUIRE(NS_CLIENT_VALID(source));
REQUIRE(targetp != NULL && *targetp == NULL);
source->references++;
oldrefs = isc_refcount_increment(&source->references);
ns_client_log(source, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
"ns_client_attach: ref = %d", source->references);
"ns_client_attach: ref = %d", oldrefs+1);
*targetp = source;
}
void
ns_client_detach(ns_client_t **clientp) {
int32_t oldrefs;
ns_client_t *client = *clientp;
oldrefs = isc_refcount_decrement(&client->references);
INSIST(oldrefs > 0);
client->references--;
INSIST(client->references >= 0);
*clientp = NULL;
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
"ns_client_detach: ref = %d", client->references);
"ns_client_detach: ref = %d", oldrefs-1);
(void)exit_check(client);
}
@ -3924,7 +3926,7 @@ ns__clientmgr_getclient(ns_clientmgr_t *manager, ns_interface_t *ifp,
INSIST(client->recursionquota == NULL);
client->dscp = ifp->dscp;
client->references++;
isc_refcount_increment(&client->references);
if (tcp) {
client->attributes |= NS_CLIENTATTR_TCP;

View file

@ -101,7 +101,7 @@ struct ns_client {
int nrecvs;
int nupdates;
int nctls;
int references;
isc_refcount_t references;
bool tcpactive;
bool needshutdown; /*
* Used by clienttest to get

View file

@ -68,7 +68,7 @@ struct ns_interface {
unsigned int magic; /*%< Magic number. */
ns_interfacemgr_t * mgr; /*%< Interface manager. */
isc_mutex_t lock;
int references; /*%< Locked */
isc_refcount_t references;
unsigned int generation; /*%< Generation number. */
isc_sockaddr_t addr; /*%< Address and port. */
unsigned int flags; /*%< Interface characteristics */

View file

@ -64,7 +64,7 @@
/*% nameserver interface manager structure */
struct ns_interfacemgr {
unsigned int magic; /*%< Magic number. */
int references;
isc_refcount_t references;
isc_mutex_t lock;
isc_mem_t * mctx; /*%< Memory context. */
ns_server_t * sctx; /*%< Server context. */
@ -253,9 +253,9 @@ ns_interfacemgr_create(isc_mem_t *mctx,
mgr->task = NULL;
if (mgr->route != NULL)
isc_task_attach(task, &mgr->task);
mgr->references = (mgr->route != NULL) ? 2 : 1;
isc_refcount_init(&mgr->references, (mgr->route != NULL) ? 2 : 1);
#else
mgr->references = 1;
isc_refcount_init(&mgr->references, 1);
#endif
mgr->magic = IFMGR_MAGIC;
*mgrp = mgr;
@ -332,27 +332,18 @@ ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
void
ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
REQUIRE(NS_INTERFACEMGR_VALID(source));
LOCK(&source->lock);
INSIST(source->references > 0);
source->references++;
UNLOCK(&source->lock);
INSIST(isc_refcount_increment(&source->references) > 0);
*target = source;
}
void
ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
isc_result_t need_destroy = false;
ns_interfacemgr_t *target = *targetp;
REQUIRE(target != NULL);
REQUIRE(NS_INTERFACEMGR_VALID(target));
LOCK(&target->lock);
REQUIRE(target->references > 0);
target->references--;
if (target->references == 0)
need_destroy = true;
UNLOCK(&target->lock);
if (need_destroy)
if (isc_refcount_decrement(&target->references) == 1) {
ns_interfacemgr_destroy(target);
}
*targetp = NULL;
}
@ -435,7 +426,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
ns_interfacemgr_attach(mgr, &ifp->mgr);
ISC_LIST_APPEND(mgr->interfaces, ifp, link);
ifp->references = 1;
isc_refcount_init(&ifp->references, 1);
ifp->magic = IFACE_MAGIC;
*ifpret = ifp;
@ -667,27 +658,18 @@ ns_interface_destroy(ns_interface_t *ifp) {
void
ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
REQUIRE(NS_INTERFACE_VALID(source));
LOCK(&source->lock);
INSIST(source->references > 0);
source->references++;
UNLOCK(&source->lock);
isc_refcount_increment(&source->references);
*target = source;
}
void
ns_interface_detach(ns_interface_t **targetp) {
isc_result_t need_destroy = false;
ns_interface_t *target = *targetp;
REQUIRE(target != NULL);
REQUIRE(NS_INTERFACE_VALID(target));
LOCK(&target->lock);
REQUIRE(target->references > 0);
target->references--;
if (target->references == 0)
need_destroy = true;
UNLOCK(&target->lock);
if (need_destroy)
if (isc_refcount_decrement(&target->references) == 1) {
ns_interface_destroy(target);
}
*targetp = NULL;
}

View file

@ -17,6 +17,7 @@
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/once.h>
#include <isc/refcount.h>
#include <isc/util.h>
#include <dns/name.h>
@ -38,8 +39,7 @@ LIBNS_EXTERNAL_DATA unsigned int ns_pps = 0U;
static isc_once_t init_once = ISC_ONCE_INIT;
static isc_mem_t *ns_g_mctx = NULL;
static bool initialize_done = false;
static isc_mutex_t reflock;
static unsigned int references = 0;
static isc_refcount_t references;
static void
initialize(void) {
@ -51,8 +51,7 @@ initialize(void) {
if (result != ISC_R_SUCCESS)
return;
isc_mutex_init(&reflock);
isc_refcount_init(&references, 0);
initialize_done = true;
return;
}
@ -73,25 +72,16 @@ ns_lib_init(void) {
if (!initialize_done)
return (ISC_R_FAILURE);
LOCK(&reflock);
references++;
UNLOCK(&reflock);
isc_refcount_increment(&references);
return (ISC_R_SUCCESS);
}
void
ns_lib_shutdown(void) {
bool cleanup_ok = false;
LOCK(&reflock);
if (--references == 0)
cleanup_ok = true;
UNLOCK(&reflock);
if (!cleanup_ok)
return;
if (ns_g_mctx != NULL)
isc_mem_detach(&ns_g_mctx);
if (isc_refcount_decrement(&references) == 1) {
if (ns_g_mctx != NULL) {
isc_mem_detach(&ns_g_mctx);
}
}
}

View file

@ -25,6 +25,7 @@
#include <isc/string.h>
#include <isc/thread.h>
#include <isc/util.h>
#include <isc/once.h>
#include <dns/adb.h>
#include <dns/badcache.h>
@ -5691,6 +5692,15 @@ recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype,
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
}
static atomic_uint_fast32_t last_soft, last_hard;
#ifdef ISC_MUTEX_ATOMICS
static isc_once_t last_once = ISC_ONCE_INIT;
static void last_init() {
atomic_init(&last_soft, 0);
atomic_init(&last_hard, 0);
}
#endif
isc_result_t
ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
@ -5738,11 +5748,13 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
}
if (result == ISC_R_SOFTQUOTA) {
static atomic_uint_fast32_t last = 0;
#ifdef ISC_MUTEX_ATOMICS
isc_once_do(&last_once, last_init);
#endif
isc_stdtime_t now;
isc_stdtime_get(&now);
if (now != atomic_load_relaxed(&last)) {
atomic_store_relaxed(&last, now);
if (now != atomic_load_relaxed(&last_soft)) {
atomic_store_relaxed(&last_soft, now);
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
"recursive-clients soft limit "
@ -5755,12 +5767,14 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
ns_client_killoldestquery(client);
result = ISC_R_SUCCESS;
} else if (result == ISC_R_QUOTA) {
static atomic_uint_fast32_t last = 0;
#ifdef ISC_MUTEX_ATOMICS
isc_once_do(&last_once, last_init);
#endif
isc_stdtime_t now;
isc_stdtime_get(&now);
if (now != atomic_load_relaxed(&last)) {
if (now != atomic_load_relaxed(&last_hard)) {
ns_server_t *sctx = client->sctx;
atomic_store_relaxed(&last, now);
atomic_store_relaxed(&last_hard, now);
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
"no more recursive clients "

View file

@ -13,6 +13,7 @@
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/refcount.h>
#include <isc/stats.h>
#include <isc/util.h>
@ -25,11 +26,8 @@ struct ns_stats {
/*% Unlocked */
unsigned int magic;
isc_mem_t *mctx;
isc_mutex_t lock;
isc_stats_t *counters;
/*% Locked by lock */
unsigned int references;
isc_refcount_t references;
};
void
@ -37,9 +35,7 @@ ns_stats_attach(ns_stats_t *stats, ns_stats_t **statsp) {
REQUIRE(NS_STATS_VALID(stats));
REQUIRE(statsp != NULL && *statsp == NULL);
LOCK(&stats->lock);
stats->references++;
UNLOCK(&stats->lock);
isc_refcount_increment(&stats->references);
*statsp = stats;
}
@ -53,13 +49,9 @@ ns_stats_detach(ns_stats_t **statsp) {
stats = *statsp;
*statsp = NULL;
LOCK(&stats->lock);
stats->references--;
UNLOCK(&stats->lock);
if (stats->references == 0) {
if (isc_refcount_decrement(&stats->references) == 1) {
isc_stats_detach(&stats->counters);
isc_mutex_destroy(&stats->lock);
isc_refcount_destroy(&stats->references);
isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
}
}
@ -72,17 +64,14 @@ ns_stats_create(isc_mem_t *mctx, int ncounters, ns_stats_t **statsp) {
REQUIRE(statsp != NULL && *statsp == NULL);
stats = isc_mem_get(mctx, sizeof(*stats));
if (stats == NULL)
return (ISC_R_NOMEMORY);
stats->counters = NULL;
stats->references = 1;
isc_mutex_init(&stats->lock);
isc_refcount_init(&stats->references, 1);
result = isc_stats_create(mctx, &stats->counters, ncounters);
if (result != ISC_R_SUCCESS)
goto clean_mutex;
if (result != ISC_R_SUCCESS) {
goto clean_mem;
}
stats->magic = NS_STATS_MAGIC;
stats->mctx = NULL;
@ -91,8 +80,7 @@ ns_stats_create(isc_mem_t *mctx, int ncounters, ns_stats_t **statsp) {
return (ISC_R_SUCCESS);
clean_mutex:
isc_mutex_destroy(&stats->lock);
clean_mem:
isc_mem_put(mctx, stats, sizeof(*stats));
return (result);

View file

@ -2182,6 +2182,7 @@
./lib/isc/include/isc/md.h C 2018,2019
./lib/isc/include/isc/mem.h C 1997,1998,1999,2000,2001,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2015,2016,2017,2018,2019
./lib/isc/include/isc/meminfo.h C 2015,2016,2018,2019
./lib/isc/include/isc/mutexatomic.h C 2019
./lib/isc/include/isc/mutexblock.h C 1999,2000,2001,2004,2005,2006,2007,2016,2018,2019
./lib/isc/include/isc/netaddr.h C 1998,1999,2000,2001,2002,2004,2005,2006,2007,2009,2015,2016,2017,2018,2019
./lib/isc/include/isc/netscope.h C 2002,2004,2005,2006,2007,2009,2016,2018,2019