mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
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:
commit
fcabb55942
40 changed files with 697 additions and 704 deletions
|
|
@ -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:
|
||||
|
|
|
|||
3
CHANGES
3
CHANGES
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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:"
|
||||
|
|
|
|||
|
|
@ -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
54
configure
vendored
|
|
@ -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
|
||||
|
|
|
|||
21
configure.ac
21
configure.ac
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
110
lib/dns/sdlz.c
110
lib/dns/sdlz.c
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
92
lib/dns/zt.c
92
lib/dns/zt.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
132
lib/isc/include/isc/mutexatomic.h
Normal file
132
lib/isc/include/isc/mutexatomic.h
Normal 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)
|
||||
|
|
@ -21,27 +21,27 @@
|
|||
|
||||
void
|
||||
isc_quota_init(isc_quota_t *quota, unsigned int max) {
|
||||
atomic_store("a->max, max);
|
||||
atomic_store("a->used, 0);
|
||||
atomic_store("a->soft, 0);
|
||||
atomic_init("a->max, max);
|
||||
atomic_init("a->used, 0);
|
||||
atomic_init("a->soft, 0);
|
||||
}
|
||||
|
||||
void
|
||||
isc_quota_destroy(isc_quota_t *quota) {
|
||||
INSIST(atomic_load("a->used) == 0);
|
||||
atomic_store("a->max, 0);
|
||||
atomic_store("a->used, 0);
|
||||
atomic_store("a->soft, 0);
|
||||
atomic_store_release("a->max, 0);
|
||||
atomic_store_release("a->used, 0);
|
||||
atomic_store_release("a->soft, 0);
|
||||
}
|
||||
|
||||
void
|
||||
isc_quota_soft(isc_quota_t *quota, unsigned int soft) {
|
||||
atomic_store("a->soft, soft);
|
||||
atomic_store_release("a->soft, soft);
|
||||
}
|
||||
|
||||
void
|
||||
isc_quota_max(isc_quota_t *quota, unsigned int max) {
|
||||
atomic_store("a->max, max);
|
||||
atomic_store_release("a->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("a->max);
|
||||
uint32_t soft = atomic_load("a->soft);
|
||||
uint32_t used = atomic_fetch_add("a->used, 1);
|
||||
uint32_t max = atomic_load_acquire("a->max);
|
||||
uint32_t soft = atomic_load_acquire("a->soft);
|
||||
uint32_t used = atomic_fetch_add_relaxed("a->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("a->used, 1) > 0);
|
||||
INSIST(atomic_fetch_sub_release("a->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("a->used, 1) > 0);
|
||||
INSIST(atomic_fetch_sub_release("a->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("a->used, 1);
|
||||
atomic_fetch_add_relaxed("a->used, 1);
|
||||
*p = quota;
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
28
lib/ns/lib.c
28
lib/ns/lib.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue