Compare commits

...

9 Commits

Author SHA1 Message Date
Witold Kręcicki
074afd291b Special, for-tests-only, mode with atomics emulated by a mutex-locked variable - useful for finding atomics congestions 2019-07-08 12:32:46 +02:00
Witold Kręcicki
3a99a83517 Properly initialize all atomic variables 2019-07-08 12:32:46 +02:00
Witold Kręcicki
7f602075bd Test: rbtdb: increase node lock count 2019-07-08 12:32:46 +02:00
Witold Kręcicki
75d60b04a8 isc/stats: use isc_refcount_t 2019-07-08 12:32:11 +02:00
Witold Kręcicki
0520dcafdb isc/timer: use isc_refcount_t 2019-07-08 12:32:11 +02:00
Witold Kręcicki
15e45ec5e0 lib/isc/task: use isc_refcount_t 2019-07-08 12:32:11 +02:00
Witold Kręcicki
d304f09f53 dns/zt.c: use isc_refcount_t for reference counting 2019-07-08 12:24:57 +02:00
Witold Kręcicki
0ce7879b35 interfacemgr: use isc_refcount_t for reference counting 2019-07-08 12:24:57 +02:00
Witold Kręcicki
9ad2b15b13 Make portentry->refs an isc_refcount_t 2019-07-08 12:24:57 +02:00
16 changed files with 297 additions and 144 deletions

View File

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

54
configure vendored
View File

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

View File

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

View File

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

View File

@@ -310,7 +310,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
(((header)->rdh_ttl > (now)) || \
((header)->rdh_ttl == (now) && ZEROTTL(header)))
#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
#define DEFAULT_NODE_LOCK_COUNT 31 /*%< Should be prime. */
#define RBTDB_GLUE_TABLE_INIT_SIZE 2U
/*%
@@ -330,7 +330,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
#define DEFAULT_CACHE_NODE_LOCK_COUNT DNS_RBTDB_CACHE_NODE_LOCK_COUNT
#endif
#else
#define DEFAULT_CACHE_NODE_LOCK_COUNT 16
#define DEFAULT_CACHE_NODE_LOCK_COUNT 64
#endif /* DNS_RBTDB_CACHE_NODE_LOCK_COUNT */
typedef struct {

View File

@@ -45,9 +45,9 @@ struct dns_zt {
dns_zt_allloaded_t loaddone;
void * loaddone_arg;
struct zt_load_params *loadparams;
isc_refcount_t references;
/* Locked by lock. */
bool flush;
uint32_t references;
unsigned int loads_pending;
dns_rbt_t *table;
};
@@ -93,7 +93,7 @@ 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;
isc_refcount_init(&zt->references, 1);
zt->flush = false;
zt->rdclass = rdclass;
zt->magic = ZTMAGIC;
@@ -209,13 +209,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;
}
@@ -238,26 +232,17 @@ 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)
if (need_flush) {
zt->flush = true;
RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
if (destroy)
}
if (isc_refcount_decrement(&zt->references) == 1) {
zt_destroy(zt);
}
*ztp = NULL;
}
@@ -340,15 +325,13 @@ 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++;
INSIST(isc_refcount_increment(&zt->references) > 0);
zt->loads_pending++;
result = dns_zone_asyncload(zone, zt->loadparams->newonly, *zt->loadparams->dl, zt);
if (result != ISC_R_SUCCESS) {
zt->references--;
INSIST(isc_refcount_decrement(&zt->references) > 1);
zt->loads_pending--;
INSIST(zt->references > 0);
}
return (ISC_R_SUCCESS);
}
@@ -548,10 +531,9 @@ doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
INSIST(zt->loads_pending != 0);
INSIST(zt->references != 0);
zt->references--;
if (zt->references == 0)
if (isc_refcount_decrement(&zt->references) == 1) {
destroy = true;
}
zt->loads_pending--;
if (zt->loads_pending == 0) {
alldone = zt->loaddone;

View File

@@ -44,9 +44,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);
atomic_init(&counter->references, 1);
atomic_init(&counter->limit, limit);
atomic_init(&counter->used, 0);
counter->magic = COUNTER_MAGIC;
*counterp = counter;

View File

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

View File

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

View File

@@ -45,13 +45,16 @@ struct isc_stats {
static isc_result_t
create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
isc_stats_t *stats;
int i;
REQUIRE(statsp != NULL && *statsp == NULL);
stats = isc_mem_get(mctx, sizeof(*stats));
stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters);
isc_refcount_init(&stats->refs, 1);
memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters);
for (i = 0; i < ncounters; i++) {
atomic_init(&stats->counters[i], 0);
}
stats->mctx = NULL;
isc_mem_attach(mctx, &stats->mctx);
stats->ncounters = ncounters;

View File

@@ -29,6 +29,7 @@
#include <isc/print.h>
#include <isc/string.h>
#include <isc/random.h>
#include <isc/refcount.h>
#include <isc/task.h>
#include <isc/thread.h>
#include <isc/time.h>
@@ -99,9 +100,9 @@ struct isc__task {
isc_task_t common;
isc__taskmgr_t * manager;
isc_mutex_t lock;
isc_refcount_t references;
/* Locked by task lock. */
task_state_t state;
unsigned int 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(isc_refcount_current(&task->references) == 0);
REQUIRE(task->state == task_state_done);
XTRACE("task_finished");
@@ -295,7 +296,7 @@ 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 +346,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 +419,12 @@ task_detach(isc__task_t *task) {
* Caller must be holding the task lock.
*/
REQUIRE(task->references > 0);
REQUIRE(isc_refcount_current(&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,7 @@ 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 +1256,7 @@ 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_relaxed(&manager->mode) != isc_taskmgrmode_normal &&
atomic_load_explicit(&manager->tasks_running,
memory_order_acquire) == 0)
{
@@ -1342,7 +1341,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
RUNTIME_CHECK(manager != NULL);
manager->common.impmagic = TASK_MANAGER_MAGIC;
manager->common.magic = ISCAPI_TASKMGR_MAGIC;
atomic_store(&manager->mode, isc_taskmgrmode_normal);
atomic_init(&manager->mode, isc_taskmgrmode_normal);
manager->mctx = NULL;
isc_mutex_init(&manager->lock);
isc_mutex_init(&manager->excl_lock);
@@ -1357,18 +1356,18 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
}
manager->default_quantum = default_quantum;
INIT_LIST(manager->tasks);
atomic_store(&manager->tasks_count, 0);
atomic_init(&manager->tasks_count, 0);
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);
atomic_store_relaxed(&manager->pause_req, false);
atomic_init(&manager->exclusive_req, false);
atomic_init(&manager->pause_req, false);
isc_mem_attach(mctx, &manager->mctx);
@@ -1530,8 +1529,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_relaxed(&manager->pause_req)) {
atomic_store_relaxed(&manager->pause_req, false);
while (manager->halted > 0) {
BROADCAST(&manager->halt_cond);
WAIT(&manager->halt_cond, &manager->halt_lock);
@@ -1732,8 +1731,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, "%lu",
isc_refcount_current(&task->references)));
TRY0(xmlTextWriterEndElement(writer)); /* references */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "id"));
@@ -1843,7 +1842,7 @@ isc_taskmgr_renderjson(isc_taskmgr_t *mgr0, void *tasks0) {
json_object_object_add(taskobj, "name", obj);
}
obj = json_object_new_int(task->references);
obj = json_object_new_int(isc_refcount_current(&task->references));
CHECKMEM(obj);
json_object_object_add(taskobj, "references", obj);

View File

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

View File

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

View File

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

View File

@@ -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>
@@ -5738,7 +5739,12 @@ 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;
static atomic_uint_fast32_t last;
static isc_once_t once = ISC_ONCE_INIT;
void __ain() {
atomic_init(&last, 0);
}
isc_once_do(&once, __ain);
isc_stdtime_t now;
isc_stdtime_get(&now);
if (now != atomic_load_relaxed(&last)) {
@@ -5755,7 +5761,12 @@ 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;
static atomic_uint_fast32_t last;
static isc_once_t once = ISC_ONCE_INIT;
void __ain() {
atomic_init(&last, 0);
}
isc_once_do(&once, __ain);
isc_stdtime_t now;
isc_stdtime_get(&now);
if (now != atomic_load_relaxed(&last)) {

View File

@@ -13,6 +13,7 @@
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/refcount.h>
#include <isc/stats.h>
#include <isc/util.h>
@@ -22,14 +23,10 @@
#define NS_STATS_VALID(x) ISC_MAGIC_VALID(x, NS_STATS_MAGIC)
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 +34,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 +48,8 @@ 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_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
}
}
@@ -76,9 +66,7 @@ ns_stats_create(isc_mem_t *mctx, int ncounters, ns_stats_t **statsp) {
return (ISC_R_NOMEMORY);
stats->counters = NULL;
stats->references = 1;
isc_mutex_init(&stats->lock);
atomic_init(&stats->references, 1);
result = isc_stats_create(mctx, &stats->counters, ncounters);
if (result != ISC_R_SUCCESS)
@@ -92,7 +80,6 @@ ns_stats_create(isc_mem_t *mctx, int ncounters, ns_stats_t **statsp) {
return (ISC_R_SUCCESS);
clean_mutex:
isc_mutex_destroy(&stats->lock);
isc_mem_put(mctx, stats, sizeof(*stats));
return (result);