Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3aff66a8cd | ||
|
|
f3804430cc | ||
|
|
f4b4895b8b | ||
|
|
93ebd46780 | ||
|
|
dcc084abda | ||
|
|
46940f248a | ||
|
|
32ed003f03 | ||
|
|
9536b45ae1 | ||
|
|
53961b6b2b | ||
|
|
e4d96e53eb | ||
|
|
99c692e6b6 | ||
|
|
bf642660c9 | ||
|
|
87f9d22ae0 | ||
|
|
d85d74f993 | ||
|
|
bdfece8011 | ||
|
|
1a83111379 | ||
|
|
3d487d5f52 | ||
|
|
670f50c6bf | ||
|
|
297c75a6aa | ||
|
|
662738e981 | ||
|
|
d28f4765a9 |
+1
-1
@@ -115,7 +115,7 @@ stages:
|
||||
- test -w "${CCACHE_DIR}" && export PATH="/usr/lib/ccache:${PATH}"
|
||||
# - ./autogen.sh
|
||||
script:
|
||||
- ./configure --enable-developer --with-libtool --disable-static --with-atf=/usr --prefix=$HOME/.local $EXTRA_CONFIGURE || cat config.log
|
||||
- ./configure --enable-developer --with-libtool --disable-static --with-atf=/usr --prefix=$HOME/.local --without-make-clean $EXTRA_CONFIGURE || cat config.log
|
||||
- make -j${PARALLEL_JOBS_BUILD:-1} -k all V=1
|
||||
artifacts:
|
||||
expire_in: '1 hour'
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
5023. [func] Replace custom assembly for atomic operations with
|
||||
atomic support from the compiler. The code will now use
|
||||
C11 stdatomic, or __atomic, or __sync builtins with GCC
|
||||
or Clang compilers, and Interlocked functions with MSVC.
|
||||
[GL #10]
|
||||
|
||||
5022. [doc] Update ms-self, ms-subdomain, krb5-self, and
|
||||
krb5-subdomain documentation. [GL !708]
|
||||
|
||||
|
||||
+25
-29
@@ -9143,7 +9143,6 @@ view_loaded(void *arg) {
|
||||
ns_zoneload_t *zl = (ns_zoneload_t *) arg;
|
||||
named_server_t *server = zl->server;
|
||||
bool reconfig = zl->reconfig;
|
||||
unsigned int refs;
|
||||
|
||||
|
||||
/*
|
||||
@@ -9154,35 +9153,34 @@ view_loaded(void *arg) {
|
||||
* We use the zoneload reference counter to let us
|
||||
* know when all views are finished.
|
||||
*/
|
||||
isc_refcount_decrement(&zl->refs, &refs);
|
||||
if (refs != 0)
|
||||
return (ISC_R_SUCCESS);
|
||||
if (isc_refcount_decrement(&zl->refs) == 1) {
|
||||
|
||||
isc_refcount_destroy(&zl->refs);
|
||||
isc_mem_put(server->mctx, zl, sizeof (*zl));
|
||||
isc_refcount_destroy(&zl->refs);
|
||||
isc_mem_put(server->mctx, zl, sizeof (*zl));
|
||||
|
||||
/*
|
||||
* To maintain compatibility with log parsing tools that might
|
||||
* be looking for this string after "rndc reconfig", we keep it
|
||||
* as it is
|
||||
*/
|
||||
if (reconfig) {
|
||||
/*
|
||||
* To maintain compatibility with log parsing tools that might
|
||||
* be looking for this string after "rndc reconfig", we keep it
|
||||
* as it is
|
||||
*/
|
||||
if (reconfig) {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
|
||||
"any newly configured zones are now loaded");
|
||||
} else {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
|
||||
"all zones loaded");
|
||||
}
|
||||
|
||||
CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr),
|
||||
"forcing zone maintenance");
|
||||
|
||||
named_os_started();
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
|
||||
"any newly configured zones are now loaded");
|
||||
} else {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
|
||||
"all zones loaded");
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, "running");
|
||||
}
|
||||
|
||||
CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr),
|
||||
"forcing zone maintenance");
|
||||
|
||||
named_os_started();
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, "running");
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -9191,7 +9189,6 @@ load_zones(named_server_t *server, bool init, bool reconfig) {
|
||||
isc_result_t result;
|
||||
dns_view_t *view;
|
||||
ns_zoneload_t *zl;
|
||||
unsigned int refs = 0;
|
||||
|
||||
zl = isc_mem_get(server->mctx, sizeof (*zl));
|
||||
if (zl == NULL)
|
||||
@@ -9230,13 +9227,12 @@ load_zones(named_server_t *server, bool init, bool reconfig) {
|
||||
* 'dns_view_asyncload' calls view_loaded if there are no
|
||||
* zones.
|
||||
*/
|
||||
isc_refcount_increment(&zl->refs, NULL);
|
||||
isc_refcount_increment(&zl->refs);
|
||||
CHECK(dns_view_asyncload(view, view_loaded, zl));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
isc_refcount_decrement(&zl->refs, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&zl->refs) == 1) {
|
||||
isc_refcount_destroy(&zl->refs);
|
||||
isc_mem_put(server->mctx, zl, sizeof (*zl));
|
||||
} else if (init) {
|
||||
|
||||
@@ -72,7 +72,7 @@ attach(dns_db_t *source, dns_db_t **targetp) {
|
||||
|
||||
REQUIRE(VALID_SAMPLEDB(sampledb));
|
||||
|
||||
isc_refcount_increment(&sampledb->refs, NULL);
|
||||
isc_refcount_increment(&sampledb->refs);
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
@@ -88,13 +88,12 @@ free_sampledb(sampledb_t *sampledb) {
|
||||
static void
|
||||
detach(dns_db_t **dbp) {
|
||||
sampledb_t *sampledb = (sampledb_t *)(*dbp);
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(VALID_SAMPLEDB(sampledb));
|
||||
|
||||
isc_refcount_decrement(&sampledb->refs, &refs);
|
||||
if (refs == 0)
|
||||
if (isc_refcount_decrement(&sampledb->refs) == 1) {
|
||||
free_sampledb(sampledb);
|
||||
}
|
||||
*dbp = NULL;
|
||||
}
|
||||
|
||||
@@ -773,7 +772,7 @@ create_db(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
|
||||
|
||||
CHECK(dns_name_dupwithoffsets(origin, mctx, &sampledb->common.origin));
|
||||
|
||||
CHECK(isc_refcount_init(&sampledb->refs, 1));
|
||||
isc_refcount_init(&sampledb->refs, 1);
|
||||
|
||||
/* Translate instance name to instance pointer. */
|
||||
sampledb->inst = driverarg;
|
||||
|
||||
+3
-3
@@ -194,6 +194,9 @@ int sigwait(const unsigned int *set, int *sig);
|
||||
/* Define to 1 if you have the `chroot' function. */
|
||||
#undef HAVE_CHROOT
|
||||
|
||||
/* Define to 1 if you have the <ck_pr.h> header file. */
|
||||
#undef HAVE_CK_PR_H
|
||||
|
||||
/* Define if clock_gettime is available. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
@@ -593,9 +596,6 @@ int sigwait(const unsigned int *set, int *sig);
|
||||
your system. */
|
||||
#undef PTHREAD_CREATE_JOINABLE
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#undef SIZEOF_VOID_P
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
|
||||
@@ -707,17 +707,6 @@ DNSTAP
|
||||
FSTRM_CAPTURE
|
||||
PROTOC_C
|
||||
ISC_PLATFORM_BUSYWAITNOP
|
||||
ISC_ARCH_DIR
|
||||
ISC_PLATFORM_USEMACASM
|
||||
ISC_PLATFORM_USESTDASM
|
||||
ISC_PLATFORM_USEOSFASM
|
||||
ISC_PLATFORM_USEGCCASM
|
||||
ISC_PLATFORM_HAVEATOMICSTOREQ
|
||||
ISC_PLATFORM_HAVEATOMICSTORE
|
||||
ISC_PLATFORM_HAVECMPXCHG
|
||||
ISC_PLATFORM_HAVEXADDQ
|
||||
ISC_PLATFORM_HAVEXADD
|
||||
ISC_PLATFORM_HAVESTDATOMIC
|
||||
ISC_PLATFORM_HAVEIFNAMETOINDEX
|
||||
ISC_PLATFORM_HAVESTRINGSH
|
||||
ISC_PLATFORM_BRACEPTHREADONCEINIT
|
||||
@@ -786,6 +775,8 @@ MKDEPCC
|
||||
ZLIB
|
||||
JSONSTATS
|
||||
XMLSTATS
|
||||
CK_LIBS
|
||||
CK_CFLAGS
|
||||
NZDTARGETS
|
||||
NZDSRCS
|
||||
NZD_TOOLS
|
||||
@@ -967,6 +958,7 @@ enable_native_pkcs11
|
||||
with_pkcs11
|
||||
with_gssapi
|
||||
with_lmdb
|
||||
with_ck
|
||||
with_libxml2
|
||||
with_libjson
|
||||
with_zlib
|
||||
@@ -984,7 +976,6 @@ enable_isc_spnego
|
||||
enable_chroot
|
||||
enable_linux_caps
|
||||
with_rlimtype
|
||||
enable_atomic
|
||||
enable_fixed_rrset
|
||||
enable_rpz_nsip
|
||||
enable_rpz_nsdname
|
||||
@@ -1028,6 +1019,8 @@ PKG_CONFIG_PATH
|
||||
PKG_CONFIG_LIBDIR
|
||||
OPENSSL_CFLAGS
|
||||
OPENSSL_LIBS
|
||||
CK_CFLAGS
|
||||
CK_LIBS
|
||||
LIBIDN2_CFLAGS
|
||||
LIBIDN2_LIBS
|
||||
CMOCKA_CFLAGS
|
||||
@@ -1674,8 +1667,6 @@ Optional Features:
|
||||
--disable-isc-spnego use SPNEGO from GSSAPI library
|
||||
--disable-chroot disable chroot
|
||||
--disable-linux-caps disable Linux capabilities
|
||||
--enable-atomic enable machine specific atomic operations
|
||||
[default=autodetect]
|
||||
--enable-fixed-rrset enable fixed rrset ordering [default=no]
|
||||
--disable-rpz-nsip disable rpz nsip rules [default=enabled]
|
||||
--disable-rpz-nsdname disable rpz nsdname rules [default=enabled]
|
||||
@@ -1715,6 +1706,7 @@ Optional Packages:
|
||||
Specify path for system-supplied GSSAPI
|
||||
[default=yes]
|
||||
--with-lmdb=PATH build with LMDB library [yes|no|path]
|
||||
--with-ck=PATH specify path to Concurrency Kit
|
||||
--with-libxml2=PATH build with libxml2 library [yes|no|path]
|
||||
--with-libjson=PATH build with libjson0 library [yes|no|path]
|
||||
--with-zlib=PATH build with zlib for HTTP compression [default=yes]
|
||||
@@ -1773,6 +1765,8 @@ Some influential environment variables:
|
||||
C compiler flags for OPENSSL, overriding pkg-config
|
||||
OPENSSL_LIBS
|
||||
linker flags for OPENSSL, overriding pkg-config
|
||||
CK_CFLAGS C compiler flags for CK, overriding pkg-config
|
||||
CK_LIBS linker flags for CK, overriding pkg-config
|
||||
LIBIDN2_CFLAGS
|
||||
C compiler flags for LIBIDN2, overriding pkg-config
|
||||
LIBIDN2_LIBS
|
||||
@@ -2267,189 +2261,6 @@ $as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_type
|
||||
|
||||
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
|
||||
# --------------------------------------------
|
||||
# Tries to find the compile-time value of EXPR in a program that includes
|
||||
# INCLUDES, setting VAR accordingly. Returns whether the value could be
|
||||
# computed
|
||||
ac_fn_c_compute_int ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
if test "$cross_compiling" = yes; then
|
||||
# Depending upon the size, compute the lo and hi bounds.
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
int
|
||||
main ()
|
||||
{
|
||||
static int test_array [1 - 2 * !(($2) >= 0)];
|
||||
test_array [0] = 0;
|
||||
return test_array [0];
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_lo=0 ac_mid=0
|
||||
while :; do
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
int
|
||||
main ()
|
||||
{
|
||||
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
|
||||
test_array [0] = 0;
|
||||
return test_array [0];
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_hi=$ac_mid; break
|
||||
else
|
||||
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
|
||||
if test $ac_lo -le $ac_mid; then
|
||||
ac_lo= ac_hi=
|
||||
break
|
||||
fi
|
||||
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
done
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
int
|
||||
main ()
|
||||
{
|
||||
static int test_array [1 - 2 * !(($2) < 0)];
|
||||
test_array [0] = 0;
|
||||
return test_array [0];
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_hi=-1 ac_mid=-1
|
||||
while :; do
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
int
|
||||
main ()
|
||||
{
|
||||
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
|
||||
test_array [0] = 0;
|
||||
return test_array [0];
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_lo=$ac_mid; break
|
||||
else
|
||||
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
|
||||
if test $ac_mid -le $ac_hi; then
|
||||
ac_lo= ac_hi=
|
||||
break
|
||||
fi
|
||||
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
done
|
||||
else
|
||||
ac_lo= ac_hi=
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
# Binary search between lo and hi bounds.
|
||||
while test "x$ac_lo" != "x$ac_hi"; do
|
||||
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
int
|
||||
main ()
|
||||
{
|
||||
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
|
||||
test_array [0] = 0;
|
||||
return test_array [0];
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_hi=$ac_mid
|
||||
else
|
||||
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
done
|
||||
case $ac_lo in #((
|
||||
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
|
||||
'') ac_retval=1 ;;
|
||||
esac
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
static long int longval () { return $2; }
|
||||
static unsigned long int ulongval () { return $2; }
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
FILE *f = fopen ("conftest.val", "w");
|
||||
if (! f)
|
||||
return 1;
|
||||
if (($2) < 0)
|
||||
{
|
||||
long int i = longval ();
|
||||
if (i != ($2))
|
||||
return 1;
|
||||
fprintf (f, "%ld", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long int i = ulongval ();
|
||||
if (i != ($2))
|
||||
return 1;
|
||||
fprintf (f, "%lu", i);
|
||||
}
|
||||
/* Do not output a trailing newline, as this causes \r\n confusion
|
||||
on some platforms. */
|
||||
return ferror (f) || fclose (f) != 0;
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_run "$LINENO"; then :
|
||||
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
|
||||
else
|
||||
ac_retval=1
|
||||
fi
|
||||
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
|
||||
conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
rm -f conftest.val
|
||||
|
||||
fi
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_c_compute_int
|
||||
cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
@@ -17046,6 +16857,202 @@ fi
|
||||
|
||||
|
||||
|
||||
# Search for Concurrency Kit
|
||||
|
||||
|
||||
# Check whether --with-ck was given.
|
||||
if test "${with_ck+set}" = set; then :
|
||||
withval=$with_ck; :
|
||||
else
|
||||
with_ck=yes
|
||||
fi
|
||||
|
||||
case $with_ck in #(
|
||||
no) :
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error $? "Concurrency Kit is mandatory
|
||||
See \`config.log' for more details" "$LINENO" 5; } ;; #(
|
||||
yes) :
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ck" >&5
|
||||
$as_echo_n "checking for ck... " >&6; }
|
||||
|
||||
if test -n "$CK_CFLAGS"; then
|
||||
pkg_cv_CK_CFLAGS="$CK_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ck\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "ck") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_CK_CFLAGS=`$PKG_CONFIG --cflags "ck" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$CK_LIBS"; then
|
||||
pkg_cv_CK_LIBS="$CK_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ck\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "ck") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_CK_LIBS=`$PKG_CONFIG --libs "ck" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
CK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "ck" 2>&1`
|
||||
else
|
||||
CK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "ck" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$CK_PKG_ERRORS" >&5
|
||||
|
||||
as_fn_error $? "Package requirements (ck) were not met:
|
||||
|
||||
$CK_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
Alternatively, you may set the environment variables CK_CFLAGS
|
||||
and CK_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details." "$LINENO" 5
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
Alternatively, you may set the environment variables CK_CFLAGS
|
||||
and CK_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
|
||||
See \`config.log' for more details" "$LINENO" 5; }
|
||||
else
|
||||
CK_CFLAGS=$pkg_cv_CK_CFLAGS
|
||||
CK_LIBS=$pkg_cv_CK_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
fi ;; #(
|
||||
*) :
|
||||
|
||||
save_CFLAGS="$CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS -I$with_ck/include"
|
||||
LIBS="$LIBS -L$with_ck/lib"
|
||||
for ac_header in ck_pr.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "ck_pr.h" "ac_cv_header_ck_pr_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_ck_pr_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_CK_PR_H 1
|
||||
_ACEOF
|
||||
:
|
||||
else
|
||||
as_fn_error $? "ck_pr.h not found; Concurrency Kit is mandatory" "$LINENO" 5
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ck_array_init" >&5
|
||||
$as_echo_n "checking for library containing ck_array_init... " >&6; }
|
||||
if ${ac_cv_search_ck_array_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char ck_array_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return ck_array_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' ck; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_ck_array_init=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_ck_array_init+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_ck_array_init+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_ck_array_init=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ck_array_init" >&5
|
||||
$as_echo "$ac_cv_search_ck_array_init" >&6; }
|
||||
ac_res=$ac_cv_search_ck_array_init
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
CK_CFLAGS="-I$with_ck/include"
|
||||
CK_LIBS="-Wl,-rpath,$with_ck/lib -L$with_ck/lib -lck"
|
||||
|
||||
else
|
||||
as_fn_error $? "Concurrency Kit is mandatory" "$LINENO" 5
|
||||
fi
|
||||
;; #(
|
||||
*) :
|
||||
;;
|
||||
esac
|
||||
|
||||
CFLAGS="$CFLAGS $CK_CFLAGS"
|
||||
LIBS="$LIBS $CK_LIBS"
|
||||
|
||||
#
|
||||
# was --with-libxml2 specified?
|
||||
#
|
||||
@@ -19744,389 +19751,6 @@ fi
|
||||
done
|
||||
|
||||
|
||||
#
|
||||
# Machine architecture dependent features
|
||||
#
|
||||
have_stdatomic=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for usable stdatomic.h" >&5
|
||||
$as_echo_n "checking for usable stdatomic.h... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
atomic_int_fast32_t val = 0; atomic_fetch_add_explicit(&val, 1, memory_order_relaxed);
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
have_stdatomic=yes
|
||||
ISC_PLATFORM_HAVESTDATOMIC="#define ISC_PLATFORM_HAVESTDATOMIC 1"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
have_stdatomic=no
|
||||
ISC_PLATFORM_HAVESTDATOMIC="#undef ISC_PLATFORM_HAVESTDATOMIC"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
# Check whether --enable-atomic was given.
|
||||
if test "${enable_atomic+set}" = set; then :
|
||||
enableval=$enable_atomic; enable_atomic="$enableval"
|
||||
else
|
||||
enable_atomic="autodetect"
|
||||
fi
|
||||
|
||||
case "$enable_atomic" in
|
||||
yes|''|autodetect)
|
||||
case "$host" in
|
||||
powerpc-ibm-aix*)
|
||||
if test "X$GCC" = "Xyes"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if asm(\"ics\"); works" >&5
|
||||
$as_echo_n "checking if asm(\"ics\"); works... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
main() { asm("ics"); exit(0); }
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
use_atomic=yes
|
||||
else
|
||||
|
||||
saved_cflags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wa,-many"
|
||||
if test "$cross_compiling" = yes; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cross compile, assume yes" >&5
|
||||
$as_echo "cross compile, assume yes" >&6; }
|
||||
CFLAGS="$saved_cflags"
|
||||
use_atomic=yes
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
main() { asm("ics"); exit(0); }
|
||||
|
||||
_ACEOF
|
||||
if ac_fn_c_try_run "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, required -Wa,-many" >&5
|
||||
$as_echo "yes, required -Wa,-many" >&6; }
|
||||
use_atomic=yes
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, use_atomic disabled" >&5
|
||||
$as_echo "no, use_atomic disabled" >&6; }
|
||||
CFLAGS="$saved_cflags"
|
||||
use_atomic=no
|
||||
fi
|
||||
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
|
||||
conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
fi
|
||||
|
||||
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
else
|
||||
use_atomic=yes
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
use_atomic=yes
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
no)
|
||||
have_stdatomic=no
|
||||
ISC_PLATFORM_HAVESTDATOMIC="#undef ISC_PLATFORM_HAVESTDATOMIC"
|
||||
use_atomic=no
|
||||
arch=noatomic
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "X$have_stdatomic" = "Xyes"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -latomic is needed to use 64-bit stdatomic.h primitives" >&5
|
||||
$as_echo_n "checking if -latomic is needed to use 64-bit stdatomic.h primitives... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdatomic.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
atomic_int_fast64_t val = 0; atomic_fetch_add_explicit(&val, 1, memory_order_relaxed);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
ISC_ATOMIC_LIBS=""
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
ISC_ATOMIC_LIBS="-latomic"
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS="$LIBS $ISC_ATOMIC_LIBS"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
ISC_PLATFORM_USEOSFASM="#undef ISC_PLATFORM_USEOSFASM"
|
||||
ISC_PLATFORM_USEGCCASM="#undef ISC_PLATFORM_USEGCCASM"
|
||||
ISC_PLATFORM_USESTDASM="#undef ISC_PLATFORM_USESTDASM"
|
||||
ISC_PLATFORM_USEMACASM="#undef ISC_PLATFORM_USEMACASM"
|
||||
if test "yes" = "$use_atomic"; then
|
||||
# The cast to long int works around a bug in the HP C Compiler
|
||||
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
|
||||
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
|
||||
# This bug is HP SR number 8606223364.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
|
||||
$as_echo_n "checking size of void *... " >&6; }
|
||||
if ${ac_cv_sizeof_void_p+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
|
||||
|
||||
else
|
||||
if test "$ac_cv_type_void_p" = yes; then
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error 77 "cannot compute sizeof (void *)
|
||||
See \`config.log' for more details" "$LINENO" 5; }
|
||||
else
|
||||
ac_cv_sizeof_void_p=0
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
|
||||
$as_echo "$ac_cv_sizeof_void_p" >&6; }
|
||||
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
|
||||
_ACEOF
|
||||
|
||||
|
||||
have_atomic=yes # set default
|
||||
case "$host" in
|
||||
i[3456]86-*)
|
||||
# XXX: some old x86 architectures actually do not support
|
||||
# (some of) these operations. Do we need stricter checks?
|
||||
if test $ac_cv_sizeof_void_p = 8; then
|
||||
arch=x86_64
|
||||
have_xaddq=yes
|
||||
else
|
||||
arch=x86_32
|
||||
fi
|
||||
;;
|
||||
x86_64-*|amd64-*)
|
||||
if test $ac_cv_sizeof_void_p = 8; then
|
||||
arch=x86_64
|
||||
have_xaddq=yes
|
||||
else
|
||||
arch=x86_32
|
||||
fi
|
||||
;;
|
||||
alpha*-*)
|
||||
arch=alpha
|
||||
;;
|
||||
powerpc-*|powerpc64-*)
|
||||
arch=powerpc
|
||||
;;
|
||||
mips-*|mipsel-*|mips64-*|mips64el-*)
|
||||
arch=mips
|
||||
;;
|
||||
ia64-*)
|
||||
arch=ia64
|
||||
;;
|
||||
*)
|
||||
have_atomic=no
|
||||
arch=noatomic
|
||||
;;
|
||||
esac
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking architecture type for atomic operations" >&5
|
||||
$as_echo_n "checking architecture type for atomic operations... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $arch" >&5
|
||||
$as_echo "$arch" >&6; }
|
||||
fi
|
||||
|
||||
if test "yes" = "$have_atomic"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler support for inline assembly code" >&5
|
||||
$as_echo_n "checking compiler support for inline assembly code... " >&6; }
|
||||
|
||||
compiler=generic
|
||||
# Check whether the compiler supports the assembly syntax we provide.
|
||||
if test "X$GCC" = "Xyes"; then
|
||||
# GCC's ASM extension always works
|
||||
compiler=gcc
|
||||
if test $arch = "x86_64"; then
|
||||
# We can share the same code for gcc with x86_32
|
||||
arch=x86_32
|
||||
fi
|
||||
if test $arch = "powerpc"; then
|
||||
#
|
||||
# The MacOS (and maybe others) uses "r0" for register
|
||||
# zero. Under linux/ibm it is "0" for register 0.
|
||||
# Probe to see if we have a MacOS style assembler.
|
||||
#
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Checking for MacOS style assembler syntax" >&5
|
||||
$as_echo_n "checking Checking for MacOS style assembler syntax... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
__asm__ volatile ("li r0, 0x0\n"::);
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
compiler="mac"
|
||||
ISC_PLATFORM_USEMACASM="#define ISC_PLATFORM_USEMACASM 1"
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
else
|
||||
case "$host" in
|
||||
alpha*-dec-osf*)
|
||||
# Tru64 compiler has its own syntax for inline
|
||||
# assembly.
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
#ifndef __DECC
|
||||
#error "unexpected compiler"
|
||||
#endif
|
||||
return (0);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
compiler=osf
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
;;
|
||||
powerpc-ibm-aix*)
|
||||
compiler=aix
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case "$compiler" in
|
||||
gcc)
|
||||
ISC_PLATFORM_USEGCCASM="#define ISC_PLATFORM_USEGCCASM 1"
|
||||
;;
|
||||
osf)
|
||||
ISC_PLATFORM_USEOSFASM="#define ISC_PLATFORM_USEOSFASM 1"
|
||||
;;
|
||||
aix)
|
||||
;;
|
||||
mac)
|
||||
;;
|
||||
*)
|
||||
# See if the generic __asm function works. If not,
|
||||
# we need to disable the atomic operations.
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
__asm("nop")
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
compiler="standard"
|
||||
ISC_PLATFORM_USESTDASM="#define ISC_PLATFORM_USESTDASM 1"
|
||||
else
|
||||
compiler="not supported (atomic operations disabled)"
|
||||
have_atomic=no
|
||||
arch=noatomic
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext;
|
||||
;;
|
||||
esac
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $compiler" >&5
|
||||
$as_echo "$compiler" >&6; }
|
||||
fi
|
||||
|
||||
if test "yes" = "$have_atomic"; then
|
||||
ISC_PLATFORM_HAVEXADD="#define ISC_PLATFORM_HAVEXADD 1"
|
||||
ISC_PLATFORM_HAVECMPXCHG="#define ISC_PLATFORM_HAVECMPXCHG 1"
|
||||
ISC_PLATFORM_HAVEATOMICSTORE="#define ISC_PLATFORM_HAVEATOMICSTORE 1"
|
||||
if test "yes" = "$have_xaddq"; then
|
||||
ISC_PLATFORM_HAVEXADDQ="#define ISC_PLATFORM_HAVEXADDQ 1"
|
||||
ISC_PLATFORM_HAVEATOMICSTOREQ="#define ISC_PLATFORM_HAVEATOMICSTOREQ 1"
|
||||
else
|
||||
ISC_PLATFORM_HAVEXADDQ="#undef ISC_PLATFORM_HAVEXADDQ"
|
||||
ISC_PLATFORM_HAVEATOMICSTOREQ="#undef ISC_PLATFORM_HAVEATOMICSTOREQ"
|
||||
fi
|
||||
else
|
||||
ISC_PLATFORM_HAVEXADD="#undef ISC_PLATFORM_HAVEXADD"
|
||||
ISC_PLATFORM_HAVECMPXCHG="#undef ISC_PLATFORM_HAVECMPXCHG"
|
||||
ISC_PLATFORM_HAVEATOMICSTORE="#undef ISC_PLATFORM_HAVEATOMICSTORE"
|
||||
ISC_PLATFORM_HAVEXADDQ="#undef ISC_PLATFORM_HAVEXADDQ"
|
||||
ISC_PLATFORM_HAVEATOMICSTOREQ="#undef ISC_PLATFORM_HAVEATOMICSTOREQ"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ISC_ARCH_DIR=$arch
|
||||
|
||||
|
||||
#
|
||||
# Check for __builtin_expect
|
||||
#
|
||||
|
||||
+36
-245
@@ -24,7 +24,7 @@ case $build_os in
|
||||
sunos*)
|
||||
# Just set the maximum command line length for sunos as it otherwise
|
||||
# takes a exceptionally long time to work it out. Required for libtool.
|
||||
|
||||
|
||||
lt_cv_sys_max_cmd_len=4096;
|
||||
;;
|
||||
esac
|
||||
@@ -1306,7 +1306,7 @@ case "$use_gssapi" in
|
||||
DNS_GSSAPI_LIBS="-framework Kerberos"
|
||||
AC_MSG_RESULT(framework)
|
||||
;;
|
||||
|
||||
|
||||
*)
|
||||
AC_MSG_RESULT(looking in $use_gssapi/lib)
|
||||
USE_GSSAPI='-DGSSAPI'
|
||||
@@ -1530,6 +1530,32 @@ AC_SUBST(NZD_TOOLS)
|
||||
AC_SUBST(NZDSRCS)
|
||||
AC_SUBST(NZDTARGETS)
|
||||
|
||||
# Search for Concurrency Kit
|
||||
|
||||
AC_ARG_WITH([ck],
|
||||
[AS_HELP_STRING([--with-ck[=PATH]], [specify path to Concurrency Kit])],
|
||||
[:],[with_ck=yes])
|
||||
AS_CASE([$with_ck],
|
||||
[no],[AC_MSG_FAILURE([Concurrency Kit is mandatory])],
|
||||
[yes],[PKG_CHECK_MODULES([CK],[ck])],
|
||||
[*],[
|
||||
save_CFLAGS="$CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS -I$with_ck/include"
|
||||
LIBS="$LIBS -L$with_ck/lib"
|
||||
AC_CHECK_HEADERS([ck_pr.h],
|
||||
[:],
|
||||
[AC_MSG_ERROR([ck_pr.h not found; Concurrency Kit is mandatory])])
|
||||
AC_SEARCH_LIBS([ck_array_init], [ck],
|
||||
[
|
||||
CK_CFLAGS="-I$with_ck/include"
|
||||
CK_LIBS="-Wl,-rpath,$with_ck/lib -L$with_ck/lib -lck"
|
||||
],
|
||||
[AC_MSG_ERROR([Concurrency Kit is mandatory])])])
|
||||
|
||||
CFLAGS="$CFLAGS $CK_CFLAGS"
|
||||
LIBS="$LIBS $CK_LIBS"
|
||||
|
||||
#
|
||||
# was --with-libxml2 specified?
|
||||
#
|
||||
@@ -2331,7 +2357,7 @@ AC_TRY_RUN([
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
main() { char a[16]; return (inet_pton(AF_INET, "1.2.3", a) == 1 ? 1 :
|
||||
inet_pton(AF_INET, "1.2.3.04", a) == 1 ? 1 :
|
||||
inet_pton(AF_INET, "1.2.3.04", a) == 1 ? 1 :
|
||||
(inet_pton(AF_INET6, "::1.2.3.4", a) != 1)); }],
|
||||
[AC_MSG_RESULT(yes)
|
||||
ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"],
|
||||
@@ -2521,7 +2547,7 @@ AC_ARG_ENABLE(getifaddrs,
|
||||
# This interface iteration code for getifaddrs() will fall back to using
|
||||
# /proc/net/if_inet6 if getifaddrs() in glibc doesn't return any IPv6
|
||||
# addresses.
|
||||
#
|
||||
#
|
||||
case $want_getifaddrs in
|
||||
glibc)
|
||||
AC_MSG_WARN("--enable-getifaddrs=glibc is no longer required")
|
||||
@@ -2955,241 +2981,6 @@ AC_SUBST(ISC_PLATFORM_HAVEIFNAMETOINDEX)
|
||||
|
||||
AC_CHECK_FUNCS(nanosleep usleep explicit_bzero)
|
||||
|
||||
#
|
||||
# Machine architecture dependent features
|
||||
#
|
||||
have_stdatomic=no
|
||||
AC_MSG_CHECKING(for usable stdatomic.h)
|
||||
AC_TRY_COMPILE([
|
||||
#include <stdio.h>
|
||||
#include <stdatomic.h>
|
||||
],
|
||||
[
|
||||
atomic_int_fast32_t val = 0; atomic_fetch_add_explicit(&val, 1, memory_order_relaxed);
|
||||
],
|
||||
[AC_MSG_RESULT(yes)
|
||||
have_stdatomic=yes
|
||||
ISC_PLATFORM_HAVESTDATOMIC="#define ISC_PLATFORM_HAVESTDATOMIC 1"],
|
||||
[AC_MSG_RESULT(no)
|
||||
have_stdatomic=no
|
||||
ISC_PLATFORM_HAVESTDATOMIC="#undef ISC_PLATFORM_HAVESTDATOMIC"])
|
||||
|
||||
AC_ARG_ENABLE(atomic,
|
||||
AS_HELP_STRING([--enable-atomic],
|
||||
[enable machine specific atomic operations [default=autodetect]]),
|
||||
enable_atomic="$enableval",
|
||||
enable_atomic="autodetect")
|
||||
case "$enable_atomic" in
|
||||
yes|''|autodetect)
|
||||
case "$host" in
|
||||
powerpc-ibm-aix*)
|
||||
if test "X$GCC" = "Xyes"; then
|
||||
AC_MSG_CHECKING([if asm("ics"); works])
|
||||
AC_TRY_COMPILE(,[
|
||||
main() { asm("ics"); exit(0); }
|
||||
],
|
||||
[AC_MSG_RESULT(yes)
|
||||
use_atomic=yes],
|
||||
[
|
||||
saved_cflags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wa,-many"
|
||||
AC_TRY_RUN([
|
||||
main() { asm("ics"); exit(0); }
|
||||
],
|
||||
[AC_MSG_RESULT([yes, required -Wa,-many])
|
||||
use_atomic=yes],
|
||||
[AC_MSG_RESULT([no, use_atomic disabled])
|
||||
CFLAGS="$saved_cflags"
|
||||
use_atomic=no],
|
||||
[AC_MSG_RESULT([cross compile, assume yes])
|
||||
CFLAGS="$saved_cflags"
|
||||
use_atomic=yes])
|
||||
]
|
||||
)
|
||||
else
|
||||
use_atomic=yes
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
use_atomic=yes
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
no)
|
||||
have_stdatomic=no
|
||||
ISC_PLATFORM_HAVESTDATOMIC="#undef ISC_PLATFORM_HAVESTDATOMIC"
|
||||
use_atomic=no
|
||||
arch=noatomic
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "X$have_stdatomic" = "Xyes"; then
|
||||
AC_MSG_CHECKING(if -latomic is needed to use 64-bit stdatomic.h primitives)
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([#include <stdatomic.h>],
|
||||
[atomic_int_fast64_t val = 0; atomic_fetch_add_explicit(&val, 1, memory_order_relaxed);])],
|
||||
[AC_MSG_RESULT(no)
|
||||
ISC_ATOMIC_LIBS=""],
|
||||
[AC_MSG_RESULT(yes)
|
||||
ISC_ATOMIC_LIBS="-latomic"]
|
||||
)
|
||||
LIBS="$LIBS $ISC_ATOMIC_LIBS"
|
||||
fi
|
||||
|
||||
AC_SUBST(ISC_PLATFORM_HAVESTDATOMIC)
|
||||
|
||||
ISC_PLATFORM_USEOSFASM="#undef ISC_PLATFORM_USEOSFASM"
|
||||
ISC_PLATFORM_USEGCCASM="#undef ISC_PLATFORM_USEGCCASM"
|
||||
ISC_PLATFORM_USESTDASM="#undef ISC_PLATFORM_USESTDASM"
|
||||
ISC_PLATFORM_USEMACASM="#undef ISC_PLATFORM_USEMACASM"
|
||||
if test "yes" = "$use_atomic"; then
|
||||
AC_CHECK_SIZEOF([void *])
|
||||
have_atomic=yes # set default
|
||||
case "$host" in
|
||||
[i[3456]86-*])
|
||||
# XXX: some old x86 architectures actually do not support
|
||||
# (some of) these operations. Do we need stricter checks?
|
||||
if test $ac_cv_sizeof_void_p = 8; then
|
||||
arch=x86_64
|
||||
have_xaddq=yes
|
||||
else
|
||||
arch=x86_32
|
||||
fi
|
||||
;;
|
||||
x86_64-*|amd64-*)
|
||||
if test $ac_cv_sizeof_void_p = 8; then
|
||||
arch=x86_64
|
||||
have_xaddq=yes
|
||||
else
|
||||
arch=x86_32
|
||||
fi
|
||||
;;
|
||||
alpha*-*)
|
||||
arch=alpha
|
||||
;;
|
||||
powerpc-*|powerpc64-*)
|
||||
arch=powerpc
|
||||
;;
|
||||
mips-*|mipsel-*|mips64-*|mips64el-*)
|
||||
arch=mips
|
||||
;;
|
||||
ia64-*)
|
||||
arch=ia64
|
||||
;;
|
||||
*)
|
||||
have_atomic=no
|
||||
arch=noatomic
|
||||
;;
|
||||
esac
|
||||
AC_MSG_CHECKING([architecture type for atomic operations])
|
||||
AC_MSG_RESULT($arch)
|
||||
fi
|
||||
|
||||
if test "yes" = "$have_atomic"; then
|
||||
AC_MSG_CHECKING([compiler support for inline assembly code])
|
||||
|
||||
compiler=generic
|
||||
# Check whether the compiler supports the assembly syntax we provide.
|
||||
if test "X$GCC" = "Xyes"; then
|
||||
# GCC's ASM extension always works
|
||||
compiler=gcc
|
||||
if test $arch = "x86_64"; then
|
||||
# We can share the same code for gcc with x86_32
|
||||
arch=x86_32
|
||||
fi
|
||||
if test $arch = "powerpc"; then
|
||||
#
|
||||
# The MacOS (and maybe others) uses "r0" for register
|
||||
# zero. Under linux/ibm it is "0" for register 0.
|
||||
# Probe to see if we have a MacOS style assembler.
|
||||
#
|
||||
AC_MSG_CHECKING([Checking for MacOS style assembler syntax])
|
||||
AC_TRY_COMPILE(, [
|
||||
__asm__ volatile ("li r0, 0x0\n"::);
|
||||
], [
|
||||
AC_MSG_RESULT(yes)
|
||||
compiler="mac"
|
||||
ISC_PLATFORM_USEMACASM="#define ISC_PLATFORM_USEMACASM 1"
|
||||
], [AC_MSG_RESULT(no)])
|
||||
fi
|
||||
else
|
||||
case "$host" in
|
||||
alpha*-dec-osf*)
|
||||
# Tru64 compiler has its own syntax for inline
|
||||
# assembly.
|
||||
AC_TRY_COMPILE(, [
|
||||
#ifndef __DECC
|
||||
#error "unexpected compiler"
|
||||
#endif
|
||||
return (0);],
|
||||
[compiler=osf],)
|
||||
;;
|
||||
powerpc-ibm-aix*)
|
||||
compiler=aix
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case "$compiler" in
|
||||
gcc)
|
||||
ISC_PLATFORM_USEGCCASM="#define ISC_PLATFORM_USEGCCASM 1"
|
||||
;;
|
||||
osf)
|
||||
ISC_PLATFORM_USEOSFASM="#define ISC_PLATFORM_USEOSFASM 1"
|
||||
;;
|
||||
aix)
|
||||
;;
|
||||
mac)
|
||||
;;
|
||||
*)
|
||||
# See if the generic __asm function works. If not,
|
||||
# we need to disable the atomic operations.
|
||||
AC_TRY_LINK(, [
|
||||
__asm("nop")
|
||||
],
|
||||
[compiler="standard"
|
||||
ISC_PLATFORM_USESTDASM="#define ISC_PLATFORM_USESTDASM 1"],
|
||||
[compiler="not supported (atomic operations disabled)"
|
||||
have_atomic=no
|
||||
arch=noatomic ]);
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_RESULT($compiler)
|
||||
fi
|
||||
|
||||
if test "yes" = "$have_atomic"; then
|
||||
ISC_PLATFORM_HAVEXADD="#define ISC_PLATFORM_HAVEXADD 1"
|
||||
ISC_PLATFORM_HAVECMPXCHG="#define ISC_PLATFORM_HAVECMPXCHG 1"
|
||||
ISC_PLATFORM_HAVEATOMICSTORE="#define ISC_PLATFORM_HAVEATOMICSTORE 1"
|
||||
if test "yes" = "$have_xaddq"; then
|
||||
ISC_PLATFORM_HAVEXADDQ="#define ISC_PLATFORM_HAVEXADDQ 1"
|
||||
ISC_PLATFORM_HAVEATOMICSTOREQ="#define ISC_PLATFORM_HAVEATOMICSTOREQ 1"
|
||||
else
|
||||
ISC_PLATFORM_HAVEXADDQ="#undef ISC_PLATFORM_HAVEXADDQ"
|
||||
ISC_PLATFORM_HAVEATOMICSTOREQ="#undef ISC_PLATFORM_HAVEATOMICSTOREQ"
|
||||
fi
|
||||
else
|
||||
ISC_PLATFORM_HAVEXADD="#undef ISC_PLATFORM_HAVEXADD"
|
||||
ISC_PLATFORM_HAVECMPXCHG="#undef ISC_PLATFORM_HAVECMPXCHG"
|
||||
ISC_PLATFORM_HAVEATOMICSTORE="#undef ISC_PLATFORM_HAVEATOMICSTORE"
|
||||
ISC_PLATFORM_HAVEXADDQ="#undef ISC_PLATFORM_HAVEXADDQ"
|
||||
ISC_PLATFORM_HAVEATOMICSTOREQ="#undef ISC_PLATFORM_HAVEATOMICSTOREQ"
|
||||
fi
|
||||
|
||||
AC_SUBST(ISC_PLATFORM_HAVEXADD)
|
||||
AC_SUBST(ISC_PLATFORM_HAVEXADDQ)
|
||||
AC_SUBST(ISC_PLATFORM_HAVECMPXCHG)
|
||||
AC_SUBST(ISC_PLATFORM_HAVEATOMICSTORE)
|
||||
AC_SUBST(ISC_PLATFORM_HAVEATOMICSTOREQ)
|
||||
|
||||
AC_SUBST(ISC_PLATFORM_USEGCCASM)
|
||||
AC_SUBST(ISC_PLATFORM_USEOSFASM)
|
||||
AC_SUBST(ISC_PLATFORM_USESTDASM)
|
||||
AC_SUBST(ISC_PLATFORM_USEMACASM)
|
||||
|
||||
ISC_ARCH_DIR=$arch
|
||||
AC_SUBST(ISC_ARCH_DIR)
|
||||
|
||||
#
|
||||
# Check for __builtin_expect
|
||||
#
|
||||
@@ -3557,11 +3348,11 @@ AC_SUBST(CURL)
|
||||
# NOM_PATH_FILE(VARIABLE, FILENAME, DIRECTORIES)
|
||||
#
|
||||
# If the file FILENAME is found in one of the DIRECTORIES, the shell
|
||||
# variable VARIABLE is defined to its absolute pathname. Otherwise,
|
||||
# variable VARIABLE is defined to its absolute pathname. Otherwise,
|
||||
# it is set to FILENAME, with no directory prefix (that's not terribly
|
||||
# useful, but looks less confusing in substitutions than leaving it
|
||||
# empty). The variable VARIABLE will be substituted into output files.
|
||||
#
|
||||
#
|
||||
|
||||
AC_DEFUN([NOM_PATH_FILE], [
|
||||
$1=""
|
||||
@@ -3937,7 +3728,7 @@ DLZ_SYSTEM_TEST=""
|
||||
DLZ_DRIVER_MYSQL_INCLUDES=""
|
||||
DLZ_DRIVER_MYSQL_LIBS=""
|
||||
|
||||
#
|
||||
#
|
||||
# Configure support for building a shared library object
|
||||
#
|
||||
# Even when libtool is available it can't always be relied upon
|
||||
@@ -4086,8 +3877,8 @@ if test "yes" = "$cross_compiling"; then
|
||||
BUILD_LDFLAGS="$BUILD_LDFLAGS"
|
||||
BUILD_LIBS="$BUILD_LIBS"
|
||||
else
|
||||
BUILD_CC="$CC"
|
||||
BUILD_CFLAGS="$CFLAGS"
|
||||
BUILD_CC="$CC"
|
||||
BUILD_CFLAGS="$CFLAGS"
|
||||
BUILD_CPPFLAGS="$CPPFLAGS $GEN_NEED_OPTARG"
|
||||
BUILD_LDFLAGS="$LDFLAGS"
|
||||
BUILD_LIBS="$LIBS"
|
||||
@@ -4407,7 +4198,7 @@ report() {
|
||||
echo " Algorithm: $with_cc_alg"
|
||||
fi
|
||||
|
||||
# these lines are only printed if run with --enable-full-report
|
||||
# these lines are only printed if run with --enable-full-report
|
||||
if test "yes" = "$enable_full_report"; then
|
||||
test "no" = "$enable_ipv6" -o "no" = "$found_ipv6" || \
|
||||
echo " IPv6 support (--enable-ipv6)"
|
||||
|
||||
+5
-9
@@ -50,11 +50,7 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
|
||||
|
||||
acl->name = NULL;
|
||||
|
||||
result = isc_refcount_init(&acl->refcount, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(mctx, acl, sizeof(*acl));
|
||||
return (result);
|
||||
}
|
||||
isc_refcount_init(&acl->refcount, 1);
|
||||
|
||||
result = dns_iptable_create(mctx, &acl->iptable);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@@ -454,7 +450,7 @@ void
|
||||
dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
|
||||
REQUIRE(DNS_ACL_VALID(source));
|
||||
|
||||
isc_refcount_increment(&source->refcount, NULL);
|
||||
isc_refcount_increment(&source->refcount);
|
||||
*target = source;
|
||||
}
|
||||
|
||||
@@ -487,13 +483,13 @@ destroy(dns_acl_t *dacl) {
|
||||
void
|
||||
dns_acl_detach(dns_acl_t **aclp) {
|
||||
dns_acl_t *acl = *aclp;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(DNS_ACL_VALID(acl));
|
||||
|
||||
isc_refcount_decrement(&acl->refcount, &refs);
|
||||
if (refs == 0)
|
||||
if (isc_refcount_decrement(&acl->refcount) == 1) {
|
||||
destroy(acl);
|
||||
}
|
||||
|
||||
*aclp = NULL;
|
||||
}
|
||||
|
||||
|
||||
+14
-21
@@ -233,7 +233,7 @@ dns_catz_entry_copy(dns_catz_zone_t *zone, const dns_catz_entry_t *entry,
|
||||
void
|
||||
dns_catz_entry_attach(dns_catz_entry_t *entry, dns_catz_entry_t **entryp) {
|
||||
REQUIRE(entryp != NULL && *entryp == NULL);
|
||||
isc_refcount_increment(&entry->refs, NULL);
|
||||
isc_refcount_increment(&entry->refs);
|
||||
*entryp = entry;
|
||||
}
|
||||
|
||||
@@ -241,23 +241,22 @@ void
|
||||
dns_catz_entry_detach(dns_catz_zone_t *zone, dns_catz_entry_t **entryp) {
|
||||
dns_catz_entry_t *entry;
|
||||
isc_mem_t *mctx;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(entryp != NULL && *entryp != NULL);
|
||||
|
||||
entry = *entryp;
|
||||
*entryp = NULL;
|
||||
|
||||
mctx = zone->catzs->mctx;
|
||||
|
||||
isc_refcount_decrement(&entry->refs, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&entry->refs) == 1) {
|
||||
dns_catz_options_free(&entry->opts, mctx);
|
||||
if (dns_name_dynamic(&entry->name))
|
||||
dns_name_free(&entry->name, mctx);
|
||||
isc_refcount_destroy(&entry->refs);
|
||||
isc_mem_put(mctx, entry, sizeof(dns_catz_entry_t));
|
||||
}
|
||||
|
||||
*entryp = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -568,9 +567,7 @@ dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_newzones;
|
||||
|
||||
result = isc_refcount_init(&new_zones->refs, 1);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_mutex;
|
||||
isc_refcount_init(&new_zones->refs, 1);
|
||||
|
||||
result = isc_ht_init(&new_zones->zones, mctx, 4);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@@ -592,7 +589,6 @@ dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
|
||||
isc_ht_destroy(&new_zones->zones);
|
||||
cleanup_refcount:
|
||||
isc_refcount_destroy(&new_zones->refs);
|
||||
cleanup_mutex:
|
||||
isc_mutex_destroy(&new_zones->lock);
|
||||
cleanup_newzones:
|
||||
isc_mem_put(mctx, new_zones, sizeof(*new_zones));
|
||||
@@ -731,7 +727,7 @@ void
|
||||
dns_catz_catzs_attach(dns_catz_zones_t *catzs, dns_catz_zones_t **catzsp) {
|
||||
REQUIRE(catzsp != NULL && *catzsp == NULL);
|
||||
|
||||
isc_refcount_increment(&catzs->refs, NULL);
|
||||
isc_refcount_increment(&catzs->refs);
|
||||
*catzsp = catzs;
|
||||
}
|
||||
|
||||
@@ -739,7 +735,7 @@ void
|
||||
dns_catz_zone_attach(dns_catz_zone_t *zone, dns_catz_zone_t **zonep) {
|
||||
REQUIRE(zonep != NULL && *zonep == NULL);
|
||||
|
||||
isc_refcount_increment(&zone->refs, NULL);
|
||||
isc_refcount_increment(&zone->refs);
|
||||
*zonep = zone;
|
||||
}
|
||||
|
||||
@@ -749,14 +745,13 @@ dns_catz_zone_detach(dns_catz_zone_t **zonep) {
|
||||
dns_catz_zone_t *zone;
|
||||
isc_ht_iter_t *iter = NULL;
|
||||
isc_mem_t *mctx;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(zonep != NULL && *zonep != NULL);
|
||||
|
||||
zone = *zonep;
|
||||
*zonep = NULL;
|
||||
isc_refcount_decrement(&zone->refs, &refs);
|
||||
if (refs == 0) {
|
||||
|
||||
if (isc_refcount_decrement(&zone->refs) == 1) {
|
||||
isc_refcount_destroy(&zone->refs);
|
||||
if (zone->entries != NULL) {
|
||||
result = isc_ht_iter_create(zone->entries, &iter);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
@@ -778,7 +773,6 @@ dns_catz_zone_detach(dns_catz_zone_t **zonep) {
|
||||
}
|
||||
mctx = zone->catzs->mctx;
|
||||
isc_timer_detach(&zone->updatetimer);
|
||||
isc_refcount_destroy(&zone->refs);
|
||||
if (zone->db_registered == true) {
|
||||
result = dns_db_updatenotify_unregister(zone->db,
|
||||
dns_catz_dbupdate_callback,
|
||||
@@ -798,6 +792,8 @@ dns_catz_zone_detach(dns_catz_zone_t **zonep) {
|
||||
zone->catzs = NULL;
|
||||
isc_mem_put(mctx, zone, sizeof(dns_catz_zone_t));
|
||||
}
|
||||
|
||||
*zonep = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -805,7 +801,6 @@ dns_catz_catzs_detach(dns_catz_zones_t ** catzsp) {
|
||||
dns_catz_zones_t *catzs;
|
||||
isc_ht_iter_t *iter = NULL;
|
||||
isc_result_t result;
|
||||
unsigned int refs;
|
||||
dns_catz_zone_t *zone;
|
||||
|
||||
|
||||
@@ -814,9 +809,8 @@ dns_catz_catzs_detach(dns_catz_zones_t ** catzsp) {
|
||||
REQUIRE(catzs != NULL);
|
||||
|
||||
*catzsp = NULL;
|
||||
isc_refcount_decrement(&catzs->refs, &refs);
|
||||
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&catzs->refs) == 1) {
|
||||
isc_refcount_destroy(&catzs->refs);
|
||||
DESTROYLOCK(&catzs->lock);
|
||||
if (catzs->zones != NULL) {
|
||||
result = isc_ht_iter_create(catzs->zones, &iter);
|
||||
@@ -833,7 +827,6 @@ dns_catz_catzs_detach(dns_catz_zones_t ** catzsp) {
|
||||
INSIST(isc_ht_count(catzs->zones) == 0);
|
||||
isc_ht_destroy(&catzs->zones);
|
||||
}
|
||||
isc_refcount_destroy(&catzs->refs);
|
||||
isc_task_destroy(&catzs->updater);
|
||||
isc_mem_putanddetach(&catzs->mctx, catzs, sizeof(*catzs));
|
||||
}
|
||||
|
||||
+6
-6
@@ -214,7 +214,7 @@ dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path,
|
||||
|
||||
memset(env, 0, sizeof(dns_dtenv_t));
|
||||
|
||||
CHECK(isc_refcount_init(&env->refcount, 1));
|
||||
isc_refcount_init(&env->refcount, 1);
|
||||
CHECK(isc_stats_create(mctx, &env->stats, dns_dnstapcounter_max));
|
||||
env->path = isc_mem_strdup(mctx, path);
|
||||
if (env->path == NULL)
|
||||
@@ -531,7 +531,7 @@ dns_dt_attach(dns_dtenv_t *source, dns_dtenv_t **destp) {
|
||||
REQUIRE(VALID_DTENV(source));
|
||||
REQUIRE(destp != NULL && *destp == NULL);
|
||||
|
||||
isc_refcount_increment(&source->refcount, NULL);
|
||||
isc_refcount_increment(&source->refcount);
|
||||
*destp = source;
|
||||
}
|
||||
|
||||
@@ -579,17 +579,17 @@ destroy(dns_dtenv_t *env) {
|
||||
|
||||
void
|
||||
dns_dt_detach(dns_dtenv_t **envp) {
|
||||
unsigned int refs;
|
||||
dns_dtenv_t *env;
|
||||
|
||||
REQUIRE(envp != NULL && VALID_DTENV(*envp));
|
||||
|
||||
env = *envp;
|
||||
*envp = NULL;
|
||||
|
||||
isc_refcount_decrement(&env->refcount, &refs);
|
||||
if (refs == 0)
|
||||
if (isc_refcount_decrement(&env->refcount) == 1) {
|
||||
destroy(env);
|
||||
}
|
||||
|
||||
*envp = NULL;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
|
||||
+19
-28
@@ -1124,7 +1124,7 @@ dst_key_attach(dst_key_t *source, dst_key_t **target) {
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
REQUIRE(VALID_KEY(source));
|
||||
|
||||
isc_refcount_increment(&source->refs, NULL);
|
||||
isc_refcount_increment(&source->refs);
|
||||
*target = source;
|
||||
}
|
||||
|
||||
@@ -1132,7 +1132,6 @@ void
|
||||
dst_key_free(dst_key_t **keyp) {
|
||||
isc_mem_t *mctx;
|
||||
dst_key_t *key;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(dst_initialized == true);
|
||||
REQUIRE(keyp != NULL && VALID_KEY(*keyp));
|
||||
@@ -1140,26 +1139,24 @@ dst_key_free(dst_key_t **keyp) {
|
||||
key = *keyp;
|
||||
mctx = key->mctx;
|
||||
|
||||
isc_refcount_decrement(&key->refs, &refs);
|
||||
if (refs != 0)
|
||||
return;
|
||||
|
||||
isc_refcount_destroy(&key->refs);
|
||||
if (key->keydata.generic != NULL) {
|
||||
INSIST(key->func->destroy != NULL);
|
||||
key->func->destroy(key);
|
||||
if (isc_refcount_decrement(&key->refs) == 1) {
|
||||
isc_refcount_destroy(&key->refs);
|
||||
if (key->keydata.generic != NULL) {
|
||||
INSIST(key->func->destroy != NULL);
|
||||
key->func->destroy(key);
|
||||
}
|
||||
if (key->engine != NULL)
|
||||
isc_mem_free(mctx, key->engine);
|
||||
if (key->label != NULL)
|
||||
isc_mem_free(mctx, key->label);
|
||||
dns_name_free(key->key_name, mctx);
|
||||
isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
|
||||
if (key->key_tkeytoken) {
|
||||
isc_buffer_free(&key->key_tkeytoken);
|
||||
}
|
||||
isc_safe_memwipe(key, sizeof(*key));
|
||||
isc_mem_putanddetach(&mctx, key, sizeof(*key));
|
||||
}
|
||||
if (key->engine != NULL)
|
||||
isc_mem_free(mctx, key->engine);
|
||||
if (key->label != NULL)
|
||||
isc_mem_free(mctx, key->label);
|
||||
dns_name_free(key->key_name, mctx);
|
||||
isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
|
||||
if (key->key_tkeytoken) {
|
||||
isc_buffer_free(&key->key_tkeytoken);
|
||||
}
|
||||
isc_safe_memwipe(key, sizeof(*key));
|
||||
isc_mem_putanddetach(&mctx, key, sizeof(*key));
|
||||
*keyp = NULL;
|
||||
}
|
||||
|
||||
@@ -1354,13 +1351,7 @@ get_key_struct(const dns_name_t *name, unsigned int alg,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
result = isc_refcount_init(&key->refs, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_name_free(key->key_name, mctx);
|
||||
isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
|
||||
isc_mem_put(mctx, key, sizeof(dst_key_t));
|
||||
return (NULL);
|
||||
}
|
||||
isc_refcount_init(&key->refs, 1);
|
||||
isc_mem_attach(mctx, &key->mctx);
|
||||
key->key_alg = alg;
|
||||
key->key_flags = flags;
|
||||
|
||||
@@ -38,12 +38,6 @@ ISC_LANG_BEGINDECLS
|
||||
#define DNS_RBTFIND_NOPREDECESSOR 0x04
|
||||
/*@}*/
|
||||
|
||||
#ifndef DNS_RBT_USEISCREFCOUNT
|
||||
#ifdef ISC_REFCOUNT_HAVEATOMIC
|
||||
#define DNS_RBT_USEISCREFCOUNT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DNS_RBT_USEMAGIC 1
|
||||
|
||||
/*
|
||||
@@ -164,13 +158,8 @@ struct dns_rbtnode {
|
||||
unsigned int dirty:1;
|
||||
unsigned int wild:1;
|
||||
unsigned int locknum:DNS_RBT_LOCKLENGTH;
|
||||
#ifndef DNS_RBT_USEISCREFCOUNT
|
||||
unsigned int references:DNS_RBT_REFLENGTH;
|
||||
#endif
|
||||
unsigned int :0; /* end of bitfields c/o node lock */
|
||||
#ifdef DNS_RBT_USEISCREFCOUNT
|
||||
isc_refcount_t references; /* note that this is not in the bitfield */
|
||||
#endif
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
@@ -1052,89 +1041,6 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
|
||||
* Find the next node at the current depth in DNSSEC order.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Wrapper macros for manipulating the rbtnode reference counter:
|
||||
* Since we selectively use isc_refcount_t for the reference counter of
|
||||
* a rbtnode, operations on the counter depend on the actual type of it.
|
||||
* The following macros provide a common interface to these operations,
|
||||
* hiding the back-end. The usage is the same as that of isc_refcount_xxx().
|
||||
*/
|
||||
#ifdef DNS_RBT_USEISCREFCOUNT
|
||||
#define dns_rbtnode_refinit(node, n) \
|
||||
do { \
|
||||
isc_refcount_init(&(node)->references, (n)); \
|
||||
} while (0)
|
||||
#define dns_rbtnode_refdestroy(node) \
|
||||
do { \
|
||||
isc_refcount_destroy(&(node)->references); \
|
||||
} while (0)
|
||||
#define dns_rbtnode_refcurrent(node) \
|
||||
isc_refcount_current(&(node)->references)
|
||||
#define dns_rbtnode_refincrement0(node, refs) \
|
||||
do { \
|
||||
isc_refcount_increment0(&(node)->references, (refs)); \
|
||||
} while (0)
|
||||
#define dns_rbtnode_refincrement(node, refs) \
|
||||
do { \
|
||||
isc_refcount_increment(&(node)->references, (refs)); \
|
||||
} while (0)
|
||||
#define dns_rbtnode_refdecrement(node, refs) \
|
||||
do { \
|
||||
isc_refcount_decrement(&(node)->references, (refs)); \
|
||||
} while (0)
|
||||
#else /* DNS_RBT_USEISCREFCOUNT */
|
||||
#define dns_rbtnode_refinit(node, n) ((node)->references = (n))
|
||||
#define dns_rbtnode_refdestroy(node) ISC_REQUIRE((node)->references == 0)
|
||||
#define dns_rbtnode_refcurrent(node) ((node)->references)
|
||||
|
||||
#if (__STDC_VERSION__ + 0) >= 199901L || defined __GNUC__
|
||||
static inline void
|
||||
dns_rbtnode_refincrement0(dns_rbtnode_t *node, unsigned int *refs) {
|
||||
node->references++;
|
||||
if (refs != NULL)
|
||||
*refs = node->references;
|
||||
}
|
||||
|
||||
static inline void
|
||||
dns_rbtnode_refincrement(dns_rbtnode_t *node, unsigned int *refs) {
|
||||
ISC_REQUIRE(node->references > 0);
|
||||
node->references++;
|
||||
if (refs != NULL)
|
||||
*refs = node->references;
|
||||
}
|
||||
|
||||
static inline void
|
||||
dns_rbtnode_refdecrement(dns_rbtnode_t *node, unsigned int *refs) {
|
||||
ISC_REQUIRE(node->references > 0);
|
||||
node->references--;
|
||||
if (refs != NULL)
|
||||
*refs = node->references;
|
||||
}
|
||||
#else
|
||||
#define dns_rbtnode_refincrement0(node, refs) \
|
||||
do { \
|
||||
unsigned int *_tmp = (unsigned int *)(refs); \
|
||||
(node)->references++; \
|
||||
if ((_tmp) != NULL) \
|
||||
(*_tmp) = (node)->references; \
|
||||
} while (0)
|
||||
#define dns_rbtnode_refincrement(node, refs) \
|
||||
do { \
|
||||
ISC_REQUIRE((node)->references > 0); \
|
||||
(node)->references++; \
|
||||
if ((refs) != NULL) \
|
||||
(*refs) = (node)->references; \
|
||||
} while (0)
|
||||
#define dns_rbtnode_refdecrement(node, refs) \
|
||||
do { \
|
||||
ISC_REQUIRE((node)->references > 0); \
|
||||
(node)->references--; \
|
||||
if ((refs) != NULL) \
|
||||
(*refs) = (node)->references; \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif /* DNS_RBT_USEISCREFCOUNT */
|
||||
|
||||
void
|
||||
dns_rbtnode_nodename(dns_rbtnode_t *node, dns_name_t *name);
|
||||
|
||||
|
||||
+5
-4
@@ -142,18 +142,19 @@ dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, bool pos)
|
||||
void
|
||||
dns_iptable_attach(dns_iptable_t *source, dns_iptable_t **target) {
|
||||
REQUIRE(DNS_IPTABLE_VALID(source));
|
||||
isc_refcount_increment(&source->refcount, NULL);
|
||||
isc_refcount_increment(&source->refcount);
|
||||
*target = source;
|
||||
}
|
||||
|
||||
void
|
||||
dns_iptable_detach(dns_iptable_t **tabp) {
|
||||
dns_iptable_t *tab = *tabp;
|
||||
unsigned int refs;
|
||||
REQUIRE(DNS_IPTABLE_VALID(tab));
|
||||
isc_refcount_decrement(&tab->refcount, &refs);
|
||||
if (refs == 0)
|
||||
|
||||
if (isc_refcount_decrement(&tab->refcount) == 1) {
|
||||
destroy_iptable(tab);
|
||||
}
|
||||
|
||||
*tabp = NULL;
|
||||
}
|
||||
|
||||
|
||||
+16
-36
@@ -89,15 +89,8 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
|
||||
goto cleanup_rbt;
|
||||
}
|
||||
|
||||
result = isc_refcount_init(&keytable->active_nodes, 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_rwlock;
|
||||
}
|
||||
|
||||
result = isc_refcount_init(&keytable->references, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_active_nodes;
|
||||
}
|
||||
isc_refcount_init(&keytable->active_nodes, 0);
|
||||
isc_refcount_init(&keytable->references, 1);
|
||||
|
||||
keytable->mctx = NULL;
|
||||
isc_mem_attach(mctx, &keytable->mctx);
|
||||
@@ -106,12 +99,6 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup_active_nodes:
|
||||
isc_refcount_destroy(&keytable->active_nodes);
|
||||
|
||||
cleanup_rwlock:
|
||||
isc_rwlock_destroy(&keytable->rwlock);
|
||||
|
||||
cleanup_rbt:
|
||||
dns_rbt_destroy(&keytable->table);
|
||||
|
||||
@@ -131,7 +118,7 @@ dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
|
||||
REQUIRE(VALID_KEYTABLE(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
isc_refcount_increment(&source->references, NULL);
|
||||
isc_refcount_increment(&source->references);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
@@ -139,7 +126,6 @@ dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
|
||||
void
|
||||
dns_keytable_detach(dns_keytable_t **keytablep) {
|
||||
dns_keytable_t *keytable;
|
||||
unsigned int refs;
|
||||
|
||||
/*
|
||||
* Detach *keytablep from its keytable.
|
||||
@@ -148,10 +134,8 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
|
||||
REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
|
||||
|
||||
keytable = *keytablep;
|
||||
*keytablep = NULL;
|
||||
|
||||
isc_refcount_decrement(&keytable->references, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&keytable->references) == 1) {
|
||||
INSIST(isc_refcount_current(&keytable->active_nodes) == 0);
|
||||
isc_refcount_destroy(&keytable->active_nodes);
|
||||
isc_refcount_destroy(&keytable->references);
|
||||
@@ -161,6 +145,7 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
|
||||
isc_mem_putanddetach(&keytable->mctx,
|
||||
keytable, sizeof(*keytable));
|
||||
}
|
||||
*keytablep = NULL;
|
||||
}
|
||||
|
||||
/*%
|
||||
@@ -424,7 +409,7 @@ dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
|
||||
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (node->data != NULL) {
|
||||
isc_refcount_increment0(&keytable->active_nodes, NULL);
|
||||
isc_refcount_increment0(&keytable->active_nodes);
|
||||
dns_keynode_attach(node->data, keynodep);
|
||||
} else
|
||||
result = ISC_R_NOTFOUND;
|
||||
@@ -452,7 +437,7 @@ dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
dns_keynode_attach(keynode->next, nextnodep);
|
||||
isc_refcount_increment(&keytable->active_nodes, NULL);
|
||||
isc_refcount_increment(&keytable->active_nodes);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@@ -500,7 +485,7 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, const dns_name_t *name,
|
||||
break;
|
||||
}
|
||||
if (knode != NULL) {
|
||||
isc_refcount_increment0(&keytable->active_nodes, NULL);
|
||||
isc_refcount_increment0(&keytable->active_nodes);
|
||||
dns_keynode_attach(knode, keynodep);
|
||||
} else
|
||||
result = DNS_R_PARTIALMATCH;
|
||||
@@ -538,7 +523,7 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
|
||||
break;
|
||||
}
|
||||
if (knode != NULL) {
|
||||
isc_refcount_increment(&keytable->active_nodes, NULL);
|
||||
isc_refcount_increment(&keytable->active_nodes);
|
||||
result = ISC_R_SUCCESS;
|
||||
dns_keynode_attach(knode, nextnodep);
|
||||
} else
|
||||
@@ -587,7 +572,7 @@ dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
|
||||
REQUIRE(VALID_KEYNODE(source));
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
|
||||
isc_refcount_increment(&keytable->active_nodes, NULL);
|
||||
isc_refcount_increment(&keytable->active_nodes);
|
||||
|
||||
dns_keynode_attach(source, target);
|
||||
}
|
||||
@@ -602,7 +587,7 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
|
||||
REQUIRE(VALID_KEYTABLE(keytable));
|
||||
REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
|
||||
|
||||
isc_refcount_decrement(&keytable->active_nodes, NULL);
|
||||
(void)isc_refcount_decrement(&keytable->active_nodes);
|
||||
dns_keynode_detach(keytable->mctx, keynodep);
|
||||
}
|
||||
|
||||
@@ -748,7 +733,7 @@ dns_keytable_forall(dns_keytable_t *keytable,
|
||||
result = ISC_R_SUCCESS;
|
||||
goto cleanup;
|
||||
}
|
||||
isc_refcount_increment0(&keytable->active_nodes, NULL);
|
||||
isc_refcount_increment0(&keytable->active_nodes);
|
||||
for (;;) {
|
||||
dns_rbtnodechain_current(&chain, NULL, NULL, &node);
|
||||
if (node->data != NULL)
|
||||
@@ -760,7 +745,7 @@ dns_keytable_forall(dns_keytable_t *keytable,
|
||||
break;
|
||||
}
|
||||
}
|
||||
isc_refcount_decrement(&keytable->active_nodes, NULL);
|
||||
(void)isc_refcount_decrement(&keytable->active_nodes);
|
||||
|
||||
cleanup:
|
||||
dns_rbtnodechain_invalidate(&chain);
|
||||
@@ -798,7 +783,6 @@ dns_keynode_trust(dns_keynode_t *keynode) {
|
||||
|
||||
isc_result_t
|
||||
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
|
||||
isc_result_t result;
|
||||
dns_keynode_t *knode;
|
||||
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
@@ -813,9 +797,7 @@ dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
|
||||
knode->key = NULL;
|
||||
knode->next = NULL;
|
||||
|
||||
result = isc_refcount_init(&knode->refcount, 1);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
isc_refcount_init(&knode->refcount, 1);
|
||||
|
||||
*target = knode;
|
||||
return (ISC_R_SUCCESS);
|
||||
@@ -824,17 +806,15 @@ dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
|
||||
void
|
||||
dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
|
||||
REQUIRE(VALID_KEYNODE(source));
|
||||
isc_refcount_increment(&source->refcount, NULL);
|
||||
isc_refcount_increment(&source->refcount);
|
||||
*target = source;
|
||||
}
|
||||
|
||||
void
|
||||
dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
|
||||
unsigned int refs;
|
||||
dns_keynode_t *node = *keynode;
|
||||
REQUIRE(VALID_KEYNODE(node));
|
||||
isc_refcount_decrement(&node->refcount, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&node->refcount) == 1) {
|
||||
if (node->key != NULL)
|
||||
dst_key_free(&node->key);
|
||||
isc_refcount_destroy(&node->refcount);
|
||||
|
||||
+4
-11
@@ -61,19 +61,16 @@ struct dns_nta {
|
||||
*/
|
||||
static void
|
||||
nta_ref(dns_nta_t *nta) {
|
||||
isc_refcount_increment(&nta->refcount, NULL);
|
||||
isc_refcount_increment(&nta->refcount);
|
||||
}
|
||||
|
||||
static void
|
||||
nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
|
||||
unsigned int refs;
|
||||
dns_nta_t *nta = *ntap;
|
||||
|
||||
REQUIRE(VALID_NTA(nta));
|
||||
|
||||
*ntap = NULL;
|
||||
isc_refcount_decrement(&nta->refcount, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&nta->refcount) == 1) {
|
||||
nta->magic = 0;
|
||||
if (nta->timer != NULL) {
|
||||
(void) isc_timer_reset(nta->timer,
|
||||
@@ -92,6 +89,7 @@ nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
|
||||
}
|
||||
isc_mem_put(mctx, nta, sizeof(dns_nta_t));
|
||||
}
|
||||
*ntap = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -308,7 +306,6 @@ static isc_result_t
|
||||
nta_create(dns_ntatable_t *ntatable, const dns_name_t *name,
|
||||
dns_nta_t **target)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_nta_t *nta = NULL;
|
||||
dns_view_t *view;
|
||||
|
||||
@@ -328,11 +325,7 @@ nta_create(dns_ntatable_t *ntatable, const dns_name_t *name,
|
||||
dns_rdataset_init(&nta->rdataset);
|
||||
dns_rdataset_init(&nta->sigrdataset);
|
||||
|
||||
result = isc_refcount_init(&nta->refcount, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(view->mctx, nta, sizeof(dns_nta_t));
|
||||
return (result);
|
||||
}
|
||||
isc_refcount_init(&nta->refcount, 1);
|
||||
|
||||
nta->name = dns_fixedname_initname(&nta->fn);
|
||||
dns_name_copy(name, nta->name, NULL);
|
||||
|
||||
+12
-18
@@ -49,7 +49,6 @@ struct dns_order {
|
||||
isc_result_t
|
||||
dns_order_create(isc_mem_t *mctx, dns_order_t **orderp) {
|
||||
dns_order_t *order;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(orderp != NULL && *orderp == NULL);
|
||||
|
||||
@@ -60,11 +59,7 @@ dns_order_create(isc_mem_t *mctx, dns_order_t **orderp) {
|
||||
ISC_LIST_INIT(order->ents);
|
||||
|
||||
/* Implicit attach. */
|
||||
result = isc_refcount_init(&order->references, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(mctx, order, sizeof(*order));
|
||||
return (result);
|
||||
}
|
||||
isc_refcount_init(&order->references, 1);
|
||||
|
||||
order->mctx = NULL;
|
||||
isc_mem_attach(mctx, &order->mctx);
|
||||
@@ -133,7 +128,7 @@ void
|
||||
dns_order_attach(dns_order_t *source, dns_order_t **target) {
|
||||
REQUIRE(DNS_ORDER_VALID(source));
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
isc_refcount_increment(&source->references, NULL);
|
||||
isc_refcount_increment(&source->references);
|
||||
*target = source;
|
||||
}
|
||||
|
||||
@@ -141,21 +136,20 @@ void
|
||||
dns_order_detach(dns_order_t **orderp) {
|
||||
dns_order_t *order;
|
||||
dns_order_ent_t *ent;
|
||||
unsigned int references;
|
||||
|
||||
REQUIRE(orderp != NULL);
|
||||
order = *orderp;
|
||||
REQUIRE(DNS_ORDER_VALID(order));
|
||||
isc_refcount_decrement(&order->references, &references);
|
||||
*orderp = NULL;
|
||||
if (references != 0)
|
||||
return;
|
||||
|
||||
order->magic = 0;
|
||||
while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) {
|
||||
ISC_LIST_UNLINK(order->ents, ent, link);
|
||||
isc_mem_put(order->mctx, ent, sizeof(*ent));
|
||||
if (isc_refcount_decrement(&order->references) == 1) {
|
||||
order->magic = 0;
|
||||
while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) {
|
||||
ISC_LIST_UNLINK(order->ents, ent, link);
|
||||
isc_mem_put(order->mctx, ent, sizeof(*ent));
|
||||
}
|
||||
isc_refcount_destroy(&order->references);
|
||||
isc_mem_putanddetach(&order->mctx, order, sizeof(*order));
|
||||
}
|
||||
isc_refcount_destroy(&order->references);
|
||||
isc_mem_putanddetach(&order->mctx, order, sizeof(*order));
|
||||
|
||||
*orderp = NULL;
|
||||
}
|
||||
|
||||
+5
-11
@@ -80,12 +80,7 @@ dns_portlist_create(isc_mem_t *mctx, dns_portlist_t **portlistp) {
|
||||
isc_mem_put(mctx, portlist, sizeof(*portlist));
|
||||
return (result);
|
||||
}
|
||||
result = isc_refcount_init(&portlist->refcount, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
DESTROYLOCK(&portlist->lock);
|
||||
isc_mem_put(mctx, portlist, sizeof(*portlist));
|
||||
return (result);
|
||||
}
|
||||
isc_refcount_init(&portlist->refcount, 1);
|
||||
portlist->list = NULL;
|
||||
portlist->allocated = 0;
|
||||
portlist->active = 0;
|
||||
@@ -233,21 +228,19 @@ dns_portlist_attach(dns_portlist_t *portlist, dns_portlist_t **portlistp) {
|
||||
REQUIRE(DNS_VALID_PORTLIST(portlist));
|
||||
REQUIRE(portlistp != NULL && *portlistp == NULL);
|
||||
|
||||
isc_refcount_increment(&portlist->refcount, NULL);
|
||||
isc_refcount_increment(&portlist->refcount);
|
||||
*portlistp = portlist;
|
||||
}
|
||||
|
||||
void
|
||||
dns_portlist_detach(dns_portlist_t **portlistp) {
|
||||
dns_portlist_t *portlist;
|
||||
unsigned int count;
|
||||
|
||||
REQUIRE(portlistp != NULL);
|
||||
portlist = *portlistp;
|
||||
REQUIRE(DNS_VALID_PORTLIST(portlist));
|
||||
*portlistp = NULL;
|
||||
isc_refcount_decrement(&portlist->refcount, &count);
|
||||
if (count == 0) {
|
||||
|
||||
if (isc_refcount_decrement(&portlist->refcount) == 1) {
|
||||
portlist->magic = 0;
|
||||
isc_refcount_destroy(&portlist->refcount);
|
||||
if (portlist->list != NULL)
|
||||
@@ -258,4 +251,5 @@ dns_portlist_detach(dns_portlist_t **portlistp) {
|
||||
isc_mem_putanddetach(&portlist->mctx, portlist,
|
||||
sizeof(*portlist));
|
||||
}
|
||||
*portlistp = NULL;
|
||||
}
|
||||
|
||||
+2
-2
@@ -2105,7 +2105,7 @@ dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, bool recurse)
|
||||
#if DNS_RBT_USEMAGIC
|
||||
node->magic = 0;
|
||||
#endif
|
||||
dns_rbtnode_refdestroy(node);
|
||||
isc_refcount_destroy(&node->references);
|
||||
|
||||
freenode(rbt, &node);
|
||||
|
||||
@@ -2217,7 +2217,7 @@ create_node(isc_mem_t *mctx, const dns_name_t *name, dns_rbtnode_t **nodep) {
|
||||
LOCKNUM(node) = 0;
|
||||
WILD(node) = 0;
|
||||
DIRTY(node) = 0;
|
||||
dns_rbtnode_refinit(node, 0);
|
||||
isc_refcount_init(&node->references, 0);
|
||||
node->find_callback = 0;
|
||||
node->nsec = DNS_RBT_NSEC_NORMAL;
|
||||
|
||||
|
||||
+57
-234
@@ -134,31 +134,10 @@ typedef uint32_t rbtdb_rdatatype_t;
|
||||
#define RBTDB_RDATATYPE_NCACHEANY \
|
||||
RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any)
|
||||
|
||||
/*
|
||||
* We use rwlock for DB lock only when ISC_RWLOCK_USEATOMIC is non 0.
|
||||
* Using rwlock is effective with regard to lookup performance only when
|
||||
* it is implemented in an efficient way.
|
||||
* Otherwise, it is generally wise to stick to the simple locking since rwlock
|
||||
* would require more memory or can even make lookups slower due to its own
|
||||
* overhead (when it internally calls mutex locks).
|
||||
*/
|
||||
#ifdef ISC_RWLOCK_USEATOMIC
|
||||
#define DNS_RBTDB_USERWLOCK 1
|
||||
#else
|
||||
#define DNS_RBTDB_USERWLOCK 0
|
||||
#endif
|
||||
|
||||
#if DNS_RBTDB_USERWLOCK
|
||||
#define RBTDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
|
||||
#define RBTDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
|
||||
#define RBTDB_LOCK(l, t) RWLOCK((l), (t))
|
||||
#define RBTDB_UNLOCK(l, t) RWUNLOCK((l), (t))
|
||||
#else
|
||||
#define RBTDB_INITLOCK(l) isc_mutex_init(l)
|
||||
#define RBTDB_DESTROYLOCK(l) DESTROYLOCK(l)
|
||||
#define RBTDB_LOCK(l, t) LOCK(l)
|
||||
#define RBTDB_UNLOCK(l, t) UNLOCK(l)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Since node locking is sensitive to both performance and memory footprint,
|
||||
@@ -179,7 +158,6 @@ typedef uint32_t rbtdb_rdatatype_t;
|
||||
* Note that we cannot use NODE_LOCK()/NODE_UNLOCK() wherever the protected
|
||||
* section is also protected by NODE_STRONGLOCK().
|
||||
*/
|
||||
#if defined(ISC_RWLOCK_USEATOMIC) && defined(DNS_RBT_USEISCREFCOUNT)
|
||||
typedef isc_rwlock_t nodelock_t;
|
||||
|
||||
#define NODE_INITLOCK(l) isc_rwlock_init((l), 0, 0)
|
||||
@@ -187,27 +165,7 @@ typedef isc_rwlock_t nodelock_t;
|
||||
#define NODE_LOCK(l, t) RWLOCK((l), (t))
|
||||
#define NODE_UNLOCK(l, t) RWUNLOCK((l), (t))
|
||||
#define NODE_TRYUPGRADE(l) isc_rwlock_tryupgrade(l)
|
||||
|
||||
#define NODE_STRONGLOCK(l) ((void)0)
|
||||
#define NODE_STRONGUNLOCK(l) ((void)0)
|
||||
#define NODE_WEAKLOCK(l, t) NODE_LOCK(l, t)
|
||||
#define NODE_WEAKUNLOCK(l, t) NODE_UNLOCK(l, t)
|
||||
#define NODE_WEAKDOWNGRADE(l) isc_rwlock_downgrade(l)
|
||||
#else
|
||||
typedef isc_mutex_t nodelock_t;
|
||||
|
||||
#define NODE_INITLOCK(l) isc_mutex_init(l)
|
||||
#define NODE_DESTROYLOCK(l) DESTROYLOCK(l)
|
||||
#define NODE_LOCK(l, t) LOCK(l)
|
||||
#define NODE_UNLOCK(l, t) UNLOCK(l)
|
||||
#define NODE_TRYUPGRADE(l) ISC_R_SUCCESS
|
||||
|
||||
#define NODE_STRONGLOCK(l) LOCK(l)
|
||||
#define NODE_STRONGUNLOCK(l) UNLOCK(l)
|
||||
#define NODE_WEAKLOCK(l, t) ((void)0)
|
||||
#define NODE_WEAKUNLOCK(l, t) ((void)0)
|
||||
#define NODE_WEAKDOWNGRADE(l) ((void)0)
|
||||
#endif
|
||||
#define NODE_DOWNGRADE(l) isc_rwlock_downgrade(l)
|
||||
|
||||
/*%
|
||||
* Whether to rate-limit updating the LRU to avoid possible thread contention.
|
||||
@@ -466,11 +424,7 @@ struct dns_rbtdb {
|
||||
/* Unlocked. */
|
||||
dns_db_t common;
|
||||
/* Locks the data in this struct */
|
||||
#if DNS_RBTDB_USERWLOCK
|
||||
isc_rwlock_t lock;
|
||||
#else
|
||||
isc_mutex_t lock;
|
||||
#endif
|
||||
/* Locks the tree structure (prevents nodes appearing/disappearing) */
|
||||
isc_rwlock_t tree_lock;
|
||||
/* Locks for individual tree nodes */
|
||||
@@ -814,7 +768,7 @@ attach(dns_db_t *source, dns_db_t **targetp) {
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
isc_refcount_increment(&rbtdb->references, NULL);
|
||||
isc_refcount_increment(&rbtdb->references);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
@@ -1013,11 +967,9 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) {
|
||||
REQUIRE(rbtdb->future_version == NULL);
|
||||
|
||||
if (rbtdb->current_version != NULL) {
|
||||
unsigned int refs;
|
||||
|
||||
isc_refcount_decrement(&rbtdb->current_version->references,
|
||||
&refs);
|
||||
INSIST(refs == 0);
|
||||
INSIST(isc_refcount_decrement(&rbtdb->current_version->references) == 1);
|
||||
|
||||
UNLINK(rbtdb->open_versions, rbtdb->current_version, link);
|
||||
isc_rwlock_destroy(&rbtdb->current_version->glue_rwlock);
|
||||
isc_refcount_destroy(&rbtdb->current_version->references);
|
||||
@@ -1228,14 +1180,12 @@ maybe_free_rbtdb(dns_rbtdb_t *rbtdb) {
|
||||
static void
|
||||
detach(dns_db_t **dbp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(*dbp);
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
isc_refcount_decrement(&rbtdb->references, &refs);
|
||||
|
||||
if (refs == 0)
|
||||
if (isc_refcount_decrement(&rbtdb->references) == 1) {
|
||||
maybe_free_rbtdb(rbtdb);
|
||||
}
|
||||
|
||||
*dbp = NULL;
|
||||
}
|
||||
@@ -1244,13 +1194,13 @@ static void
|
||||
currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
rbtdb_version_t *version;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
/* XXXOND: Is the lock needed here? */
|
||||
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
|
||||
version = rbtdb->current_version;
|
||||
isc_refcount_increment(&version->references, &refs);
|
||||
isc_refcount_increment(&version->references);
|
||||
RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
|
||||
|
||||
*versionp = (dns_dbversion_t *)version;
|
||||
@@ -1268,11 +1218,9 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial,
|
||||
if (version == NULL)
|
||||
return (NULL);
|
||||
version->serial = serial;
|
||||
result = isc_refcount_init(&version->references, references);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(mctx, version, sizeof(*version));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
isc_refcount_init(&version->references, references);
|
||||
|
||||
result = isc_rwlock_init(&version->glue_rwlock, 0, 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_refcount_destroy(&version->references);
|
||||
@@ -1375,13 +1323,11 @@ attachversion(dns_db_t *db, dns_dbversion_t *source,
|
||||
{
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
rbtdb_version_t *rbtversion = source;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
INSIST(rbtversion != NULL && rbtversion->rbtdb == rbtdb);
|
||||
|
||||
isc_refcount_increment(&rbtversion->references, &refs);
|
||||
INSIST(refs > 1);
|
||||
isc_refcount_increment(&rbtversion->references);
|
||||
|
||||
*targetp = rbtversion;
|
||||
}
|
||||
@@ -1391,7 +1337,6 @@ add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
|
||||
dns_rbtnode_t *node)
|
||||
{
|
||||
rbtdb_changed_t *changed;
|
||||
unsigned int refs;
|
||||
|
||||
/*
|
||||
* Caller must be holding the node lock if its reference must be
|
||||
@@ -1405,8 +1350,7 @@ add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
|
||||
REQUIRE(version->writer);
|
||||
|
||||
if (changed != NULL) {
|
||||
dns_rbtnode_refincrement(node, &refs);
|
||||
INSIST(refs != 0);
|
||||
isc_refcount_increment(&node->references);
|
||||
changed->node = node;
|
||||
changed->dirty = false;
|
||||
ISC_LIST_INITANDAPPEND(version->changed_list, changed, link);
|
||||
@@ -1835,96 +1779,16 @@ delete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
clean_now_or_later(dns_rbtnode_t *node, dns_rbtdb_t *rbtdb,
|
||||
rdatasetheader_t *header, rdatasetheader_t **header_prevp)
|
||||
{
|
||||
if (dns_rbtnode_refcurrent(node) == 0) {
|
||||
isc_mem_t *mctx;
|
||||
|
||||
/*
|
||||
* header->down can be non-NULL if the refcount has just
|
||||
* decremented to 0 but decrement_reference() has not performed
|
||||
* clean_cache_node(), in which case we need to purge the stale
|
||||
* headers first.
|
||||
*/
|
||||
mctx = rbtdb->common.mctx;
|
||||
clean_stale_headers(rbtdb, mctx, header);
|
||||
if (*header_prevp != NULL)
|
||||
(*header_prevp)->next = header->next;
|
||||
else
|
||||
node->data = header->next;
|
||||
free_rdataset(rbtdb, mctx, header);
|
||||
} else {
|
||||
header->attributes |= RDATASET_ATTR_STALE |
|
||||
RDATASET_ATTR_ANCIENT;
|
||||
node->dirty = 1;
|
||||
*header_prevp = header;
|
||||
}
|
||||
}
|
||||
|
||||
static rdataset_ttl_t
|
||||
check_ttl(dns_rbtnode_t *node, rbtdb_search_t *search,
|
||||
rdatasetheader_t *header, rdatasetheader_t **header_prevp,
|
||||
nodelock_t *lock, isc_rwlocktype_t *locktype)
|
||||
{
|
||||
dns_rbtdb_t *rbtdb = search->rbtdb;
|
||||
|
||||
if (header->rdh_ttl > search->now)
|
||||
return rdataset_ttl_fresh;
|
||||
|
||||
/*
|
||||
* This rdataset is stale, but perhaps still usable.
|
||||
*/
|
||||
if (KEEPSTALE(rbtdb) &&
|
||||
header->rdh_ttl + rbtdb->serve_stale_ttl > search->now) {
|
||||
header->attributes |= RDATASET_ATTR_STALE;
|
||||
/* Doesn't set dirty because it doesn't need removal. */
|
||||
return rdataset_ttl_stale;
|
||||
}
|
||||
|
||||
/*
|
||||
* This rdataset is so stale it is no longer usable, even with
|
||||
* KEEPSTALE. If no one else is using the node, we can clean it up
|
||||
* right now, otherwise we mark it as ancient, and the node as dirty,
|
||||
* so it will get cleaned up later.
|
||||
*/
|
||||
if ((header->rdh_ttl <= search->now - RBTDB_VIRTUAL) &&
|
||||
(*locktype == isc_rwlocktype_write ||
|
||||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
|
||||
/*
|
||||
* We update the node's status only when we can get write
|
||||
* access; otherwise, we leave others to this work. Periodical
|
||||
* cleaning will eventually take the job as the last resort.
|
||||
* We won't downgrade the lock, since other rdatasets are
|
||||
* probably stale, too.
|
||||
*/
|
||||
*locktype = isc_rwlocktype_write;
|
||||
clean_now_or_later(node, rbtdb, header, header_prevp);
|
||||
} else
|
||||
*header_prevp = header;
|
||||
|
||||
return rdataset_ttl_ancient;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Caller must be holding the node lock.
|
||||
*/
|
||||
static inline void
|
||||
new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
|
||||
unsigned int lockrefs, noderefs;
|
||||
isc_refcount_t *lockref;
|
||||
|
||||
INSIST(!ISC_LINK_LINKED(node, deadlink));
|
||||
dns_rbtnode_refincrement0(node, &noderefs);
|
||||
if (noderefs == 1) { /* this is the first reference to the node */
|
||||
lockref = &rbtdb->node_locks[node->locknum].references;
|
||||
isc_refcount_increment0(lockref, &lockrefs);
|
||||
INSIST(lockrefs != 0);
|
||||
if (isc_refcount_increment(&node->references) == 0) {
|
||||
/* this is the first reference to the node */
|
||||
isc_refcount_increment0(&rbtdb->node_locks[node->locknum].references);
|
||||
}
|
||||
INSIST(noderefs != 0);
|
||||
}
|
||||
|
||||
/*%
|
||||
@@ -1948,7 +1812,7 @@ cleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) {
|
||||
* Since we're holding a tree write lock, it should be
|
||||
* impossible for this node to be referenced by others.
|
||||
*/
|
||||
INSIST(dns_rbtnode_refcurrent(node) == 0 &&
|
||||
INSIST(isc_refcount_current(&node->references) == 0 &&
|
||||
node->data == NULL);
|
||||
|
||||
if (node->parent != NULL &&
|
||||
@@ -2000,8 +1864,7 @@ reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
|
||||
POST(locktype);
|
||||
|
||||
NODE_STRONGLOCK(nodelock);
|
||||
NODE_WEAKLOCK(nodelock, locktype);
|
||||
NODE_LOCK(nodelock, locktype);
|
||||
|
||||
/*
|
||||
* Check if we can possibly cleanup the dead node. If so, upgrade
|
||||
@@ -2016,10 +1879,10 @@ reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
/*
|
||||
* Upgrade the lock and test if we still need to unlink.
|
||||
*/
|
||||
NODE_WEAKUNLOCK(nodelock, locktype);
|
||||
NODE_UNLOCK(nodelock, locktype);
|
||||
locktype = isc_rwlocktype_write;
|
||||
POST(locktype);
|
||||
NODE_WEAKLOCK(nodelock, locktype);
|
||||
NODE_LOCK(nodelock, locktype);
|
||||
if (ISC_LINK_LINKED(node, deadlink))
|
||||
ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum],
|
||||
node, deadlink);
|
||||
@@ -2029,8 +1892,7 @@ reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
|
||||
new_reference(rbtdb, node);
|
||||
|
||||
NODE_WEAKUNLOCK(nodelock, locktype);
|
||||
NODE_STRONGUNLOCK(nodelock);
|
||||
NODE_UNLOCK(nodelock, locktype);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2056,7 +1918,6 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
isc_result_t result;
|
||||
bool write_locked;
|
||||
rbtdb_nodelock_t *nodelock;
|
||||
unsigned int refs, nrefs;
|
||||
int bucket = node->locknum;
|
||||
bool no_reference = true;
|
||||
|
||||
@@ -2068,27 +1929,24 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
|
||||
/* Handle easy and typical case first. */
|
||||
if (!node->dirty && KEEP_NODE(node, rbtdb)) {
|
||||
dns_rbtnode_refdecrement(node, &nrefs);
|
||||
INSIST((int)nrefs >= 0);
|
||||
if (nrefs == 0) {
|
||||
isc_refcount_decrement(&nodelock->references, &refs);
|
||||
INSIST((int)refs >= 0);
|
||||
if (isc_refcount_decrement(&node->references) == 1) {
|
||||
isc_refcount_decrement(&nodelock->references);
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
return ((nrefs == 0) ? true : false);
|
||||
}
|
||||
|
||||
/* Upgrade the lock? */
|
||||
if (nlock == isc_rwlocktype_read) {
|
||||
NODE_WEAKUNLOCK(&nodelock->lock, isc_rwlocktype_read);
|
||||
NODE_WEAKLOCK(&nodelock->lock, isc_rwlocktype_write);
|
||||
NODE_UNLOCK(&nodelock->lock, isc_rwlocktype_read);
|
||||
NODE_LOCK(&nodelock->lock, isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
dns_rbtnode_refdecrement(node, &nrefs);
|
||||
INSIST((int)nrefs >= 0);
|
||||
if (nrefs > 0) {
|
||||
if (isc_refcount_decrement(&node->references) > 1) {
|
||||
/* Restore the lock? */
|
||||
if (nlock == isc_rwlocktype_read)
|
||||
NODE_WEAKDOWNGRADE(&nodelock->lock);
|
||||
NODE_DOWNGRADE(&nodelock->lock);
|
||||
return (false);
|
||||
}
|
||||
|
||||
@@ -2133,8 +1991,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
} else
|
||||
write_locked = true;
|
||||
|
||||
isc_refcount_decrement(&nodelock->references, &refs);
|
||||
INSIST((int)refs >= 0);
|
||||
isc_refcount_decrement(&nodelock->references);
|
||||
|
||||
if (KEEP_NODE(node, rbtdb))
|
||||
goto restore_locks;
|
||||
@@ -2212,7 +2069,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
restore_locks:
|
||||
/* Restore the lock? */
|
||||
if (nlock == isc_rwlocktype_read)
|
||||
NODE_WEAKDOWNGRADE(&nodelock->lock);
|
||||
NODE_DOWNGRADE(&nodelock->lock);
|
||||
|
||||
/*
|
||||
* Relock a read lock, or unlock the write lock if no lock was held.
|
||||
@@ -2489,7 +2346,6 @@ cleanup_dead_nodes_callback(isc_task_t *task, isc_event_t *event) {
|
||||
dns_rbtdb_t *rbtdb = event->ev_arg;
|
||||
bool again = false;
|
||||
unsigned int locknum;
|
||||
unsigned int refs;
|
||||
|
||||
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
|
||||
for (locknum = 0; locknum < rbtdb->node_lock_count; locknum++) {
|
||||
@@ -2506,9 +2362,9 @@ cleanup_dead_nodes_callback(isc_task_t *task, isc_event_t *event) {
|
||||
isc_task_send(task, &event);
|
||||
else {
|
||||
isc_event_free(&event);
|
||||
isc_refcount_decrement(&rbtdb->references, &refs);
|
||||
if (refs == 0)
|
||||
if (isc_refcount_decrement(&rbtdb->references) == 1) {
|
||||
maybe_free_rbtdb(rbtdb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2522,7 +2378,6 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
|
||||
rbtdb_changed_t *changed, *next_changed;
|
||||
rbtdb_serial_t serial, least_serial;
|
||||
dns_rbtnode_t *rbtnode;
|
||||
unsigned int refs;
|
||||
rdatasetheader_t *header;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
@@ -2533,8 +2388,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
|
||||
ISC_LIST_INIT(cleanup_list);
|
||||
ISC_LIST_INIT(resigned_list);
|
||||
|
||||
isc_refcount_decrement(&version->references, &refs);
|
||||
if (refs > 0) { /* typical and easy case first */
|
||||
if (isc_refcount_decrement(&version->references) > 1) {
|
||||
/* typical and easy case first */
|
||||
if (commit) {
|
||||
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
|
||||
INSIST(!version->writer);
|
||||
@@ -2565,9 +2420,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
|
||||
* DB itself and unlink it from the open list.
|
||||
*/
|
||||
cur_version = rbtdb->current_version;
|
||||
isc_refcount_decrement(&cur_version->references,
|
||||
&cur_ref);
|
||||
if (cur_ref == 0) {
|
||||
cur_ref = isc_refcount_decrement(&cur_version->references);
|
||||
if (cur_ref == 1) {
|
||||
if (cur_version->serial == rbtdb->least_serial)
|
||||
INSIST(EMPTY(cur_version->changed_list));
|
||||
UNLINK(rbtdb->open_versions,
|
||||
@@ -2601,7 +2455,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
|
||||
* isn't being used by anyone, we can clean
|
||||
* it up.
|
||||
*/
|
||||
if (cur_ref == 0) {
|
||||
if (cur_ref == 1) {
|
||||
cleanup_version = cur_version;
|
||||
APPENDLIST(version->changed_list,
|
||||
cleanup_version->changed_list,
|
||||
@@ -2622,9 +2476,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
|
||||
* case where we need to increment the counter from
|
||||
* zero and need to use isc_refcount_increment0().
|
||||
*/
|
||||
isc_refcount_increment0(&version->references,
|
||||
&cur_ref);
|
||||
INSIST(cur_ref == 1);
|
||||
INSIST(isc_refcount_increment0(&version->references) == 0);
|
||||
PREPEND(rbtdb->open_versions,
|
||||
rbtdb->current_version, link);
|
||||
resigned_list = version->resigned_list;
|
||||
@@ -2776,7 +2628,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
|
||||
sizeof(*changed));
|
||||
}
|
||||
if (event != NULL) {
|
||||
isc_refcount_increment(&rbtdb->references, NULL);
|
||||
isc_refcount_increment(&rbtdb->references);
|
||||
isc_task_send(rbtdb->task, &event);
|
||||
} else
|
||||
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
|
||||
@@ -4476,10 +4328,6 @@ check_stale_header(dns_rbtnode_t *node, rdatasetheader_t *header,
|
||||
rbtdb_search_t *search, rdatasetheader_t **header_prev)
|
||||
{
|
||||
|
||||
#if !defined(ISC_RWLOCK_USEATOMIC) || !defined(DNS_RBT_USEISCREFCOUNT)
|
||||
UNUSED(lock);
|
||||
#endif
|
||||
|
||||
if (!ACTIVE(header, search->now)) {
|
||||
dns_ttl_t stale = header->rdh_ttl +
|
||||
search->rbtdb->serve_stale_ttl;
|
||||
@@ -4514,7 +4362,7 @@ check_stale_header(dns_rbtnode_t *node, rdatasetheader_t *header,
|
||||
*/
|
||||
*locktype = isc_rwlocktype_write;
|
||||
|
||||
if (dns_rbtnode_refcurrent(node) == 0) {
|
||||
if (isc_refcount_current(&node->references) == 0) {
|
||||
isc_mem_t *mctx;
|
||||
|
||||
/*
|
||||
@@ -5327,15 +5175,11 @@ static void
|
||||
attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
dns_rbtnode_t *node = (dns_rbtnode_t *)source;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||
dns_rbtnode_refincrement(node, &refs);
|
||||
INSIST(refs != 0);
|
||||
NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||
isc_refcount_increment(&node->references);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
@@ -5491,14 +5335,16 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
dns_rbtnode_t *rbtnode = node;
|
||||
bool first;
|
||||
uint32_t refs;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
|
||||
isc_rwlocktype_read);
|
||||
|
||||
fprintf(out, "node %p, %u references, locknum = %u\n",
|
||||
rbtnode, dns_rbtnode_refcurrent(rbtnode),
|
||||
refs = isc_refcount_current(&rbtnode->references);
|
||||
fprintf(out, "node %p, %" PRIu32 " references, locknum = %u\n",
|
||||
rbtnode, refs,
|
||||
rbtnode->locknum);
|
||||
if (rbtnode->data != NULL) {
|
||||
rdatasetheader_t *current, *top_next;
|
||||
@@ -5763,7 +5609,6 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
|
||||
rbtdb_version_t *rbtversion = version;
|
||||
rbtdb_rdatasetiter_t *iterator;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
@@ -5779,9 +5624,7 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
else {
|
||||
INSIST(rbtversion->rbtdb == rbtdb);
|
||||
|
||||
isc_refcount_increment(&rbtversion->references,
|
||||
&refs);
|
||||
INSIST(refs > 1);
|
||||
(void)isc_refcount_increment(&rbtversion->references);
|
||||
}
|
||||
} else {
|
||||
if (now == 0)
|
||||
@@ -5796,15 +5639,10 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
iterator->common.version = (dns_dbversion_t *)rbtversion;
|
||||
iterator->common.now = now;
|
||||
|
||||
NODE_STRONGLOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||
|
||||
dns_rbtnode_refincrement(rbtnode, &refs);
|
||||
INSIST(refs != 0);
|
||||
isc_refcount_increment(&rbtnode->references);
|
||||
|
||||
iterator->current = NULL;
|
||||
|
||||
NODE_STRONGUNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||
|
||||
*iteratorp = (dns_rdatasetiter_t *)iterator;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
@@ -7836,9 +7674,7 @@ getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
|
||||
/* Note that the access to origin_node doesn't require a DB lock */
|
||||
onode = (dns_rbtnode_t *)rbtdb->origin_node;
|
||||
if (onode != NULL) {
|
||||
NODE_STRONGLOCK(&rbtdb->node_locks[onode->locknum].lock);
|
||||
new_reference(rbtdb, onode);
|
||||
NODE_STRONGUNLOCK(&rbtdb->node_locks[onode->locknum].lock);
|
||||
|
||||
*nodep = rbtdb->origin_node;
|
||||
} else {
|
||||
@@ -8360,9 +8196,7 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
|
||||
for (i = 0; i < (int)(rbtdb->node_lock_count); i++) {
|
||||
result = NODE_INITLOCK(&rbtdb->node_locks[i].lock);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = isc_refcount_init(&rbtdb->node_locks[i].references, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
NODE_DESTROYLOCK(&rbtdb->node_locks[i].lock);
|
||||
isc_refcount_init(&rbtdb->node_locks[i].references, 0);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
while (i-- > 0) {
|
||||
@@ -8471,11 +8305,7 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
|
||||
/*
|
||||
* Misc. Initialization.
|
||||
*/
|
||||
result = isc_refcount_init(&rbtdb->references, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
free_rbtdb(rbtdb, false, NULL);
|
||||
return (result);
|
||||
}
|
||||
isc_refcount_init(&rbtdb->references, 1);
|
||||
rbtdb->attributes = 0;
|
||||
rbtdb->task = NULL;
|
||||
rbtdb->serve_stale_ttl = 0;
|
||||
@@ -8488,7 +8318,7 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
|
||||
rbtdb->next_serial = 2;
|
||||
rbtdb->current_version = allocate_version(mctx, 1, 1, false);
|
||||
if (rbtdb->current_version == NULL) {
|
||||
isc_refcount_decrement(&rbtdb->references, NULL);
|
||||
isc_refcount_decrement(&rbtdb->references);
|
||||
free_rbtdb(rbtdb, false, NULL);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
@@ -8509,7 +8339,7 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
|
||||
isc_mem_put(mctx, rbtdb->current_version,
|
||||
sizeof(*rbtdb->current_version));
|
||||
rbtdb->current_version = NULL;
|
||||
isc_refcount_decrement(&rbtdb->references, NULL);
|
||||
isc_refcount_decrement(&rbtdb->references);
|
||||
free_rbtdb(rbtdb, false, NULL);
|
||||
return (result);
|
||||
}
|
||||
@@ -9452,9 +9282,7 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
|
||||
} else
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||
new_reference(rbtdb, node);
|
||||
NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||
|
||||
*nodep = rbtdbiter->node;
|
||||
|
||||
@@ -9475,13 +9303,8 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
|
||||
* expirenode() currently always returns success.
|
||||
*/
|
||||
if (expire_result == ISC_R_SUCCESS && node->down == NULL) {
|
||||
unsigned int refs;
|
||||
|
||||
rbtdbiter->deletions[rbtdbiter->delcnt++] = node;
|
||||
NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||
dns_rbtnode_refincrement(node, &refs);
|
||||
INSIST(refs != 0);
|
||||
NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||
isc_refcount_increment(&node->references);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9776,7 +9599,7 @@ free_gluetable(rbtdb_version_t *version) {
|
||||
cur = version->glue_table[i];
|
||||
while (cur != NULL) {
|
||||
cur_next = cur->next;
|
||||
/* dns_rbtnode_refdecrement(cur->node, NULL); */
|
||||
/* isc_refcount_decrement(&cur->node->references); */
|
||||
cur->node = NULL;
|
||||
free_gluelist(cur->glue_list, rbtdb);
|
||||
cur->glue_list = NULL;
|
||||
@@ -10204,7 +10027,7 @@ no_glue:
|
||||
* when named is terminated by a keyboard break. This doesn't
|
||||
* cleanup the node reference and keeps the process dangling.
|
||||
*/
|
||||
/* dns_rbtnode_refincrement0(node, NULL); */
|
||||
/* isc_refcount_increment0(&node->references); */
|
||||
cur->node = node;
|
||||
|
||||
if (ctx.glue_list == NULL) {
|
||||
@@ -10379,7 +10202,7 @@ expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
|
||||
* Caller must hold the node (write) lock.
|
||||
*/
|
||||
|
||||
if (dns_rbtnode_refcurrent(header->node) == 0) {
|
||||
if (isc_refcount_current(&header->node->references) == 0) {
|
||||
/*
|
||||
* If no one else is using the node, we can clean it up now.
|
||||
* We first need to gain a new reference to the node to meet a
|
||||
|
||||
+65
-74
@@ -1451,9 +1451,7 @@ dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, char *rps_cstr,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_mutex;
|
||||
|
||||
result = isc_refcount_init(&zones->refs, 1);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_refcount;
|
||||
isc_refcount_init(&zones->refs, 1);
|
||||
|
||||
zones->rps_cstr = rps_cstr;
|
||||
zones->rps_cstr_size = rps_cstr_size;
|
||||
@@ -1487,10 +1485,9 @@ cleanup_task:
|
||||
dns_rbt_destroy(&zones->rbt);
|
||||
|
||||
cleanup_rbt:
|
||||
isc_refcount_decrement(&zones->refs, NULL);
|
||||
(void)isc_refcount_decrement(&zones->refs);
|
||||
isc_refcount_destroy(&zones->refs);
|
||||
|
||||
cleanup_refcount:
|
||||
DESTROYLOCK(&zones->maint_lock);
|
||||
|
||||
cleanup_mutex:
|
||||
@@ -1519,9 +1516,7 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
|
||||
}
|
||||
|
||||
memset(zone, 0, sizeof(*zone));
|
||||
result = isc_refcount_init(&zone->refs, 1);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_refcount;
|
||||
isc_refcount_init(&zone->refs, 1);
|
||||
|
||||
result = isc_timer_create(rpzs->timermgr, isc_timertype_inactive,
|
||||
NULL, NULL, rpzs->updater,
|
||||
@@ -1573,10 +1568,9 @@ cleanup_ht:
|
||||
isc_timer_detach(&zone->updatetimer);
|
||||
|
||||
cleanup_timer:
|
||||
isc_refcount_decrement(&zone->refs, NULL);
|
||||
isc_refcount_decrement(&zone->refs);
|
||||
isc_refcount_destroy(&zone->refs);
|
||||
|
||||
cleanup_refcount:
|
||||
isc_mem_put(zone->rpzs->mctx, zone, sizeof(*zone));
|
||||
|
||||
return (result);
|
||||
@@ -2056,51 +2050,51 @@ cidr_free(dns_rpz_zones_t *rpzs) {
|
||||
static void
|
||||
rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) {
|
||||
dns_rpz_zone_t *rpz;
|
||||
unsigned int refs;
|
||||
|
||||
rpz = *rpzp;
|
||||
|
||||
if (isc_refcount_decrement(&rpz->refs) == 1) {
|
||||
isc_refcount_destroy(&rpz->refs);
|
||||
|
||||
if (dns_name_dynamic(&rpz->origin))
|
||||
dns_name_free(&rpz->origin, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->client_ip))
|
||||
dns_name_free(&rpz->client_ip, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->ip))
|
||||
dns_name_free(&rpz->ip, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->nsdname))
|
||||
dns_name_free(&rpz->nsdname, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->nsip))
|
||||
dns_name_free(&rpz->nsip, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->passthru))
|
||||
dns_name_free(&rpz->passthru, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->drop))
|
||||
dns_name_free(&rpz->drop, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->tcp_only))
|
||||
dns_name_free(&rpz->tcp_only, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->cname))
|
||||
dns_name_free(&rpz->cname, rpzs->mctx);
|
||||
if (rpz->db_registered)
|
||||
dns_db_updatenotify_unregister(rpz->db,
|
||||
dns_rpz_dbupdate_callback, rpz);
|
||||
if (rpz->dbversion != NULL)
|
||||
dns_db_closeversion(rpz->db, &rpz->dbversion,
|
||||
false);
|
||||
if (rpz->db)
|
||||
dns_db_detach(&rpz->db);
|
||||
isc_ht_destroy(&rpz->nodes);
|
||||
isc_timer_detach(&rpz->updatetimer);
|
||||
|
||||
isc_mem_put(rpzs->mctx, rpz, sizeof(*rpz));
|
||||
}
|
||||
|
||||
*rpzp = NULL;
|
||||
isc_refcount_decrement(&rpz->refs, &refs);
|
||||
if (refs != 0)
|
||||
return;
|
||||
isc_refcount_destroy(&rpz->refs);
|
||||
|
||||
if (dns_name_dynamic(&rpz->origin))
|
||||
dns_name_free(&rpz->origin, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->client_ip))
|
||||
dns_name_free(&rpz->client_ip, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->ip))
|
||||
dns_name_free(&rpz->ip, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->nsdname))
|
||||
dns_name_free(&rpz->nsdname, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->nsip))
|
||||
dns_name_free(&rpz->nsip, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->passthru))
|
||||
dns_name_free(&rpz->passthru, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->drop))
|
||||
dns_name_free(&rpz->drop, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->tcp_only))
|
||||
dns_name_free(&rpz->tcp_only, rpzs->mctx);
|
||||
if (dns_name_dynamic(&rpz->cname))
|
||||
dns_name_free(&rpz->cname, rpzs->mctx);
|
||||
if (rpz->db_registered)
|
||||
dns_db_updatenotify_unregister(rpz->db,
|
||||
dns_rpz_dbupdate_callback, rpz);
|
||||
if (rpz->dbversion != NULL)
|
||||
dns_db_closeversion(rpz->db, &rpz->dbversion,
|
||||
false);
|
||||
if (rpz->db)
|
||||
dns_db_detach(&rpz->db);
|
||||
isc_ht_destroy(&rpz->nodes);
|
||||
isc_timer_detach(&rpz->updatetimer);
|
||||
|
||||
isc_mem_put(rpzs->mctx, rpz, sizeof(*rpz));
|
||||
}
|
||||
|
||||
void
|
||||
dns_rpz_attach_rpzs(dns_rpz_zones_t *rpzs, dns_rpz_zones_t **rpzsp) {
|
||||
REQUIRE(rpzsp != NULL && *rpzsp == NULL);
|
||||
isc_refcount_increment(&rpzs->refs, NULL);
|
||||
isc_refcount_increment(&rpzs->refs);
|
||||
*rpzsp = rpzs;
|
||||
}
|
||||
|
||||
@@ -2112,46 +2106,43 @@ dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) {
|
||||
dns_rpz_zones_t *rpzs;
|
||||
dns_rpz_zone_t *rpz;
|
||||
dns_rpz_num_t rpz_num;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(rpzsp != NULL);
|
||||
rpzs = *rpzsp;
|
||||
REQUIRE(rpzs != NULL);
|
||||
|
||||
*rpzsp = NULL;
|
||||
isc_refcount_decrement(&rpzs->refs, &refs);
|
||||
if (refs != 0) {
|
||||
return;
|
||||
}
|
||||
if (isc_refcount_decrement(&rpzs->refs) == 1) {
|
||||
isc_refcount_destroy(&rpzs->refs);
|
||||
|
||||
/*
|
||||
* Forget the last of view's rpz machinery after the last reference.
|
||||
*/
|
||||
for (rpz_num = 0; rpz_num < DNS_RPZ_MAX_ZONES; ++rpz_num) {
|
||||
rpz = rpzs->zones[rpz_num];
|
||||
rpzs->zones[rpz_num] = NULL;
|
||||
if (rpz != NULL) {
|
||||
rpz_detach(&rpz, rpzs);
|
||||
/*
|
||||
* Forget the last of view's rpz machinery after the last reference.
|
||||
*/
|
||||
for (rpz_num = 0; rpz_num < DNS_RPZ_MAX_ZONES; ++rpz_num) {
|
||||
rpz = rpzs->zones[rpz_num];
|
||||
rpzs->zones[rpz_num] = NULL;
|
||||
if (rpz != NULL) {
|
||||
rpz_detach(&rpz, rpzs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rpzs->rps_cstr_size != 0) {
|
||||
if (rpzs->rps_cstr_size != 0) {
|
||||
#ifdef USE_DNSRPS
|
||||
librpz->client_detach(&rpzs->rps_client);
|
||||
librpz->client_detach(&rpzs->rps_client);
|
||||
#endif
|
||||
isc_mem_put(rpzs->mctx, rpzs->rps_cstr,
|
||||
rpzs->rps_cstr_size);
|
||||
}
|
||||
isc_mem_put(rpzs->mctx, rpzs->rps_cstr,
|
||||
rpzs->rps_cstr_size);
|
||||
}
|
||||
|
||||
cidr_free(rpzs);
|
||||
if (rpzs->rbt != NULL) {
|
||||
dns_rbt_destroy(&rpzs->rbt);
|
||||
cidr_free(rpzs);
|
||||
if (rpzs->rbt != NULL) {
|
||||
dns_rbt_destroy(&rpzs->rbt);
|
||||
}
|
||||
DESTROYLOCK(&rpzs->maint_lock);
|
||||
isc_rwlock_destroy(&rpzs->search_lock);
|
||||
isc_task_destroy(&rpzs->updater);
|
||||
isc_mem_putanddetach(&rpzs->mctx, rpzs, sizeof(*rpzs));
|
||||
}
|
||||
DESTROYLOCK(&rpzs->maint_lock);
|
||||
isc_rwlock_destroy(&rpzs->search_lock);
|
||||
isc_refcount_destroy(&rpzs->refs);
|
||||
isc_task_destroy(&rpzs->updater);
|
||||
isc_mem_putanddetach(&rpzs->mctx, rpzs, sizeof(*rpzs));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+11
-12
@@ -331,9 +331,8 @@ dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm,
|
||||
refs = 1;
|
||||
if (ring != NULL)
|
||||
refs++;
|
||||
ret = isc_refcount_init(&tkey->refs, refs);
|
||||
if (ret != ISC_R_SUCCESS)
|
||||
goto cleanup_creator;
|
||||
|
||||
isc_refcount_init(&tkey->refs, refs);
|
||||
|
||||
tkey->generated = generated;
|
||||
tkey->inception = inception;
|
||||
@@ -370,10 +369,11 @@ dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm,
|
||||
|
||||
cleanup_refs:
|
||||
tkey->magic = 0;
|
||||
while (refs-- > 0)
|
||||
isc_refcount_decrement(&tkey->refs, NULL);
|
||||
while (refs-- > 0) {
|
||||
(void)isc_refcount_decrement(&tkey->refs);
|
||||
}
|
||||
isc_refcount_destroy(&tkey->refs);
|
||||
cleanup_creator:
|
||||
|
||||
if (tkey->key != NULL)
|
||||
dst_key_free(&tkey->key);
|
||||
if (tkey->creator != NULL) {
|
||||
@@ -707,7 +707,7 @@ dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
|
||||
REQUIRE(VALID_TSIG_KEY(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
isc_refcount_increment(&source->refs, NULL);
|
||||
isc_refcount_increment(&source->refs);
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
@@ -736,16 +736,15 @@ tsigkey_free(dns_tsigkey_t *key) {
|
||||
void
|
||||
dns_tsigkey_detach(dns_tsigkey_t **keyp) {
|
||||
dns_tsigkey_t *key;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(keyp != NULL);
|
||||
REQUIRE(VALID_TSIG_KEY(*keyp));
|
||||
|
||||
key = *keyp;
|
||||
isc_refcount_decrement(&key->refs, &refs);
|
||||
|
||||
if (refs == 0)
|
||||
if (isc_refcount_decrement(&key->refs) == 1) {
|
||||
tsigkey_free(key);
|
||||
}
|
||||
|
||||
*keyp = NULL;
|
||||
}
|
||||
@@ -1785,7 +1784,7 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name,
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
#endif
|
||||
isc_refcount_increment(&key->refs, NULL);
|
||||
isc_refcount_increment(&key->refs);
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
adjust_lru(key);
|
||||
*tsigkey = key;
|
||||
@@ -1855,7 +1854,7 @@ dns_tsigkeyring_add(dns_tsig_keyring_t *ring, const dns_name_t *name,
|
||||
|
||||
result = keyring_add(ring, name, tkey);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
isc_refcount_increment(&tkey->refs, NULL);
|
||||
isc_refcount_increment(&tkey->refs);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
+4
-9
@@ -154,9 +154,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
||||
view->rdclass = rdclass;
|
||||
view->frozen = false;
|
||||
view->task = NULL;
|
||||
result = isc_refcount_init(&view->references, 1);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_fwdtable;
|
||||
isc_refcount_init(&view->references, 1);
|
||||
view->weakrefs = 0;
|
||||
view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
|
||||
DNS_VIEWATTR_REQSHUTDOWN);
|
||||
@@ -313,10 +311,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
||||
dns_tsigkeyring_detach(&view->dynamickeys);
|
||||
|
||||
cleanup_references:
|
||||
isc_refcount_decrement(&view->references, NULL);
|
||||
(void)isc_refcount_decrement(&view->references);
|
||||
isc_refcount_destroy(&view->references);
|
||||
|
||||
cleanup_fwdtable:
|
||||
if (view->fwdtable != NULL)
|
||||
dns_fwdtable_destroy(&view->fwdtable);
|
||||
|
||||
@@ -572,7 +569,7 @@ dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
|
||||
REQUIRE(DNS_VIEW_VALID(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
isc_refcount_increment(&source->references, NULL);
|
||||
isc_refcount_increment(&source->references);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
@@ -580,7 +577,6 @@ dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
|
||||
static void
|
||||
view_flushanddetach(dns_view_t **viewp, bool flush) {
|
||||
dns_view_t *view;
|
||||
unsigned int refs;
|
||||
bool done = false;
|
||||
|
||||
REQUIRE(viewp != NULL);
|
||||
@@ -589,8 +585,7 @@ view_flushanddetach(dns_view_t **viewp, bool flush) {
|
||||
|
||||
if (flush)
|
||||
view->flush = true;
|
||||
isc_refcount_decrement(&view->references, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&view->references) == 1) {
|
||||
dns_zone_t *mkzone = NULL, *rdzone = NULL;
|
||||
|
||||
LOCK(&view->lock);
|
||||
|
||||
+5
-23
@@ -178,17 +178,10 @@ typedef struct dns_include dns_include_t;
|
||||
do { result = isc_mutex_trylock(&(z)->lock); } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef ISC_RWLOCK_USEATOMIC
|
||||
#define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
|
||||
#define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
|
||||
#define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
|
||||
#define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
|
||||
#else
|
||||
#define ZONEDB_INITLOCK(l) isc_mutex_init(l)
|
||||
#define ZONEDB_DESTROYLOCK(l) DESTROYLOCK(l)
|
||||
#define ZONEDB_LOCK(l, t) LOCK(l)
|
||||
#define ZONEDB_UNLOCK(l, t) UNLOCK(l)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AFL
|
||||
extern bool dns_fuzzing_resolver;
|
||||
@@ -204,11 +197,7 @@ struct dns_zone {
|
||||
isc_mem_t *mctx;
|
||||
isc_refcount_t erefs;
|
||||
|
||||
#ifdef ISC_RWLOCK_USEATOMIC
|
||||
isc_rwlock_t dblock;
|
||||
#else
|
||||
isc_mutex_t dblock;
|
||||
#endif
|
||||
dns_db_t *db; /* Locked by dblock */
|
||||
|
||||
/* Locked */
|
||||
@@ -927,10 +916,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
|
||||
zone->db = NULL;
|
||||
zone->zmgr = NULL;
|
||||
ISC_LINK_INIT(zone, link);
|
||||
result = isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto free_dblock;
|
||||
}
|
||||
isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
|
||||
zone->irefs = 0;
|
||||
dns_name_init(&zone->origin, NULL);
|
||||
zone->strnamerd = NULL;
|
||||
@@ -1098,10 +1084,9 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
|
||||
isc_stats_detach(&zone->gluecachestats);
|
||||
|
||||
free_erefs:
|
||||
isc_refcount_decrement(&zone->erefs, NULL);
|
||||
(void)isc_refcount_decrement(&zone->erefs);
|
||||
isc_refcount_destroy(&zone->erefs);
|
||||
|
||||
free_dblock:
|
||||
ZONEDB_DESTROYLOCK(&zone->dblock);
|
||||
|
||||
free_mutex:
|
||||
@@ -5268,7 +5253,7 @@ void
|
||||
dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
|
||||
REQUIRE(DNS_ZONE_VALID(source));
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
isc_refcount_increment(&source->erefs, NULL);
|
||||
isc_refcount_increment(&source->erefs);
|
||||
*target = source;
|
||||
}
|
||||
|
||||
@@ -5277,16 +5262,13 @@ dns_zone_detach(dns_zone_t **zonep) {
|
||||
dns_zone_t *zone;
|
||||
dns_zone_t *raw = NULL;
|
||||
dns_zone_t *secure = NULL;
|
||||
unsigned int refs;
|
||||
bool free_now = false;
|
||||
|
||||
REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
|
||||
|
||||
zone = *zonep;
|
||||
|
||||
isc_refcount_decrement(&zone->erefs, &refs);
|
||||
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&zone->erefs) == 1) {
|
||||
LOCK_ZONE(zone);
|
||||
INSIST(zone != zone->raw);
|
||||
/*
|
||||
@@ -18654,7 +18636,7 @@ dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
|
||||
|
||||
|
||||
/* dns_zone_attach(raw, &zone->raw); */
|
||||
isc_refcount_increment(&raw->erefs, NULL);
|
||||
isc_refcount_increment(&raw->erefs);
|
||||
zone->raw = raw;
|
||||
|
||||
/* dns_zone_iattach(zone, &raw->secure); */
|
||||
|
||||
+3
-4
@@ -19,7 +19,6 @@ VERSION=@BIND9_VERSION@
|
||||
|
||||
CINCLUDES = -I${srcdir}/unix/include \
|
||||
-I${srcdir}/pthreads/include \
|
||||
-I${srcdir}/@ISC_ARCH_DIR@/include \
|
||||
-I./include \
|
||||
-I${srcdir}/include ${DNS_INCLUDES} @OPENSSL_INCLUDES@
|
||||
CDEFINES =
|
||||
@@ -54,7 +53,7 @@ OBJS = @ISC_EXTRA_OBJS@ pk11.@O@ pk11_result.@O@ \
|
||||
md5.@O@ mem.@O@ mutexblock.@O@ \
|
||||
netaddr.@O@ netscope.@O@ nonce.@O@ openssl_shim.@O@ pool.@O@ \
|
||||
parseint.@O@ portset.@O@ quota.@O@ radix.@O@ random.@O@ \
|
||||
ratelimiter.@O@ refcount.@O@ region.@O@ regex.@O@ result.@O@ \
|
||||
ratelimiter.@O@ region.@O@ regex.@O@ result.@O@ \
|
||||
rwlock.@O@ \
|
||||
serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ \
|
||||
string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \
|
||||
@@ -72,7 +71,7 @@ SRCS = @ISC_EXTRA_SRCS@ pk11.c pk11_result.c \
|
||||
md5.c mem.c mutexblock.c \
|
||||
netaddr.c netscope.c nonce.c openssl_shim.c pool.c \
|
||||
parseint.c portset.c quota.c radix.c random.c \
|
||||
ratelimiter.c refcount.c region.c regex.c result.c rwlock.c \
|
||||
ratelimiter.c region.c regex.c result.c rwlock.c \
|
||||
serial.c sha1.c sha2.c sockaddr.c stats.c string.c \
|
||||
strtoul.c symtab.c task.c taskpool.c timer.c \
|
||||
tm.c version.c
|
||||
@@ -83,7 +82,7 @@ LIBS = @OPENSSL_LIBS@ @LIBS@
|
||||
# Attempt to disable parallel processing.
|
||||
.NOTPARALLEL:
|
||||
.NO_PARALLEL:
|
||||
SUBDIRS = include unix nls pthreads @ISC_ARCH_DIR@
|
||||
SUBDIRS = include unix nls pthreads
|
||||
TARGETS = timestamp
|
||||
TESTDIRS = @UNITTESTS@
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = include
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = isc
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
HEADERS = atomic.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
|
||||
|
||||
install:: installdirs
|
||||
for i in ${HEADERS}; do \
|
||||
${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
|
||||
done
|
||||
|
||||
uninstall::
|
||||
for i in ${HEADERS}; do \
|
||||
rm -f ${DESTDIR}${includedir}/isc/$$i ; \
|
||||
done
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This code was written based on FreeBSD's kernel source whose copyright
|
||||
* follows:
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 Doug Rabson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/alpha/include/atomic.h,v 1.18.6.1 2004/09/13 21:52:04 wilko Exp $
|
||||
*/
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#ifdef ISC_PLATFORM_USEOSFASM
|
||||
#include <c_asm.h>
|
||||
|
||||
#pragma intrinsic(asm)
|
||||
|
||||
/*
|
||||
* This routine atomically increments the value stored in 'p' by 'val', and
|
||||
* returns the previous value. Memory access ordering around this function
|
||||
* can be critical, so we add explicit memory block instructions at the
|
||||
* beginning and the end of it (same for other functions).
|
||||
*/
|
||||
static inline int32_t
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
return (asm("mb;"
|
||||
"1:"
|
||||
"ldl_l %t0, 0(%a0);" /* load old value */
|
||||
"mov %t0, %v0;" /* copy the old value */
|
||||
"addl %t0, %a1, %t0;" /* calculate new value */
|
||||
"stl_c %t0, 0(%a0);" /* attempt to store */
|
||||
"beq %t0, 1b;" /* spin if failed */
|
||||
"mb;",
|
||||
p, val));
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine atomically stores the value 'val' in 'p'.
|
||||
*/
|
||||
static inline void
|
||||
isc_atomic_store(int32_t *p, int32_t val) {
|
||||
(void)asm("mb;"
|
||||
"1:"
|
||||
"ldl_l %t0, 0(%a0);" /* load old value */
|
||||
"mov %a1, %t0;" /* value to store */
|
||||
"stl_c %t0, 0(%a0);" /* attempt to store */
|
||||
"beq %t0, 1b;" /* spin if failed */
|
||||
"mb;",
|
||||
p, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine atomically replaces the value in 'p' with 'val', if the
|
||||
* original value is equal to 'cmpval'. The original value is returned in any
|
||||
* case.
|
||||
*/
|
||||
static inline int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
|
||||
|
||||
return(asm("mb;"
|
||||
"1:"
|
||||
"ldl_l %t0, 0(%a0);" /* load old value */
|
||||
"mov %t0, %v0;" /* copy the old value */
|
||||
"cmpeq %t0, %a1, %t0;" /* compare */
|
||||
"beq %t0, 2f;" /* exit if not equal */
|
||||
"mov %a2, %t0;" /* value to store */
|
||||
"stl_c %t0, 0(%a0);" /* attempt to store */
|
||||
"beq %t0, 1b;" /* if it failed, spin */
|
||||
"2:"
|
||||
"mb;",
|
||||
p, cmpval, val));
|
||||
}
|
||||
#elif defined (ISC_PLATFORM_USEGCCASM)
|
||||
static inline int32_t
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
int32_t temp, prev;
|
||||
|
||||
__asm__ volatile(
|
||||
"mb;"
|
||||
"1:"
|
||||
"ldl_l %0, %1;" /* load old value */
|
||||
"mov %0, %2;" /* copy the old value */
|
||||
"addl %0, %3, %0;" /* calculate new value */
|
||||
"stl_c %0, %1;" /* attempt to store */
|
||||
"beq %0, 1b;" /* spin if failed */
|
||||
"mb;"
|
||||
: "=&r"(temp), "+m"(*p), "=&r"(prev)
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
|
||||
return (prev);
|
||||
}
|
||||
|
||||
static inline void
|
||||
isc_atomic_store(int32_t *p, int32_t val) {
|
||||
int32_t temp;
|
||||
|
||||
__asm__ volatile(
|
||||
"mb;"
|
||||
"1:"
|
||||
"ldl_l %0, %1;" /* load old value */
|
||||
"mov %2, %0;" /* value to store */
|
||||
"stl_c %0, %1;" /* attempt to store */
|
||||
"beq %0, 1b;" /* if it failed, spin */
|
||||
"mb;"
|
||||
: "=&r"(temp), "+m"(*p)
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
|
||||
int32_t temp, prev;
|
||||
|
||||
__asm__ volatile(
|
||||
"mb;"
|
||||
"1:"
|
||||
"ldl_l %0, %1;" /* load old value */
|
||||
"mov %0, %2;" /* copy the old value */
|
||||
"cmpeq %0, %3, %0;" /* compare */
|
||||
"beq %0, 2f;" /* exit if not equal */
|
||||
"mov %4, %0;" /* value to store */
|
||||
"stl_c %0, %1;" /* attempt to store */
|
||||
"beq %0, 1b;" /* if it failed, spin */
|
||||
"2:"
|
||||
"mb;"
|
||||
: "=&r"(temp), "+m"(*p), "=&r"(prev)
|
||||
: "r"(cmpval), "r"(val)
|
||||
: "memory");
|
||||
|
||||
return (prev);
|
||||
}
|
||||
#else
|
||||
|
||||
#error "unsupported compiler. disable atomic ops by --disable-atomic"
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = include
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = isc
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
HEADERS = atomic.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
|
||||
|
||||
install:: installdirs
|
||||
for i in ${HEADERS}; do \
|
||||
${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
|
||||
done
|
||||
|
||||
uninstall::
|
||||
for i in ${HEADERS}; do \
|
||||
rm -f ${DESTDIR}${includedir}/isc/$$i ; \
|
||||
done
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#ifdef ISC_PLATFORM_USEGCCASM
|
||||
/*
|
||||
* This routine atomically increments the value stored in 'p' by 'val', and
|
||||
* returns the previous value.
|
||||
*
|
||||
* Open issue: can 'fetchadd' make the code faster for some particular values
|
||||
* (e.g., 1 and -1)?
|
||||
*/
|
||||
static inline int32_t
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((unused))
|
||||
#endif
|
||||
isc_atomic_xadd(int32_t *p, int32_t val)
|
||||
{
|
||||
int32_t prev, swapped;
|
||||
|
||||
for (prev = *(volatile int32_t *)p; ; prev = swapped) {
|
||||
swapped = prev + val;
|
||||
__asm__ volatile(
|
||||
"mov ar.ccv=%2;;"
|
||||
"cmpxchg4.acq %0=%4,%3,ar.ccv"
|
||||
: "=r" (swapped), "=m" (*p)
|
||||
: "r" (prev), "r" (swapped), "m" (*p)
|
||||
: "memory");
|
||||
if (swapped == prev)
|
||||
break;
|
||||
}
|
||||
|
||||
return (prev);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine atomically stores the value 'val' in 'p'.
|
||||
*/
|
||||
static inline void
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((unused))
|
||||
#endif
|
||||
isc_atomic_store(int32_t *p, int32_t val)
|
||||
{
|
||||
__asm__ volatile(
|
||||
"st4.rel %0=%1"
|
||||
: "=m" (*p)
|
||||
: "r" (val)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine atomically replaces the value in 'p' with 'val', if the
|
||||
* original value is equal to 'cmpval'. The original value is returned in any
|
||||
* case.
|
||||
*/
|
||||
static inline int32_t
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((unused))
|
||||
#endif
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
__asm__ volatile(
|
||||
"mov ar.ccv=%2;;"
|
||||
"cmpxchg4.acq %0=%4,%3,ar.ccv"
|
||||
: "=r" (ret), "=m" (*p)
|
||||
: "r" (cmpval), "r" (val), "m" (*p)
|
||||
: "memory");
|
||||
|
||||
return (ret);
|
||||
}
|
||||
#else /* !ISC_PLATFORM_USEGCCASM */
|
||||
|
||||
#error "unsupported compiler. disable atomic ops by --disable-atomic"
|
||||
|
||||
#endif
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
@@ -18,7 +18,7 @@ VERSION=@BIND9_VERSION@
|
||||
# machine generated. The latter are handled specially in the
|
||||
# install target below.
|
||||
#
|
||||
HEADERS = aes.h app.h assertions.h backtrace.h base32.h base64.h \
|
||||
HEADERS = aes.h app.h assertions.h atomic.h backtrace.h base32.h base64.h \
|
||||
bind9.h buffer.h bufferlist.h \
|
||||
commandline.h counter.h crc64.h deprecated.h \
|
||||
errno.h error.h event.h eventclass.h \
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
/* This file is inherently empty. */
|
||||
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
#if HAVE_STDATOMIC_H
|
||||
#include <stdatomic.h>
|
||||
#else
|
||||
#include <isc/stdatomic.h>
|
||||
#endif
|
||||
@@ -38,7 +38,7 @@ typedef void (*isc_memfree_t)(void *, void *);
|
||||
* allocation and freeing by file and line number.
|
||||
*/
|
||||
#ifndef ISC_MEM_TRACKLINES
|
||||
#define ISC_MEM_TRACKLINES 1
|
||||
#define ISC_MEM_TRACKLINES 0
|
||||
#endif
|
||||
|
||||
/*%
|
||||
|
||||
@@ -248,57 +248,6 @@
|
||||
*/
|
||||
@ISC_PLATFORM_HAVESYSUNH@
|
||||
|
||||
/*
|
||||
* If the "xadd" operation is available on this architecture,
|
||||
* ISC_PLATFORM_HAVEXADD will be defined.
|
||||
*/
|
||||
@ISC_PLATFORM_HAVEXADD@
|
||||
|
||||
/*
|
||||
* If the "xaddq" operation (64bit xadd) is available on this architecture,
|
||||
* ISC_PLATFORM_HAVEXADDQ will be defined.
|
||||
*/
|
||||
@ISC_PLATFORM_HAVEXADDQ@
|
||||
|
||||
/*
|
||||
* If the 32-bit "atomic swap" operation is available on this
|
||||
* architecture, ISC_PLATFORM_HAVEATOMICSTORE" will be defined.
|
||||
*/
|
||||
@ISC_PLATFORM_HAVEATOMICSTORE@
|
||||
|
||||
/*
|
||||
* If the 64-bit "atomic swap" operation is available on this
|
||||
* architecture, ISC_PLATFORM_HAVEATOMICSTORE" will be defined.
|
||||
*/
|
||||
@ISC_PLATFORM_HAVEATOMICSTOREQ@
|
||||
|
||||
/*
|
||||
* If the "compare-and-exchange" operation is available on this architecture,
|
||||
* ISC_PLATFORM_HAVECMPXCHG will be defined.
|
||||
*/
|
||||
@ISC_PLATFORM_HAVECMPXCHG@
|
||||
|
||||
/*
|
||||
* If <stdatomic.h> is available on this architecture,
|
||||
* ISC_PLATFORM_HAVESTDATOMIC will be defined.
|
||||
*/
|
||||
@ISC_PLATFORM_HAVESTDATOMIC@
|
||||
|
||||
/*
|
||||
* Define if gcc ASM extension is available
|
||||
*/
|
||||
@ISC_PLATFORM_USEGCCASM@
|
||||
|
||||
/*
|
||||
* Define if Tru64 style ASM syntax must be used.
|
||||
*/
|
||||
@ISC_PLATFORM_USEOSFASM@
|
||||
|
||||
/*
|
||||
* Define if the standard __asm function must be used.
|
||||
*/
|
||||
@ISC_PLATFORM_USESTDASM@
|
||||
|
||||
/*
|
||||
* Define with the busy wait nop asm or function call.
|
||||
*/
|
||||
@@ -319,12 +268,6 @@
|
||||
*** Windows dll support.
|
||||
***/
|
||||
|
||||
/*
|
||||
* Define if MacOS style of PPC assembly must be used.
|
||||
* e.g. "r6", not "6", for register six.
|
||||
*/
|
||||
@ISC_PLATFORM_USEMACASM@
|
||||
|
||||
#ifndef ISC_PLATFORM_USEDECLSPEC
|
||||
#define LIBISC_EXTERNAL_DATA
|
||||
#define LIBDNS_EXTERNAL_DATA
|
||||
|
||||
+18
-164
@@ -9,23 +9,20 @@
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ISC_REFCOUNT_H
|
||||
#define ISC_REFCOUNT_H 1
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/error.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVESTDATOMIC)
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
#define DONT_WORRY_BE_HAPPY 1
|
||||
|
||||
/*! \file isc/refcount.h
|
||||
* \brief Implements a locked reference counter.
|
||||
@@ -43,7 +40,7 @@ ISC_LANG_BEGINDECLS
|
||||
*/
|
||||
|
||||
/*
|
||||
* isc_result_t
|
||||
* void
|
||||
* isc_refcount_init(isc_refcount_t *ref, unsigned int n);
|
||||
*
|
||||
* Initialize the reference counter. There will be 'n' initial references.
|
||||
@@ -94,168 +91,25 @@ ISC_LANG_BEGINDECLS
|
||||
/*
|
||||
* Sample implementations
|
||||
*/
|
||||
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE)) || defined(ISC_PLATFORM_HAVEXADD)
|
||||
#define ISC_REFCOUNT_HAVEATOMIC 1
|
||||
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE))
|
||||
#define ISC_REFCOUNT_HAVESTDATOMIC 1
|
||||
#endif
|
||||
|
||||
typedef struct isc_refcount {
|
||||
#if defined(ISC_REFCOUNT_HAVESTDATOMIC)
|
||||
atomic_int_fast32_t refs;
|
||||
#else
|
||||
int32_t refs;
|
||||
#endif
|
||||
} isc_refcount_t;
|
||||
typedef uint32_t isc_refcount_t;
|
||||
|
||||
#if defined(ISC_REFCOUNT_HAVESTDATOMIC)
|
||||
#define isc_refcount_init(target, value) \
|
||||
ck_pr_store_32(target, value)
|
||||
|
||||
#define isc_refcount_current(rp) \
|
||||
((unsigned int)(atomic_load_explicit(&(rp)->refs, \
|
||||
memory_order_relaxed)))
|
||||
#define isc_refcount_destroy(rp) ISC_REQUIRE(isc_refcount_current(rp) == 0)
|
||||
#define isc_refcount_current(target) \
|
||||
ck_pr_load_32((const isc_refcount_t *)target)
|
||||
|
||||
#define isc_refcount_increment0(rp, tp) \
|
||||
do { \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
int32_t prev; \
|
||||
prev = atomic_fetch_add_explicit \
|
||||
(&(rp)->refs, 1, memory_order_relaxed); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = prev + 1; \
|
||||
} while (0)
|
||||
#define isc_refcount_destroy(target) \
|
||||
ISC_REQUIRE(isc_refcount_current(target) == 0)
|
||||
|
||||
#define isc_refcount_increment(rp, tp) \
|
||||
do { \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
int32_t prev; \
|
||||
prev = atomic_fetch_add_explicit \
|
||||
(&(rp)->refs, 1, memory_order_relaxed); \
|
||||
ISC_REQUIRE(prev > 0); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = prev + 1; \
|
||||
} while (0)
|
||||
#define isc_refcount_increment0(target) \
|
||||
ck_pr_faa_32(target, 1)
|
||||
|
||||
#define isc_refcount_decrement(rp, tp) \
|
||||
do { \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
int32_t prev; \
|
||||
prev = atomic_fetch_sub_explicit \
|
||||
(&(rp)->refs, 1, memory_order_relaxed); \
|
||||
ISC_REQUIRE(prev > 0); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = prev - 1; \
|
||||
} while (0)
|
||||
#define isc_refcount_increment(target) \
|
||||
ck_pr_faa_32(target, 1)
|
||||
|
||||
#else /* ISC_REFCOUNT_HAVESTDATOMIC */
|
||||
|
||||
#define isc_refcount_current(rp) \
|
||||
((unsigned int)(isc_atomic_xadd(&(rp)->refs, 0)))
|
||||
#define isc_refcount_destroy(rp) ISC_REQUIRE(isc_refcount_current(rp) == 0)
|
||||
|
||||
#define isc_refcount_increment0(rp, tp) \
|
||||
do { \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
int32_t prev; \
|
||||
prev = isc_atomic_xadd(&(rp)->refs, 1); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = prev + 1; \
|
||||
} while (0)
|
||||
|
||||
#define isc_refcount_increment(rp, tp) \
|
||||
do { \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
int32_t prev; \
|
||||
prev = isc_atomic_xadd(&(rp)->refs, 1); \
|
||||
ISC_REQUIRE(prev > 0); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = prev + 1; \
|
||||
} while (0)
|
||||
|
||||
#define isc_refcount_decrement(rp, tp) \
|
||||
do { \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
int32_t prev; \
|
||||
prev = isc_atomic_xadd(&(rp)->refs, -1); \
|
||||
ISC_REQUIRE(prev > 0); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = prev - 1; \
|
||||
} while (0)
|
||||
|
||||
#endif /* ISC_REFCOUNT_HAVESTDATOMIC */
|
||||
|
||||
#else /* ISC_PLATFORM_HAVEXADD */
|
||||
|
||||
typedef struct isc_refcount {
|
||||
int refs;
|
||||
isc_mutex_t lock;
|
||||
} isc_refcount_t;
|
||||
|
||||
/*% Destroys a reference counter. */
|
||||
#define isc_refcount_destroy(rp) \
|
||||
do { \
|
||||
isc_result_t _result; \
|
||||
ISC_REQUIRE((rp)->refs == 0); \
|
||||
_result = isc_mutex_destroy(&(rp)->lock); \
|
||||
ISC_ERROR_RUNTIMECHECK(_result == ISC_R_SUCCESS); \
|
||||
} while (0)
|
||||
|
||||
#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
|
||||
|
||||
/*%
|
||||
* Increments the reference count, returning the new value in
|
||||
* 'tp' if it's not NULL.
|
||||
*/
|
||||
#define isc_refcount_increment0(rp, tp) \
|
||||
do { \
|
||||
isc_result_t _result; \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
_result = isc_mutex_lock(&(rp)->lock); \
|
||||
ISC_ERROR_RUNTIMECHECK(_result == ISC_R_SUCCESS); \
|
||||
++((rp)->refs); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = ((rp)->refs); \
|
||||
_result = isc_mutex_unlock(&(rp)->lock); \
|
||||
ISC_ERROR_RUNTIMECHECK(_result == ISC_R_SUCCESS); \
|
||||
} while (0)
|
||||
|
||||
#define isc_refcount_increment(rp, tp) \
|
||||
do { \
|
||||
isc_result_t _result; \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
_result = isc_mutex_lock(&(rp)->lock); \
|
||||
ISC_ERROR_RUNTIMECHECK(_result == ISC_R_SUCCESS); \
|
||||
ISC_REQUIRE((rp)->refs > 0); \
|
||||
++((rp)->refs); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = ((rp)->refs); \
|
||||
_result = isc_mutex_unlock(&(rp)->lock); \
|
||||
ISC_ERROR_RUNTIMECHECK(_result == ISC_R_SUCCESS); \
|
||||
} while (0)
|
||||
|
||||
/*%
|
||||
* Decrements the reference count, returning the new value in 'tp'
|
||||
* if it's not NULL.
|
||||
*/
|
||||
#define isc_refcount_decrement(rp, tp) \
|
||||
do { \
|
||||
isc_result_t _result; \
|
||||
unsigned int *_tmp = (unsigned int *)(tp); \
|
||||
_result = isc_mutex_lock(&(rp)->lock); \
|
||||
ISC_ERROR_RUNTIMECHECK(_result == ISC_R_SUCCESS); \
|
||||
ISC_REQUIRE((rp)->refs > 0); \
|
||||
--((rp)->refs); \
|
||||
if (_tmp != NULL) \
|
||||
*_tmp = ((rp)->refs); \
|
||||
_result = isc_mutex_unlock(&(rp)->lock); \
|
||||
ISC_ERROR_RUNTIMECHECK(_result == ISC_R_SUCCESS); \
|
||||
} while (0)
|
||||
|
||||
#endif /* (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE)) || defined(ISC_PLATFORM_HAVEXADD) */
|
||||
|
||||
isc_result_t
|
||||
isc_refcount_init(isc_refcount_t *ref, unsigned int n);
|
||||
#define isc_refcount_decrement(target) \
|
||||
ck_pr_faa_32(target, -1)
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISC_REFCOUNT_H */
|
||||
|
||||
@@ -17,14 +17,10 @@
|
||||
|
||||
/*! \file isc/rwlock.h */
|
||||
|
||||
#include <isc/condition.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
#include <ck_rwlock.h>
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVESTDATOMIC)
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
#include <isc/lang.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
@@ -34,79 +30,7 @@ typedef enum {
|
||||
isc_rwlocktype_write
|
||||
} isc_rwlocktype_t;
|
||||
|
||||
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE)) || (defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG))
|
||||
#define ISC_RWLOCK_USEATOMIC 1
|
||||
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE))
|
||||
#define ISC_RWLOCK_USESTDATOMIC 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct isc_rwlock {
|
||||
/* Unlocked. */
|
||||
unsigned int magic;
|
||||
isc_mutex_t lock;
|
||||
int32_t spins;
|
||||
|
||||
#if defined(ISC_RWLOCK_USEATOMIC)
|
||||
/*
|
||||
* When some atomic instructions with hardware assistance are
|
||||
* available, rwlock will use those so that concurrent readers do not
|
||||
* interfere with each other through mutex as long as no writers
|
||||
* appear, massively reducing the lock overhead in the typical case.
|
||||
*
|
||||
* The basic algorithm of this approach is the "simple
|
||||
* writer-preference lock" shown in the following URL:
|
||||
* http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html
|
||||
* but our implementation does not rely on the spin lock unlike the
|
||||
* original algorithm to be more portable as a user space application.
|
||||
*/
|
||||
|
||||
/* Read or modified atomically. */
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
atomic_int_fast32_t write_requests;
|
||||
atomic_int_fast32_t write_completions;
|
||||
atomic_int_fast32_t cnt_and_flag;
|
||||
#else
|
||||
int32_t write_requests;
|
||||
int32_t write_completions;
|
||||
int32_t cnt_and_flag;
|
||||
#endif
|
||||
|
||||
/* Locked by lock. */
|
||||
isc_condition_t readable;
|
||||
isc_condition_t writeable;
|
||||
unsigned int readers_waiting;
|
||||
|
||||
/* Locked by rwlock itself. */
|
||||
unsigned int write_granted;
|
||||
|
||||
/* Unlocked. */
|
||||
unsigned int write_quota;
|
||||
|
||||
#else /* ISC_RWLOCK_USEATOMIC */
|
||||
|
||||
/*%< Locked by lock. */
|
||||
isc_condition_t readable;
|
||||
isc_condition_t writeable;
|
||||
isc_rwlocktype_t type;
|
||||
|
||||
/*% The number of threads that have the lock. */
|
||||
unsigned int active;
|
||||
|
||||
/*%
|
||||
* The number of lock grants made since the lock was last switched
|
||||
* from reading to writing or vice versa; used in determining
|
||||
* when the quota is reached and it is time to switch.
|
||||
*/
|
||||
unsigned int granted;
|
||||
|
||||
unsigned int readers_waiting;
|
||||
unsigned int writers_waiting;
|
||||
unsigned int read_quota;
|
||||
unsigned int write_quota;
|
||||
isc_rwlocktype_t original;
|
||||
#endif /* ISC_RWLOCK_USEATOMIC */
|
||||
};
|
||||
#define isc_rwlock_t ck_rwlock_t
|
||||
|
||||
isc_result_t
|
||||
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#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 int_fast32_t atomic_int_fast32_t;
|
||||
typedef uint_fast32_t atomic_uint_fast32_t;
|
||||
typedef int_fast64_t atomic_int_fast64_t;
|
||||
typedef uint_fast64_t atomic_uint_fast64_t;
|
||||
|
||||
#if defined(__CLANG_ATOMICS) /* __c11_atomic builtins */
|
||||
#define atomic_init(obj, desired) \
|
||||
__c11_atomic_init(obj, desired)
|
||||
#define atomic_load_explicit(obj, order) \
|
||||
__c11_atomic_load(obj, order)
|
||||
#define atomic_store_explicit(obj, desired, order) \
|
||||
__c11_atomic_store(obj, desired, order)
|
||||
#define atomic_fetch_add_explicit(obj, arg, order) \
|
||||
__c11_atomic_fetch_add(obj, arg, order)
|
||||
#define atomic_fetch_sub_explicit(obj, arg, order) \
|
||||
__c11_atomic_fetch_sub(obj, arg, order)
|
||||
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \
|
||||
__c11_atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail)
|
||||
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail) \
|
||||
__c11_atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail)
|
||||
#elif defined(__GNUC_ATOMICS) /* __atomic builtins */
|
||||
#define atomic_init(obj, desired) \
|
||||
(*obj = desired)
|
||||
#define atomic_load_explicit(obj, order) \
|
||||
__atomic_load_n(obj, order)
|
||||
#define atomic_store_explicit(obj, desired, order) \
|
||||
__atomic_store_n(obj, desired, order)
|
||||
#define atomic_fetch_add_explicit(obj, arg, order) \
|
||||
__atomic_fetch_add(obj, arg, order)
|
||||
#define atomic_fetch_sub_explicit(obj, arg, order) \
|
||||
__atomic_fetch_sub(obj, arg, order)
|
||||
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \
|
||||
__atomic_compare_exchange_n(obj, expected, desired, 0, succ, fail)
|
||||
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail) \
|
||||
__atomic_compare_exchange_n(obj, expected, desired, 1, succ, fail)
|
||||
#else /* __sync builtins */
|
||||
#define atomic_init(obj, desired) \
|
||||
(*obj = desired)
|
||||
#define atomic_load_explicit(obj, order) \
|
||||
__sync_fetch_and_add(obj, 0)
|
||||
#define atomic_store_explicit(obj, desired, order) \
|
||||
do { \
|
||||
__sync_synchronize(); \
|
||||
*obj = desired; \
|
||||
__sync_synchronize(); \
|
||||
} while (0);
|
||||
#define atomic_fetch_add_explicit(obj, arg, order) \
|
||||
__sync_fetch_and_add(obj, arg)
|
||||
#define atomic_fetch_sub_explicit(obj, arg, order) \
|
||||
__sync_fetch_and_sub(obj, arg, order)
|
||||
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \
|
||||
({ \
|
||||
__typeof__(obj) __v; \
|
||||
_Bool __r; \
|
||||
__v = __sync_val_compare_and_swap(obj, *(expected), desired); \
|
||||
__r = *(expected) == __v; \
|
||||
*(expected) = __v; \
|
||||
__r; \
|
||||
})
|
||||
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail) \
|
||||
atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail)
|
||||
#endif
|
||||
|
||||
#define atomic_load(obj) \
|
||||
atomic_load_explicit(obj, memory_order_seq_cst)
|
||||
#define atomic_store(obj) \
|
||||
atomic_store_explicit(obj, memory_order_seq_cst)
|
||||
#define atomic_fetch_add(obj) \
|
||||
atomic_fetch_add_explicit(obj, arg, memory_order_seq_cst)
|
||||
#define atomic_fetch_sub(obj) \
|
||||
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)
|
||||
+47
-415
@@ -20,6 +20,8 @@
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <ck_queue.h>
|
||||
|
||||
#include <isc/bind9.h>
|
||||
#include <isc/json.h>
|
||||
#include <isc/magic.h>
|
||||
@@ -27,6 +29,7 @@
|
||||
#include <isc/mem.h>
|
||||
#include <isc/msgs.h>
|
||||
#include <isc/once.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/print.h>
|
||||
@@ -59,24 +62,8 @@ LIBISC_EXTERNAL_DATA unsigned int isc_mem_defaultflags = ISC_MEMFLAG_DEFAULT;
|
||||
typedef struct isc__mem isc__mem_t;
|
||||
typedef struct isc__mempool isc__mempool_t;
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
typedef struct debuglink debuglink_t;
|
||||
struct debuglink {
|
||||
ISC_LINK(debuglink_t) link;
|
||||
const void *ptr;
|
||||
size_t size;
|
||||
const char *file;
|
||||
unsigned int line;
|
||||
};
|
||||
|
||||
typedef ISC_LIST(debuglink_t) debuglist_t;
|
||||
|
||||
#define FLARG_PASS , file, line
|
||||
#define FLARG , const char *file, unsigned int line
|
||||
#else
|
||||
#define FLARG_PASS
|
||||
#define FLARG
|
||||
#endif
|
||||
|
||||
typedef struct element element;
|
||||
struct element {
|
||||
@@ -106,10 +93,9 @@ struct stats {
|
||||
|
||||
/* List of all active memory contexts. */
|
||||
|
||||
static ISC_LIST(isc__mem_t) contexts;
|
||||
static CK_LIST_HEAD(contexts_list, isc__mem) contexts = CK_LIST_HEAD_INITIALIZER(contexts);
|
||||
|
||||
static isc_once_t once = ISC_ONCE_INIT;
|
||||
static isc_mutex_t contextslock;
|
||||
static isc_mutex_t createlock;
|
||||
|
||||
/*%
|
||||
@@ -128,7 +114,7 @@ struct isc__mem {
|
||||
size_t max_size;
|
||||
bool checkfree;
|
||||
struct stats * stats;
|
||||
unsigned int references;
|
||||
isc_refcount_t references;
|
||||
char name[16];
|
||||
void * tag;
|
||||
size_t quota;
|
||||
@@ -143,8 +129,7 @@ struct isc__mem {
|
||||
bool is_overmem;
|
||||
isc_mem_water_t water;
|
||||
void * water_arg;
|
||||
ISC_LIST(isc__mempool_t) pools;
|
||||
unsigned int poolcnt;
|
||||
CK_LIST_HEAD(pool_list, isc__mempool) pools;
|
||||
|
||||
/* ISC_MEMFLAG_INTERNAL */
|
||||
size_t mem_target;
|
||||
@@ -156,13 +141,8 @@ struct isc__mem {
|
||||
unsigned char * lowest;
|
||||
unsigned char * highest;
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
debuglist_t * debuglist;
|
||||
size_t debuglistcnt;
|
||||
#endif
|
||||
|
||||
unsigned int memalloc_failures;
|
||||
ISC_LINK(isc__mem_t) link;
|
||||
CK_LIST_ENTRY(isc__mem) link;
|
||||
};
|
||||
|
||||
#define MEMPOOL_MAGIC ISC_MAGIC('M', 'E', 'M', 'p')
|
||||
@@ -174,7 +154,6 @@ struct isc__mempool {
|
||||
isc_mutex_t *lock; /*%< optional lock */
|
||||
isc__mem_t *mctx; /*%< our memory context */
|
||||
/*%< locked via the memory context's lock */
|
||||
ISC_LINK(isc__mempool_t) link; /*%< next pool in this mem context */
|
||||
/*%< optionally locked from here down */
|
||||
element *items; /*%< low water item list */
|
||||
size_t size; /*%< size of each item on this pool */
|
||||
@@ -189,35 +168,16 @@ struct isc__mempool {
|
||||
#if ISC_MEMPOOL_NAMES
|
||||
char name[16]; /*%< printed name in stats reports */
|
||||
#endif
|
||||
CK_LIST_ENTRY(isc__mempool) link;
|
||||
};
|
||||
|
||||
/*
|
||||
* Private Inline-able.
|
||||
*/
|
||||
|
||||
#if ! ISC_MEM_TRACKLINES
|
||||
#define ADD_TRACE(a, b, c, d, e)
|
||||
#define DELETE_TRACE(a, b, c, d, e)
|
||||
#define ISC_MEMFUNC_SCOPE
|
||||
#else
|
||||
#define TRACE_OR_RECORD (ISC_MEM_DEBUGTRACE|ISC_MEM_DEBUGRECORD)
|
||||
#define ADD_TRACE(a, b, c, d, e) \
|
||||
do { \
|
||||
if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \
|
||||
b != NULL)) \
|
||||
add_trace_entry(a, b, c, d, e); \
|
||||
} while (0)
|
||||
#define DELETE_TRACE(a, b, c, d, e) \
|
||||
do { \
|
||||
if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \
|
||||
b != NULL)) \
|
||||
delete_trace_entry(a, b, c, d, e); \
|
||||
} while(0)
|
||||
|
||||
static void
|
||||
print_active(isc__mem_t *ctx, FILE *out);
|
||||
|
||||
#endif /* ISC_MEM_TRACKLINES */
|
||||
|
||||
/*%
|
||||
* The following are intended for internal use (indicated by "isc__"
|
||||
@@ -373,85 +333,6 @@ static struct isc__mempoolmethods {
|
||||
(void *)isc_mempool_getfillcount
|
||||
};
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
/*!
|
||||
* mctx must be locked.
|
||||
*/
|
||||
static void
|
||||
add_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size FLARG) {
|
||||
debuglink_t *dl;
|
||||
uint32_t hash;
|
||||
uint32_t idx;
|
||||
|
||||
if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
|
||||
fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_ADDTRACE,
|
||||
"add %p size %u "
|
||||
"file %s line %u mctx %p\n"),
|
||||
ptr, size, file, line, mctx);
|
||||
|
||||
if (mctx->debuglist == NULL)
|
||||
return;
|
||||
|
||||
hash = isc_hash_function(&ptr, sizeof(ptr), true, NULL);
|
||||
idx = hash % DEBUG_TABLE_COUNT;
|
||||
|
||||
dl = malloc(sizeof(debuglink_t));
|
||||
INSIST(dl != NULL);
|
||||
mctx->malloced += sizeof(debuglink_t);
|
||||
if (mctx->malloced > mctx->maxmalloced)
|
||||
mctx->maxmalloced = mctx->malloced;
|
||||
|
||||
ISC_LINK_INIT(dl, link);
|
||||
dl->ptr = ptr;
|
||||
dl->size = size;
|
||||
dl->file = file;
|
||||
dl->line = line;
|
||||
|
||||
ISC_LIST_PREPEND(mctx->debuglist[idx], dl, link);
|
||||
mctx->debuglistcnt++;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size,
|
||||
const char *file, unsigned int line)
|
||||
{
|
||||
debuglink_t *dl;
|
||||
uint32_t hash;
|
||||
uint32_t idx;
|
||||
|
||||
if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
|
||||
fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_DELTRACE,
|
||||
"del %p size %u "
|
||||
"file %s line %u mctx %p\n"),
|
||||
ptr, size, file, line, mctx);
|
||||
|
||||
if (mctx->debuglist == NULL)
|
||||
return;
|
||||
|
||||
hash = isc_hash_function(&ptr, sizeof(ptr), true, NULL);
|
||||
idx = hash % DEBUG_TABLE_COUNT;
|
||||
|
||||
dl = ISC_LIST_HEAD(mctx->debuglist[idx]);
|
||||
while (ISC_LIKELY(dl != NULL)) {
|
||||
if (ISC_UNLIKELY(dl->ptr == ptr)) {
|
||||
ISC_LIST_UNLINK(mctx->debuglist[idx], dl, link);
|
||||
mctx->malloced -= sizeof(*dl);
|
||||
free(dl);
|
||||
return;
|
||||
}
|
||||
dl = ISC_LIST_NEXT(dl, link);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here, we didn't find the item on the list. We're
|
||||
* screwed.
|
||||
*/
|
||||
INSIST(0);
|
||||
}
|
||||
#endif /* ISC_MEM_TRACKLINES */
|
||||
|
||||
static inline size_t
|
||||
rmsize(size_t size) {
|
||||
/*
|
||||
@@ -853,8 +734,8 @@ default_memfree(void *arg, void *ptr) {
|
||||
static void
|
||||
initialize_action(void) {
|
||||
RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
|
||||
RUNTIME_CHECK(isc_mutex_init(&contextslock) == ISC_R_SUCCESS);
|
||||
ISC_LIST_INIT(contexts);
|
||||
CK_LIST_INIT(&contexts);
|
||||
|
||||
totallost = 0;
|
||||
}
|
||||
|
||||
@@ -905,7 +786,7 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
|
||||
else
|
||||
ctx->max_size = init_max_size;
|
||||
ctx->flags = flags;
|
||||
ctx->references = 1;
|
||||
isc_refcount_init(&ctx->references, 1);
|
||||
memset(ctx->name, 0, sizeof(ctx->name));
|
||||
ctx->tag = NULL;
|
||||
ctx->quota = 0;
|
||||
@@ -928,12 +809,9 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
|
||||
ctx->arg = arg;
|
||||
ctx->stats = NULL;
|
||||
ctx->checkfree = true;
|
||||
#if ISC_MEM_TRACKLINES
|
||||
ctx->debuglist = NULL;
|
||||
ctx->debuglistcnt = 0;
|
||||
#endif
|
||||
ISC_LIST_INIT(ctx->pools);
|
||||
ctx->poolcnt = 0;
|
||||
|
||||
CK_LIST_INIT(&ctx->pools);
|
||||
|
||||
ctx->freelists = NULL;
|
||||
ctx->basic_blocks = NULL;
|
||||
ctx->basic_table = NULL;
|
||||
@@ -969,28 +847,9 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
|
||||
ctx->maxmalloced += ctx->max_size * sizeof(element *);
|
||||
}
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0)) {
|
||||
unsigned int i;
|
||||
|
||||
ctx->debuglist = (memalloc)(arg, (DEBUG_TABLE_COUNT *
|
||||
sizeof(debuglist_t)));
|
||||
if (ctx->debuglist == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto error;
|
||||
}
|
||||
for (i = 0; i < DEBUG_TABLE_COUNT; i++)
|
||||
ISC_LIST_INIT(ctx->debuglist[i]);
|
||||
ctx->malloced += DEBUG_TABLE_COUNT * sizeof(debuglist_t);
|
||||
ctx->maxmalloced += DEBUG_TABLE_COUNT * sizeof(debuglist_t);
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx->memalloc_failures = 0;
|
||||
|
||||
LOCK(&contextslock);
|
||||
ISC_LIST_INITANDAPPEND(contexts, ctx, link);
|
||||
UNLOCK(&contextslock);
|
||||
CK_LIST_INSERT_HEAD(&contexts, ctx, link);
|
||||
|
||||
*ctxp = (isc_mem_t *)ctx;
|
||||
return (ISC_R_SUCCESS);
|
||||
@@ -1001,10 +860,6 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
|
||||
(memfree)(arg, ctx->stats);
|
||||
if (ctx->freelists != NULL)
|
||||
(memfree)(arg, ctx->freelists);
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ctx->debuglist != NULL)
|
||||
(ctx->memfree)(ctx->arg, ctx->debuglist);
|
||||
#endif /* ISC_MEM_TRACKLINES */
|
||||
if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
|
||||
DESTROYLOCK(&ctx->lock);
|
||||
(memfree)(arg, ctx);
|
||||
@@ -1017,38 +872,15 @@ static void
|
||||
destroy(isc__mem_t *ctx) {
|
||||
unsigned int i;
|
||||
|
||||
LOCK(&contextslock);
|
||||
ISC_LIST_UNLINK(contexts, ctx, link);
|
||||
CK_LIST_REMOVE(ctx, link);
|
||||
totallost += ctx->inuse;
|
||||
UNLOCK(&contextslock);
|
||||
|
||||
ctx->common.impmagic = 0;
|
||||
ctx->common.magic = 0;
|
||||
|
||||
INSIST(ISC_LIST_EMPTY(ctx->pools));
|
||||
INSIST(CK_LIST_EMPTY(&ctx->pools));
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ISC_UNLIKELY(ctx->debuglist != NULL)) {
|
||||
debuglink_t *dl;
|
||||
for (i = 0; i < DEBUG_TABLE_COUNT; i++)
|
||||
for (dl = ISC_LIST_HEAD(ctx->debuglist[i]);
|
||||
dl != NULL;
|
||||
dl = ISC_LIST_HEAD(ctx->debuglist[i])) {
|
||||
if (ctx->checkfree && dl->ptr != NULL)
|
||||
print_active(ctx, stderr);
|
||||
INSIST (!ctx->checkfree || dl->ptr == NULL);
|
||||
|
||||
ISC_LIST_UNLINK(ctx->debuglist[i],
|
||||
dl, link);
|
||||
free(dl);
|
||||
ctx->malloced -= sizeof(*dl);
|
||||
}
|
||||
|
||||
(ctx->memfree)(ctx->arg, ctx->debuglist);
|
||||
ctx->malloced -= DEBUG_TABLE_COUNT * sizeof(debuglist_t);
|
||||
}
|
||||
#endif
|
||||
INSIST(ctx->references == 0);
|
||||
isc_refcount_destroy(&ctx->references);
|
||||
|
||||
if (ctx->checkfree) {
|
||||
for (i = 0; i <= ctx->max_size; i++) {
|
||||
@@ -1058,9 +890,6 @@ destroy(isc__mem_t *ctx) {
|
||||
"leaked memory in context %p (\"%s\") "
|
||||
"(stats[%u].gets == %lu).\n",
|
||||
ctx, ctx->name, i, ctx->stats[i].gets);
|
||||
#if ISC_MEM_TRACKLINES
|
||||
print_active(ctx, stderr);
|
||||
#endif
|
||||
INSIST(ctx->stats[i].gets == 0U);
|
||||
}
|
||||
}
|
||||
@@ -1098,9 +927,7 @@ isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) {
|
||||
REQUIRE(VALID_CONTEXT(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
MCTXLOCK(source, &source->lock);
|
||||
source->references++;
|
||||
MCTXUNLOCK(source, &source->lock);
|
||||
isc_refcount_increment(&source->references);
|
||||
|
||||
*targetp = (isc_mem_t *)source;
|
||||
}
|
||||
@@ -1108,21 +935,14 @@ isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) {
|
||||
void
|
||||
isc__mem_detach(isc_mem_t **ctxp) {
|
||||
isc__mem_t *ctx;
|
||||
bool want_destroy = false;
|
||||
|
||||
REQUIRE(ctxp != NULL);
|
||||
ctx = (isc__mem_t *)*ctxp;
|
||||
REQUIRE(VALID_CONTEXT(ctx));
|
||||
|
||||
MCTXLOCK(ctx, &ctx->lock);
|
||||
INSIST(ctx->references > 0);
|
||||
ctx->references--;
|
||||
if (ctx->references == 0)
|
||||
want_destroy = true;
|
||||
MCTXUNLOCK(ctx, &ctx->lock);
|
||||
|
||||
if (want_destroy)
|
||||
if (isc_refcount_decrement(&ctx->references) == 1) {
|
||||
destroy(ctx);
|
||||
}
|
||||
|
||||
*ctxp = NULL;
|
||||
}
|
||||
@@ -1140,7 +960,6 @@ isc__mem_detach(isc_mem_t **ctxp) {
|
||||
void
|
||||
isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
|
||||
isc__mem_t *ctx;
|
||||
bool want_destroy = false;
|
||||
size_info *si;
|
||||
size_t oldsize;
|
||||
|
||||
@@ -1167,13 +986,9 @@ isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
|
||||
}
|
||||
isc__mem_free((isc_mem_t *)ctx, ptr FLARG_PASS);
|
||||
|
||||
MCTXLOCK(ctx, &ctx->lock);
|
||||
ctx->references--;
|
||||
if (ctx->references == 0)
|
||||
want_destroy = true;
|
||||
MCTXUNLOCK(ctx, &ctx->lock);
|
||||
if (want_destroy)
|
||||
if (isc_refcount_decrement(&ctx->references) == 1) {
|
||||
destroy(ctx);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1188,16 +1003,11 @@ isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
|
||||
mem_putstats(ctx, ptr, size);
|
||||
mem_put(ctx, ptr, size);
|
||||
}
|
||||
|
||||
INSIST(ctx->references > 0);
|
||||
ctx->references--;
|
||||
if (ctx->references == 0)
|
||||
want_destroy = true;
|
||||
|
||||
MCTXUNLOCK(ctx, &ctx->lock);
|
||||
|
||||
if (want_destroy)
|
||||
if (isc_refcount_decrement(&ctx->references) == 1) {
|
||||
destroy(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1213,15 +1023,8 @@ isc__mem_destroy(isc_mem_t **ctxp) {
|
||||
ctx = (isc__mem_t *)*ctxp;
|
||||
REQUIRE(VALID_CONTEXT(ctx));
|
||||
|
||||
MCTXLOCK(ctx, &ctx->lock);
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ctx->references != 1)
|
||||
print_active(ctx, stderr);
|
||||
#endif
|
||||
REQUIRE(ctx->references == 1);
|
||||
ctx->references--;
|
||||
MCTXUNLOCK(ctx, &ctx->lock);
|
||||
|
||||
(void)isc_refcount_decrement(&ctx->references);
|
||||
isc_refcount_destroy(&ctx->references);
|
||||
destroy(ctx);
|
||||
|
||||
*ctxp = NULL;
|
||||
@@ -1337,45 +1140,6 @@ isc__mem_waterack(isc_mem_t *ctx0, int flag) {
|
||||
MCTXUNLOCK(ctx, &ctx->lock);
|
||||
}
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
static void
|
||||
print_active(isc__mem_t *mctx, FILE *out) {
|
||||
if (mctx->debuglist != NULL) {
|
||||
debuglink_t *dl;
|
||||
unsigned int i;
|
||||
const char *format;
|
||||
bool found;
|
||||
|
||||
fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_DUMPALLOC,
|
||||
"Dump of all outstanding "
|
||||
"memory allocations:\n"));
|
||||
found = false;
|
||||
format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_PTRFILELINE,
|
||||
"\tptr %p size %u file %s line %u\n");
|
||||
for (i = 0; i < DEBUG_TABLE_COUNT; i++) {
|
||||
dl = ISC_LIST_HEAD(mctx->debuglist[i]);
|
||||
|
||||
if (dl != NULL)
|
||||
found = true;
|
||||
|
||||
while (dl != NULL) {
|
||||
if (dl->ptr != NULL)
|
||||
fprintf(out, format,
|
||||
dl->ptr, dl->size,
|
||||
dl->file, dl->line);
|
||||
dl = ISC_LIST_NEXT(dl, link);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
fputs(isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_NONE, "\tNone.\n"), out);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Print the stats[] on the stream "out" with suitable formatting.
|
||||
*/
|
||||
@@ -1403,6 +1167,7 @@ isc_mem_stats(isc_mem_t *ctx0, FILE *out) {
|
||||
s->blocks, s->freefrags);
|
||||
fputc('\n', out);
|
||||
}
|
||||
MCTXUNLOCK(ctx, &ctx->lock);
|
||||
|
||||
/*
|
||||
* Note that since a pool can be locked now, these stats might be
|
||||
@@ -1411,31 +1176,8 @@ isc_mem_stats(isc_mem_t *ctx0, FILE *out) {
|
||||
* lock, however, so walking this list and extracting integers from
|
||||
* stats fields is always safe.
|
||||
*/
|
||||
pool = ISC_LIST_HEAD(ctx->pools);
|
||||
if (pool != NULL) {
|
||||
fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLSTATS,
|
||||
"[Pool statistics]\n"));
|
||||
fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLNAME, "name"),
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLSIZE, "size"),
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLMAXALLOC, "maxalloc"),
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLALLOCATED, "allocated"),
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLFREECOUNT, "freecount"),
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLFREEMAX, "freemax"),
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLFILLCOUNT, "fillcount"),
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
|
||||
ISC_MSG_POOLGETS, "gets"),
|
||||
"L");
|
||||
}
|
||||
while (pool != NULL) {
|
||||
CK_LIST_FOREACH(pool, &ctx->pools, link) {
|
||||
|
||||
fprintf(out, "%15s %10lu %10u %10u %10u %10u %10u %10u %s\n",
|
||||
#if ISC_MEMPOOL_NAMES
|
||||
pool->name,
|
||||
@@ -1446,14 +1188,8 @@ isc_mem_stats(isc_mem_t *ctx0, FILE *out) {
|
||||
pool->allocated, pool->freecount, pool->freemax,
|
||||
pool->fillcount, pool->gets,
|
||||
(pool->lock == NULL ? "N" : "Y"));
|
||||
pool = ISC_LIST_NEXT(pool, link);
|
||||
}
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
print_active(ctx, out);
|
||||
#endif
|
||||
|
||||
MCTXUNLOCK(ctx, &ctx->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1861,10 +1597,7 @@ isc__mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) {
|
||||
|
||||
*mpctxp = (isc_mempool_t *)mpctx;
|
||||
|
||||
MCTXLOCK(mctx, &mctx->lock);
|
||||
ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
|
||||
mctx->poolcnt++;
|
||||
MCTXUNLOCK(mctx, &mctx->lock);
|
||||
CK_LIST_INSERT_HEAD(&mctx->pools, mpctx, link);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@@ -1938,10 +1671,7 @@ isc__mempool_destroy(isc_mempool_t **mpctxp) {
|
||||
/*
|
||||
* Remove our linked list entry from the memory context.
|
||||
*/
|
||||
MCTXLOCK(mctx, &mctx->lock);
|
||||
ISC_LIST_UNLINK(mctx->pools, mpctx, link);
|
||||
mctx->poolcnt--;
|
||||
MCTXUNLOCK(mctx, &mctx->lock);
|
||||
CK_LIST_REMOVE(mpctx, link);
|
||||
|
||||
mpctx->common.impmagic = 0;
|
||||
mpctx->common.magic = 0;
|
||||
@@ -2027,16 +1757,6 @@ isc___mempool_get(isc_mempool_t *mpctx0 FLARG) {
|
||||
if (mpctx->lock != NULL)
|
||||
UNLOCK(mpctx->lock);
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ISC_UNLIKELY(((isc_mem_debugging & TRACE_OR_RECORD) != 0) &&
|
||||
item != NULL))
|
||||
{
|
||||
MCTXLOCK(mctx, &mctx->lock);
|
||||
ADD_TRACE(mctx, item, mpctx->size, file, line);
|
||||
MCTXUNLOCK(mctx, &mctx->lock);
|
||||
}
|
||||
#endif /* ISC_MEM_TRACKLINES */
|
||||
|
||||
return (item);
|
||||
}
|
||||
|
||||
@@ -2058,14 +1778,6 @@ isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) {
|
||||
INSIST(mpctx->allocated > 0);
|
||||
mpctx->allocated--;
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0)) {
|
||||
MCTXLOCK(mctx, &mctx->lock);
|
||||
DELETE_TRACE(mctx, mem, mpctx->size, file, line);
|
||||
MCTXUNLOCK(mctx, &mctx->lock);
|
||||
}
|
||||
#endif /* ISC_MEM_TRACKLINES */
|
||||
|
||||
/*
|
||||
* If our free list is full, return this to the mctx directly.
|
||||
*/
|
||||
@@ -2245,85 +1957,28 @@ isc__mem_register(void) {
|
||||
|
||||
void
|
||||
isc__mem_printactive(isc_mem_t *ctx0, FILE *file) {
|
||||
#if ISC_MEM_TRACKLINES
|
||||
isc__mem_t *ctx = (isc__mem_t *)ctx0;
|
||||
|
||||
REQUIRE(VALID_CONTEXT(ctx));
|
||||
REQUIRE(file != NULL);
|
||||
|
||||
print_active(ctx, file);
|
||||
#else
|
||||
UNUSED(ctx0);
|
||||
UNUSED(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Requires contextslock to be held by caller.
|
||||
*/
|
||||
static void
|
||||
print_contexts(FILE *file) {
|
||||
isc__mem_t *ctx;
|
||||
|
||||
for (ctx = ISC_LIST_HEAD(contexts);
|
||||
ctx != NULL;
|
||||
ctx = ISC_LIST_NEXT(ctx, link))
|
||||
{
|
||||
fprintf(file, "context: %p (%s): %u references\n",
|
||||
ctx,
|
||||
ctx->name[0] == 0 ? "<unknown>" : ctx->name,
|
||||
ctx->references);
|
||||
print_active(ctx, file);
|
||||
}
|
||||
fflush(file);
|
||||
}
|
||||
|
||||
void
|
||||
isc_mem_printallactive(FILE *file) {
|
||||
#if !ISC_MEM_TRACKLINES
|
||||
UNUSED(file);
|
||||
#else
|
||||
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
|
||||
|
||||
LOCK(&contextslock);
|
||||
print_contexts(file);
|
||||
UNLOCK(&contextslock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
isc_mem_checkdestroyed(FILE *file) {
|
||||
#if !ISC_MEM_TRACKLINES
|
||||
UNUSED(file);
|
||||
#endif
|
||||
|
||||
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
|
||||
|
||||
LOCK(&contextslock);
|
||||
if (!ISC_LIST_EMPTY(contexts)) {
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0)) {
|
||||
print_contexts(file);
|
||||
}
|
||||
#endif
|
||||
INSIST(0);
|
||||
}
|
||||
UNLOCK(&contextslock);
|
||||
INSIST(CK_LIST_EMPTY(&contexts));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_mem_references(isc_mem_t *ctx0) {
|
||||
isc__mem_t *ctx = (isc__mem_t *)ctx0;
|
||||
unsigned int references;
|
||||
|
||||
REQUIRE(VALID_CONTEXT(ctx));
|
||||
|
||||
MCTXLOCK(ctx, &ctx->lock);
|
||||
references = ctx->references;
|
||||
MCTXUNLOCK(ctx, &ctx->lock);
|
||||
|
||||
return (references);
|
||||
return (isc_refcount_current(&ctx->references));
|
||||
}
|
||||
|
||||
typedef struct summarystat {
|
||||
@@ -2362,15 +2017,9 @@ xml_renderctx(isc__mem_t *ctx, summarystat_t *summary,
|
||||
(ctx->max_size + 1) * sizeof(struct stats) +
|
||||
ctx->max_size * sizeof(element *) +
|
||||
ctx->basic_table_count * sizeof(char *);
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ctx->debuglist != NULL) {
|
||||
summary->contextsize +=
|
||||
DEBUG_TABLE_COUNT * sizeof(debuglist_t) +
|
||||
ctx->debuglistcnt * sizeof(debuglink_t);
|
||||
}
|
||||
#endif
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "references"));
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%d", ctx->references));
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu32,
|
||||
isc_refcount_current(&ctx->references)));
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* references */
|
||||
|
||||
summary->total += ctx->total;
|
||||
@@ -2420,10 +2069,10 @@ xml_renderctx(isc__mem_t *ctx, summarystat_t *summary,
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%s", "-"));
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* blocksize */
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "pools"));
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%u", ctx->poolcnt));
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* pools */
|
||||
summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
|
||||
/* TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "pools")); */
|
||||
/* TRY0(xmlTextWriterWriteFormatString(writer, "%u", ctx->poolcnt)); */
|
||||
/* TRY0(xmlTextWriterEndElement(writer)); /\* pools *\/ */
|
||||
/* summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t); */
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "hiwater"));
|
||||
TRY0(xmlTextWriterWriteFormatString(writer,
|
||||
@@ -2458,18 +2107,13 @@ isc_mem_renderxml(xmlTextWriterPtr writer) {
|
||||
|
||||
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
|
||||
|
||||
LOCK(&contextslock);
|
||||
lost = totallost;
|
||||
for (ctx = ISC_LIST_HEAD(contexts);
|
||||
ctx != NULL;
|
||||
ctx = ISC_LIST_NEXT(ctx, link)) {
|
||||
CK_LIST_FOREACH(ctx, &contexts, link) {
|
||||
xmlrc = xml_renderctx(ctx, &summary, writer);
|
||||
if (xmlrc < 0) {
|
||||
UNLOCK(&contextslock);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
UNLOCK(&contextslock);
|
||||
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* contexts */
|
||||
|
||||
@@ -2548,13 +2192,6 @@ json_renderctx(isc__mem_t *ctx, summarystat_t *summary, json_object *array) {
|
||||
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
|
||||
summary->blocksize += ctx->basic_table_count *
|
||||
NUM_BASIC_BLOCKS * ctx->mem_target;
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if (ctx->debuglist != NULL) {
|
||||
summary->contextsize +=
|
||||
DEBUG_TABLE_COUNT * sizeof(debuglist_t) +
|
||||
ctx->debuglistcnt * sizeof(debuglink_t);
|
||||
}
|
||||
#endif
|
||||
|
||||
ctxobj = json_object_new_object();
|
||||
CHECKMEM(ctxobj);
|
||||
@@ -2570,7 +2207,7 @@ json_renderctx(isc__mem_t *ctx, summarystat_t *summary, json_object *array) {
|
||||
json_object_object_add(ctxobj, "name", obj);
|
||||
}
|
||||
|
||||
obj = json_object_new_int64(ctx->references);
|
||||
obj = json_object_new_int64(isc_refcount_current(&ctx->references));
|
||||
CHECKMEM(obj);
|
||||
json_object_object_add(ctxobj, "references", obj);
|
||||
|
||||
@@ -2603,11 +2240,11 @@ json_renderctx(isc__mem_t *ctx, summarystat_t *summary, json_object *array) {
|
||||
json_object_object_add(ctxobj, "blocksize", obj);
|
||||
}
|
||||
|
||||
obj = json_object_new_int64(ctx->poolcnt);
|
||||
CHECKMEM(obj);
|
||||
json_object_object_add(ctxobj, "pools", obj);
|
||||
/* obj = json_object_new_int64(ctx->poolcnt); */
|
||||
/* CHECKMEM(obj); */
|
||||
/* json_object_object_add(ctxobj, "pools", obj); */
|
||||
|
||||
summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
|
||||
/* summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t); */
|
||||
|
||||
obj = json_object_new_int64(ctx->hi_water);
|
||||
CHECKMEM(obj);
|
||||
@@ -2642,18 +2279,13 @@ isc_mem_renderjson(json_object *memobj) {
|
||||
ctxarray = json_object_new_array();
|
||||
CHECKMEM(ctxarray);
|
||||
|
||||
LOCK(&contextslock);
|
||||
lost = totallost;
|
||||
for (ctx = ISC_LIST_HEAD(contexts);
|
||||
ctx != NULL;
|
||||
ctx = ISC_LIST_NEXT(ctx, link)) {
|
||||
CK_LIST_FOREACH(ctx, &contexts, link) {
|
||||
result = json_renderctx(ctx, &summary, ctxarray);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNLOCK(&contextslock);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
UNLOCK(&contextslock);
|
||||
|
||||
obj = json_object_new_int64(summary.total);
|
||||
CHECKMEM(obj);
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = include
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = isc
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
HEADERS = atomic.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
|
||||
|
||||
install:: installdirs
|
||||
for i in ${HEADERS}; do \
|
||||
${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
|
||||
done
|
||||
|
||||
uninstall::
|
||||
for i in ${HEADERS}; do \
|
||||
rm -f ${DESTDIR}${includedir}/isc/$$i ; \
|
||||
done
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#ifdef ISC_PLATFORM_USEGCCASM
|
||||
/*
|
||||
* This routine atomically increments the value stored in 'p' by 'val', and
|
||||
* returns the previous value.
|
||||
*/
|
||||
static inline int32_t
|
||||
isc_atomic_xadd(int32_t *p, int val) {
|
||||
int32_t orig;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
" .set push \n"
|
||||
" .set mips2 \n"
|
||||
" .set noreorder \n"
|
||||
" .set noat \n"
|
||||
"1: ll $1, %1 \n"
|
||||
" addu %0, $1, %2 \n"
|
||||
" sc %0, %1 \n"
|
||||
" beqz %0, 1b \n"
|
||||
" move %0, $1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (orig), "+R" (*p)
|
||||
: "r" (val)
|
||||
: "memory");
|
||||
|
||||
return (orig);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine atomically stores the value 'val' in 'p'.
|
||||
*/
|
||||
static inline void
|
||||
isc_atomic_store(int32_t *p, int32_t val) {
|
||||
*p = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine atomically replaces the value in 'p' with 'val', if the
|
||||
* original value is equal to 'cmpval'. The original value is returned in any
|
||||
* case.
|
||||
*/
|
||||
static inline int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int cmpval, int val) {
|
||||
int32_t orig;
|
||||
int32_t tmp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
" .set push \n"
|
||||
" .set mips2 \n"
|
||||
" .set noreorder \n"
|
||||
" .set noat \n"
|
||||
"1: ll $1, %1 \n"
|
||||
" bne $1, %3, 2f \n"
|
||||
" move %2, %4 \n"
|
||||
" sc %2, %1 \n"
|
||||
" beqz %2, 1b \n"
|
||||
"2: move %0, $1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r"(orig), "+R" (*p), "=r" (tmp)
|
||||
: "r"(cmpval), "r"(val)
|
||||
: "memory");
|
||||
|
||||
return (orig);
|
||||
}
|
||||
|
||||
#else /* !ISC_PLATFORM_USEGCCASM */
|
||||
|
||||
#error "unsupported compiler. disable atomic ops by --disable-atomic"
|
||||
|
||||
#endif
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = include
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = isc
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
HEADERS = atomic.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
|
||||
|
||||
install:: installdirs
|
||||
for i in ${HEADERS}; do \
|
||||
${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
|
||||
done
|
||||
|
||||
uninstall::
|
||||
for i in ${HEADERS}; do \
|
||||
rm -f ${DESTDIR}${includedir}/isc/$$i ; \
|
||||
done
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = include
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = isc
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
HEADERS = atomic.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
|
||||
|
||||
install:: installdirs
|
||||
for i in ${HEADERS}; do \
|
||||
${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
|
||||
done
|
||||
|
||||
uninstall::
|
||||
for i in ${HEADERS}; do \
|
||||
rm -f ${DESTDIR}${includedir}/isc/$$i ; \
|
||||
done
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
/*!\file
|
||||
* static inline int32_t
|
||||
* isc_atomic_xadd(int32_t *p, int32_t val);
|
||||
*
|
||||
* This routine atomically increments the value stored in 'p' by 'val', and
|
||||
* returns the previous value.
|
||||
*
|
||||
* static inline void
|
||||
* isc_atomic_store(void *p, int32_t val);
|
||||
*
|
||||
* This routine atomically stores the value 'val' in 'p'.
|
||||
*
|
||||
* static inline int32_t
|
||||
* isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val);
|
||||
*
|
||||
* This routine atomically replaces the value in 'p' with 'val', if the
|
||||
* original value is equal to 'cmpval'. The original value is returned in any
|
||||
* case.
|
||||
*/
|
||||
|
||||
#if defined(_AIX)
|
||||
|
||||
#include <sys/atomic_op.h>
|
||||
|
||||
#define isc_atomic_store(p, v) _clear_lock(p, v)
|
||||
|
||||
#ifdef __GNUC__
|
||||
static inline int32_t
|
||||
#else
|
||||
static int32_t
|
||||
#endif
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
int ret;
|
||||
|
||||
#ifdef __GNUC__
|
||||
asm("ics");
|
||||
#else
|
||||
__isync();
|
||||
#endif
|
||||
|
||||
ret = fetch_and_add((atomic_p)p, (int)val);
|
||||
|
||||
#ifdef __GNUC__
|
||||
asm("ics");
|
||||
#else
|
||||
__isync();
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
static inline int
|
||||
#else
|
||||
static int
|
||||
#endif
|
||||
isc_atomic_cmpxchg(atomic_p p, int old, int replacement) {
|
||||
int orig = old;
|
||||
|
||||
#ifdef __GNUC__
|
||||
asm("ics");
|
||||
#else
|
||||
__isync();
|
||||
#endif
|
||||
if (compare_and_swap(p, &orig, replacement))
|
||||
orig = old;
|
||||
|
||||
#ifdef __GNUC__
|
||||
asm("ics");
|
||||
#else
|
||||
__isync();
|
||||
#endif
|
||||
|
||||
return (orig);
|
||||
}
|
||||
|
||||
#elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM)
|
||||
static inline int32_t
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
int32_t orig;
|
||||
|
||||
__asm__ volatile (
|
||||
#ifdef ISC_PLATFORM_USEMACASM
|
||||
"1:"
|
||||
"lwarx r6, 0, %1\n"
|
||||
"mr %0, r6\n"
|
||||
"add r6, r6, %2\n"
|
||||
"stwcx. r6, 0, %1\n"
|
||||
"bne- 1b\n"
|
||||
"sync"
|
||||
#else
|
||||
"1:"
|
||||
"lwarx 6, 0, %1\n"
|
||||
"mr %0, 6\n"
|
||||
"add 6, 6, %2\n"
|
||||
"stwcx. 6, 0, %1\n"
|
||||
"bne- 1b\n"
|
||||
"sync"
|
||||
#endif
|
||||
: "=&r"(orig)
|
||||
: "r"(p), "r"(val)
|
||||
: "r6", "memory"
|
||||
);
|
||||
|
||||
return (orig);
|
||||
}
|
||||
|
||||
static inline void
|
||||
isc_atomic_store(void *p, int32_t val) {
|
||||
__asm__ volatile (
|
||||
#ifdef ISC_PLATFORM_USEMACASM
|
||||
"1:"
|
||||
"lwarx r6, 0, %0\n"
|
||||
"lwz r6, %1\n"
|
||||
"stwcx. r6, 0, %0\n"
|
||||
"bne- 1b\n"
|
||||
"sync"
|
||||
#else
|
||||
"1:"
|
||||
"lwarx 6, 0, %0\n"
|
||||
"lwz 6, %1\n"
|
||||
"stwcx. 6, 0, %0\n"
|
||||
"bne- 1b\n"
|
||||
"sync"
|
||||
#endif
|
||||
:
|
||||
: "r"(p), "m"(val)
|
||||
: "r6", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
|
||||
int32_t orig;
|
||||
|
||||
__asm__ volatile (
|
||||
#ifdef ISC_PLATFORM_USEMACASM
|
||||
"1:"
|
||||
"lwarx r6, 0, %1\n"
|
||||
"mr %0,r6\n"
|
||||
"cmpw r6, %2\n"
|
||||
"bne 2f\n"
|
||||
"mr r6, %3\n"
|
||||
"stwcx. r6, 0, %1\n"
|
||||
"bne- 1b\n"
|
||||
"2:\n"
|
||||
"sync"
|
||||
#else
|
||||
"1:"
|
||||
"lwarx 6, 0, %1\n"
|
||||
"mr %0,6\n"
|
||||
"cmpw 6, %2\n"
|
||||
"bne 2f\n"
|
||||
"mr 6, %3\n"
|
||||
"stwcx. 6, 0, %1\n"
|
||||
"bne- 1b\n"
|
||||
"2:\n"
|
||||
"sync"
|
||||
#endif
|
||||
: "=&r" (orig)
|
||||
: "r"(p), "r"(cmpval), "r"(val)
|
||||
: "r6", "memory"
|
||||
);
|
||||
|
||||
return (orig);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error "unsupported compiler. disable atomic ops by --disable-atomic"
|
||||
|
||||
#endif
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
+2
-6
@@ -76,14 +76,10 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
|
||||
|
||||
static void
|
||||
_deref_prefix(isc_prefix_t *prefix) {
|
||||
int refs;
|
||||
|
||||
if (prefix == NULL)
|
||||
return;
|
||||
|
||||
isc_refcount_decrement(&prefix->refcount, &refs);
|
||||
|
||||
if (refs <= 0) {
|
||||
if (isc_refcount_decrement(&prefix->refcount) == 1) {
|
||||
isc_refcount_destroy(&prefix->refcount);
|
||||
isc_mem_putanddetach(&prefix->mctx, prefix,
|
||||
sizeof(isc_prefix_t));
|
||||
@@ -110,7 +106,7 @@ _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
|
||||
return (ret);
|
||||
}
|
||||
|
||||
isc_refcount_increment(&prefix->refcount, NULL);
|
||||
isc_refcount_increment(&prefix->refcount);
|
||||
|
||||
*target = prefix;
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
isc_result_t
|
||||
isc_refcount_init(isc_refcount_t *ref, unsigned int n) {
|
||||
REQUIRE(ref != NULL);
|
||||
|
||||
ref->refs = n;
|
||||
#if !defined(ISC_REFCOUNT_HAVEATOMIC)
|
||||
return (isc_mutex_init(&ref->lock));
|
||||
#else
|
||||
return (ISC_R_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
+33
-826
@@ -18,7 +18,8 @@
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <ck_rwlock.h>
|
||||
|
||||
#include <isc/magic.h>
|
||||
#include <isc/msgs.h>
|
||||
#include <isc/platform.h>
|
||||
@@ -26,867 +27,73 @@
|
||||
#include <isc/rwlock.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#define RWLOCK_MAGIC ISC_MAGIC('R', 'W', 'L', 'k')
|
||||
#define VALID_RWLOCK(rwl) ISC_MAGIC_VALID(rwl, RWLOCK_MAGIC)
|
||||
|
||||
#ifndef RWLOCK_DEFAULT_READ_QUOTA
|
||||
#define RWLOCK_DEFAULT_READ_QUOTA 4
|
||||
#endif
|
||||
|
||||
#ifndef RWLOCK_DEFAULT_WRITE_QUOTA
|
||||
#define RWLOCK_DEFAULT_WRITE_QUOTA 4
|
||||
#endif
|
||||
|
||||
#ifndef RWLOCK_MAX_ADAPTIVE_COUNT
|
||||
#define RWLOCK_MAX_ADAPTIVE_COUNT 100
|
||||
#endif
|
||||
|
||||
#if defined(ISC_RWLOCK_USEATOMIC)
|
||||
static isc_result_t
|
||||
isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
|
||||
#endif
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
#include <stdio.h> /* Required for fprintf/stderr. */
|
||||
#include <isc/thread.h> /* Required for isc_thread_self(). */
|
||||
|
||||
static void
|
||||
print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
#if defined(ISC_RWLOCK_USEATOMIC)
|
||||
fprintf(stderr,
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_PRINTLOCK2,
|
||||
"rwlock %p thread %lu %s(%s): "
|
||||
"write_requests=%u, write_completions=%u, "
|
||||
"cnt_and_flag=0x%x, readers_waiting=%u, "
|
||||
"write_granted=%u, write_quota=%u\n"),
|
||||
rwl, isc_thread_self(), operation,
|
||||
(type == isc_rwlocktype_read ?
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_READ, "read") :
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_WRITE, "write")),
|
||||
rwl->write_requests, rwl->write_completions,
|
||||
rwl->cnt_and_flag, rwl->readers_waiting,
|
||||
rwl->write_granted, rwl->write_quota);
|
||||
#else
|
||||
fprintf(stderr,
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_PRINTLOCK,
|
||||
"rwlock %p thread %lu %s(%s): %s, %u active, "
|
||||
"%u granted, %u rwaiting, %u wwaiting\n"),
|
||||
rwl, isc_thread_self(), operation,
|
||||
(type == isc_rwlocktype_read ?
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_READ, "read") :
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_WRITE, "write")),
|
||||
(rwl->type == isc_rwlocktype_read ?
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_READING, "reading") :
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_WRITING, "writing")),
|
||||
rwl->active, rwl->granted,
|
||||
rwl->readers_waiting, rwl->writers_waiting);
|
||||
#endif
|
||||
}
|
||||
#endif /* ISC_RWLOCK_TRACE */
|
||||
|
||||
inline
|
||||
isc_result_t
|
||||
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
||||
unsigned int write_quota)
|
||||
{
|
||||
isc_result_t result;
|
||||
UNUSED(read_quota);
|
||||
UNUSED(write_quota);
|
||||
|
||||
REQUIRE(rwl != NULL);
|
||||
|
||||
/*
|
||||
* In case there's trouble initializing, we zero magic now. If all
|
||||
* goes well, we'll set it to RWLOCK_MAGIC.
|
||||
*/
|
||||
rwl->magic = 0;
|
||||
|
||||
rwl->spins = 0;
|
||||
#if defined(ISC_RWLOCK_USEATOMIC)
|
||||
rwl->write_requests = 0;
|
||||
rwl->write_completions = 0;
|
||||
rwl->cnt_and_flag = 0;
|
||||
rwl->readers_waiting = 0;
|
||||
rwl->write_granted = 0;
|
||||
if (read_quota != 0) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"read quota is not supported");
|
||||
}
|
||||
if (write_quota == 0)
|
||||
write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
|
||||
rwl->write_quota = write_quota;
|
||||
#else
|
||||
rwl->type = isc_rwlocktype_read;
|
||||
rwl->original = isc_rwlocktype_none;
|
||||
rwl->active = 0;
|
||||
rwl->granted = 0;
|
||||
rwl->readers_waiting = 0;
|
||||
rwl->writers_waiting = 0;
|
||||
if (read_quota == 0)
|
||||
read_quota = RWLOCK_DEFAULT_READ_QUOTA;
|
||||
rwl->read_quota = read_quota;
|
||||
if (write_quota == 0)
|
||||
write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
|
||||
rwl->write_quota = write_quota;
|
||||
#endif
|
||||
|
||||
result = isc_mutex_init(&rwl->lock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = isc_condition_init(&rwl->readable);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_condition_init(readable) %s: %s",
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
|
||||
ISC_MSG_FAILED, "failed"),
|
||||
isc_result_totext(result));
|
||||
result = ISC_R_UNEXPECTED;
|
||||
goto destroy_lock;
|
||||
}
|
||||
result = isc_condition_init(&rwl->writeable);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_condition_init(writeable) %s: %s",
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
|
||||
ISC_MSG_FAILED, "failed"),
|
||||
isc_result_totext(result));
|
||||
result = ISC_R_UNEXPECTED;
|
||||
goto destroy_rcond;
|
||||
}
|
||||
|
||||
rwl->magic = RWLOCK_MAGIC;
|
||||
ck_rwlock_init(rwl);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
destroy_rcond:
|
||||
(void)isc_condition_destroy(&rwl->readable);
|
||||
destroy_lock:
|
||||
DESTROYLOCK(&rwl->lock);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
isc_rwlock_destroy(isc_rwlock_t *rwl) {
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
#if defined(ISC_RWLOCK_USEATOMIC)
|
||||
REQUIRE(rwl->write_requests == rwl->write_completions &&
|
||||
rwl->cnt_and_flag == 0 && rwl->readers_waiting == 0);
|
||||
#else
|
||||
LOCK(&rwl->lock);
|
||||
REQUIRE(rwl->active == 0 &&
|
||||
rwl->readers_waiting == 0 &&
|
||||
rwl->writers_waiting == 0);
|
||||
UNLOCK(&rwl->lock);
|
||||
#endif
|
||||
|
||||
rwl->magic = 0;
|
||||
(void)isc_condition_destroy(&rwl->readable);
|
||||
(void)isc_condition_destroy(&rwl->writeable);
|
||||
DESTROYLOCK(&rwl->lock);
|
||||
}
|
||||
|
||||
#if defined(ISC_RWLOCK_USEATOMIC)
|
||||
|
||||
/*
|
||||
* When some architecture-dependent atomic operations are available,
|
||||
* rwlock can be more efficient than the generic algorithm defined below.
|
||||
* The basic algorithm is described in the following URL:
|
||||
* http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html
|
||||
*
|
||||
* The key is to use the following integer variables modified atomically:
|
||||
* write_requests, write_completions, and cnt_and_flag.
|
||||
*
|
||||
* write_requests and write_completions act as a waiting queue for writers
|
||||
* in order to ensure the FIFO order. Both variables begin with the initial
|
||||
* value of 0. When a new writer tries to get a write lock, it increments
|
||||
* write_requests and gets the previous value of the variable as a "ticket".
|
||||
* When write_completions reaches the ticket number, the new writer can start
|
||||
* writing. When the writer completes its work, it increments
|
||||
* write_completions so that another new writer can start working. If the
|
||||
* write_requests is not equal to write_completions, it means a writer is now
|
||||
* working or waiting. In this case, a new readers cannot start reading, or
|
||||
* in other words, this algorithm basically prefers writers.
|
||||
*
|
||||
* cnt_and_flag is a "lock" shared by all readers and writers. This integer
|
||||
* variable is a kind of structure with two members: writer_flag (1 bit) and
|
||||
* reader_count (31 bits). The writer_flag shows whether a writer is working,
|
||||
* and the reader_count shows the number of readers currently working or almost
|
||||
* ready for working. A writer who has the current "ticket" tries to get the
|
||||
* lock by exclusively setting the writer_flag to 1, provided that the whole
|
||||
* 32-bit is 0 (meaning no readers or writers working). On the other hand,
|
||||
* a new reader tries to increment the "reader_count" field provided that
|
||||
* the writer_flag is 0 (meaning there is no writer working).
|
||||
*
|
||||
* If some of the above operations fail, the reader or the writer sleeps
|
||||
* until the related condition changes. When a working reader or writer
|
||||
* completes its work, some readers or writers are sleeping, and the condition
|
||||
* that suspended the reader or writer has changed, it wakes up the sleeping
|
||||
* readers or writers.
|
||||
*
|
||||
* As already noted, this algorithm basically prefers writers. In order to
|
||||
* prevent readers from starving, however, the algorithm also introduces the
|
||||
* "writer quota" (Q). When Q consecutive writers have completed their work,
|
||||
* suspending readers, the last writer will wake up the readers, even if a new
|
||||
* writer is waiting.
|
||||
*
|
||||
* Implementation specific note: due to the combination of atomic operations
|
||||
* and a mutex lock, ordering between the atomic operation and locks can be
|
||||
* very sensitive in some cases. In particular, it is generally very important
|
||||
* to check the atomic variable that requires a reader or writer to sleep after
|
||||
* locking the mutex and before actually sleeping; otherwise, it could be very
|
||||
* likely to cause a deadlock. For example, assume "var" is a variable
|
||||
* atomically modified, then the corresponding code would be:
|
||||
* if (var == need_sleep) {
|
||||
* LOCK(lock);
|
||||
* if (var == need_sleep)
|
||||
* WAIT(cond, lock);
|
||||
* UNLOCK(lock);
|
||||
* }
|
||||
* The second check is important, since "var" is protected by the atomic
|
||||
* operation, not by the mutex, and can be changed just before sleeping.
|
||||
* (The first "if" could be omitted, but this is also important in order to
|
||||
* make the code efficient by avoiding the use of the mutex unless it is
|
||||
* really necessary.)
|
||||
*/
|
||||
|
||||
#define WRITER_ACTIVE 0x1
|
||||
#define READER_INCR 0x2
|
||||
|
||||
static isc_result_t
|
||||
isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
int32_t cntflag;
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_PRELOCK, "prelock"), rwl, type);
|
||||
#endif
|
||||
|
||||
if (type == isc_rwlocktype_read) {
|
||||
if (rwl->write_requests != rwl->write_completions) {
|
||||
/* there is a waiting or active writer */
|
||||
LOCK(&rwl->lock);
|
||||
if (rwl->write_requests != rwl->write_completions) {
|
||||
rwl->readers_waiting++;
|
||||
WAIT(&rwl->readable, &rwl->lock);
|
||||
rwl->readers_waiting--;
|
||||
}
|
||||
UNLOCK(&rwl->lock);
|
||||
}
|
||||
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
cntflag = atomic_fetch_add_explicit(&rwl->cnt_and_flag,
|
||||
READER_INCR,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
|
||||
#endif
|
||||
POST(cntflag);
|
||||
while (1) {
|
||||
if ((rwl->cnt_and_flag & WRITER_ACTIVE) == 0)
|
||||
break;
|
||||
|
||||
/* A writer is still working */
|
||||
LOCK(&rwl->lock);
|
||||
rwl->readers_waiting++;
|
||||
if ((rwl->cnt_and_flag & WRITER_ACTIVE) != 0)
|
||||
WAIT(&rwl->readable, &rwl->lock);
|
||||
rwl->readers_waiting--;
|
||||
UNLOCK(&rwl->lock);
|
||||
|
||||
/*
|
||||
* Typically, the reader should be able to get a lock
|
||||
* at this stage:
|
||||
* (1) there should have been no pending writer when
|
||||
* the reader was trying to increment the
|
||||
* counter; otherwise, the writer should be in
|
||||
* the waiting queue, preventing the reader from
|
||||
* proceeding to this point.
|
||||
* (2) once the reader increments the counter, no
|
||||
* more writer can get a lock.
|
||||
* Still, it is possible another writer can work at
|
||||
* this point, e.g. in the following scenario:
|
||||
* A previous writer unlocks the writer lock.
|
||||
* This reader proceeds to point (1).
|
||||
* A new writer appears, and gets a new lock before
|
||||
* the reader increments the counter.
|
||||
* The reader then increments the counter.
|
||||
* The previous writer notices there is a waiting
|
||||
* reader who is almost ready, and wakes it up.
|
||||
* So, the reader needs to confirm whether it can now
|
||||
* read explicitly (thus we loop). Note that this is
|
||||
* not an infinite process, since the reader has
|
||||
* incremented the counter at this point.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are temporarily preferred to writers due to the writer
|
||||
* quota, reset the condition (race among readers doesn't
|
||||
* matter).
|
||||
*/
|
||||
rwl->write_granted = 0;
|
||||
} else {
|
||||
int32_t prev_writer;
|
||||
|
||||
/* enter the waiting queue, and wait for our turn */
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
prev_writer = atomic_fetch_add_explicit(&rwl->write_requests, 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
prev_writer = isc_atomic_xadd(&rwl->write_requests, 1);
|
||||
#endif
|
||||
while (rwl->write_completions != prev_writer) {
|
||||
LOCK(&rwl->lock);
|
||||
if (rwl->write_completions != prev_writer) {
|
||||
WAIT(&rwl->writeable, &rwl->lock);
|
||||
UNLOCK(&rwl->lock);
|
||||
continue;
|
||||
}
|
||||
UNLOCK(&rwl->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
int_fast32_t cntflag2 = 0;
|
||||
atomic_compare_exchange_strong_explicit
|
||||
(&rwl->cnt_and_flag, &cntflag2, WRITER_ACTIVE,
|
||||
memory_order_relaxed, memory_order_relaxed);
|
||||
#else
|
||||
int32_t cntflag2;
|
||||
cntflag2 = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
|
||||
WRITER_ACTIVE);
|
||||
#endif
|
||||
|
||||
if (cntflag2 == 0)
|
||||
break;
|
||||
|
||||
/* Another active reader or writer is working. */
|
||||
LOCK(&rwl->lock);
|
||||
if (rwl->cnt_and_flag != 0)
|
||||
WAIT(&rwl->writeable, &rwl->lock);
|
||||
UNLOCK(&rwl->lock);
|
||||
}
|
||||
|
||||
INSIST((rwl->cnt_and_flag & WRITER_ACTIVE) != 0);
|
||||
rwl->write_granted++;
|
||||
}
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_POSTLOCK, "postlock"), rwl, type);
|
||||
#endif
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
UNUSED(rwl);
|
||||
return;
|
||||
}
|
||||
|
||||
inline
|
||||
isc_result_t
|
||||
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
int32_t cnt = 0;
|
||||
int32_t max_cnt = rwl->spins * 2 + 10;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
if (max_cnt > RWLOCK_MAX_ADAPTIVE_COUNT)
|
||||
max_cnt = RWLOCK_MAX_ADAPTIVE_COUNT;
|
||||
switch (type) {
|
||||
case isc_rwlocktype_read: ck_rwlock_read_lock(rwl); break;
|
||||
case isc_rwlocktype_write: ck_rwlock_write_lock(rwl); break;
|
||||
default: INSIST(0);
|
||||
}
|
||||
|
||||
do {
|
||||
if (cnt++ >= max_cnt) {
|
||||
result = isc__rwlock_lock(rwl, type);
|
||||
break;
|
||||
}
|
||||
#ifdef ISC_PLATFORM_BUSYWAITNOP
|
||||
ISC_PLATFORM_BUSYWAITNOP;
|
||||
#endif
|
||||
} while (isc_rwlock_trylock(rwl, type) != ISC_R_SUCCESS);
|
||||
|
||||
rwl->spins += (cnt - rwl->spins) / 8;
|
||||
|
||||
return (result);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
inline
|
||||
isc_result_t
|
||||
isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
int32_t cntflag;
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_PRELOCK, "prelock"), rwl, type);
|
||||
#endif
|
||||
|
||||
if (type == isc_rwlocktype_read) {
|
||||
/* If a writer is waiting or working, we fail. */
|
||||
if (rwl->write_requests != rwl->write_completions)
|
||||
return (ISC_R_LOCKBUSY);
|
||||
|
||||
/* Otherwise, be ready for reading. */
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
cntflag = atomic_fetch_add_explicit(&rwl->cnt_and_flag,
|
||||
READER_INCR,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
|
||||
#endif
|
||||
if ((cntflag & WRITER_ACTIVE) != 0) {
|
||||
/*
|
||||
* A writer is working. We lose, and cancel the read
|
||||
* request.
|
||||
*/
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
cntflag = atomic_fetch_sub_explicit
|
||||
(&rwl->cnt_and_flag, READER_INCR,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
cntflag = isc_atomic_xadd(&rwl->cnt_and_flag,
|
||||
-READER_INCR);
|
||||
#endif
|
||||
/*
|
||||
* If no other readers are waiting and we've suspended
|
||||
* new writers in this short period, wake them up.
|
||||
*/
|
||||
if (cntflag == READER_INCR &&
|
||||
rwl->write_completions != rwl->write_requests) {
|
||||
LOCK(&rwl->lock);
|
||||
BROADCAST(&rwl->writeable);
|
||||
UNLOCK(&rwl->lock);
|
||||
}
|
||||
|
||||
return (ISC_R_LOCKBUSY);
|
||||
}
|
||||
} else {
|
||||
/* Try locking without entering the waiting queue. */
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
int_fast32_t zero = 0;
|
||||
if (!atomic_compare_exchange_strong_explicit
|
||||
(&rwl->cnt_and_flag, &zero, WRITER_ACTIVE,
|
||||
memory_order_relaxed, memory_order_relaxed))
|
||||
return (ISC_R_LOCKBUSY);
|
||||
#else
|
||||
cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
|
||||
WRITER_ACTIVE);
|
||||
if (cntflag != 0)
|
||||
return (ISC_R_LOCKBUSY);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXXJT: jump into the queue, possibly breaking the writer
|
||||
* order.
|
||||
*/
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
atomic_fetch_sub_explicit(&rwl->write_completions, 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
(void)isc_atomic_xadd(&rwl->write_completions, -1);
|
||||
#endif
|
||||
|
||||
rwl->write_granted++;
|
||||
bool ret = false;
|
||||
switch (type) {
|
||||
case isc_rwlocktype_read: ret = ck_rwlock_read_trylock(rwl); break;
|
||||
case isc_rwlocktype_write: ret = ck_rwlock_write_trylock(rwl); break;
|
||||
default: INSIST(0);
|
||||
}
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_POSTLOCK, "postlock"), rwl, type);
|
||||
#endif
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
{
|
||||
int_fast32_t reader_incr = READER_INCR;
|
||||
|
||||
/* Try to acquire write access. */
|
||||
atomic_compare_exchange_strong_explicit
|
||||
(&rwl->cnt_and_flag, &reader_incr, WRITER_ACTIVE,
|
||||
memory_order_relaxed, memory_order_relaxed);
|
||||
/*
|
||||
* There must have been no writer, and there must have
|
||||
* been at least one reader.
|
||||
*/
|
||||
INSIST((reader_incr & WRITER_ACTIVE) == 0 &&
|
||||
(reader_incr & ~WRITER_ACTIVE) != 0);
|
||||
|
||||
if (reader_incr == READER_INCR) {
|
||||
/*
|
||||
* We are the only reader and have been upgraded.
|
||||
* Now jump into the head of the writer waiting queue.
|
||||
*/
|
||||
atomic_fetch_sub_explicit(&rwl->write_completions, 1,
|
||||
memory_order_relaxed);
|
||||
} else
|
||||
return (ISC_R_LOCKBUSY);
|
||||
|
||||
}
|
||||
#else
|
||||
{
|
||||
int32_t prevcnt;
|
||||
|
||||
/* Try to acquire write access. */
|
||||
prevcnt = isc_atomic_cmpxchg(&rwl->cnt_and_flag,
|
||||
READER_INCR, WRITER_ACTIVE);
|
||||
/*
|
||||
* There must have been no writer, and there must have
|
||||
* been at least one reader.
|
||||
*/
|
||||
INSIST((prevcnt & WRITER_ACTIVE) == 0 &&
|
||||
(prevcnt & ~WRITER_ACTIVE) != 0);
|
||||
|
||||
if (prevcnt == READER_INCR) {
|
||||
/*
|
||||
* We are the only reader and have been upgraded.
|
||||
* Now jump into the head of the writer waiting queue.
|
||||
*/
|
||||
(void)isc_atomic_xadd(&rwl->write_completions, -1);
|
||||
} else
|
||||
return (ISC_R_LOCKBUSY);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
||||
int32_t prev_readers;
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
{
|
||||
/* Become an active reader. */
|
||||
prev_readers = atomic_fetch_add_explicit(&rwl->cnt_and_flag,
|
||||
READER_INCR,
|
||||
memory_order_relaxed);
|
||||
/* We must have been a writer. */
|
||||
INSIST((prev_readers & WRITER_ACTIVE) != 0);
|
||||
|
||||
/* Complete write */
|
||||
atomic_fetch_sub_explicit(&rwl->cnt_and_flag, WRITER_ACTIVE,
|
||||
memory_order_relaxed);
|
||||
atomic_fetch_add_explicit(&rwl->write_completions, 1,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Become an active reader. */
|
||||
prev_readers = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
|
||||
/* We must have been a writer. */
|
||||
INSIST((prev_readers & WRITER_ACTIVE) != 0);
|
||||
|
||||
/* Complete write */
|
||||
(void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
|
||||
(void)isc_atomic_xadd(&rwl->write_completions, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Resume other readers */
|
||||
LOCK(&rwl->lock);
|
||||
if (rwl->readers_waiting > 0)
|
||||
BROADCAST(&rwl->readable);
|
||||
UNLOCK(&rwl->lock);
|
||||
return ((ret)?ISC_R_SUCCESS:ISC_R_LOCKBUSY);
|
||||
}
|
||||
|
||||
inline
|
||||
isc_result_t
|
||||
isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
int32_t prev_cnt;
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
|
||||
#endif
|
||||
|
||||
if (type == isc_rwlocktype_read) {
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
prev_cnt = atomic_fetch_sub_explicit(&rwl->cnt_and_flag,
|
||||
READER_INCR,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
prev_cnt = isc_atomic_xadd(&rwl->cnt_and_flag, -READER_INCR);
|
||||
#endif
|
||||
/*
|
||||
* If we're the last reader and any writers are waiting, wake
|
||||
* them up. We need to wake up all of them to ensure the
|
||||
* FIFO order.
|
||||
*/
|
||||
if (prev_cnt == READER_INCR &&
|
||||
rwl->write_completions != rwl->write_requests) {
|
||||
LOCK(&rwl->lock);
|
||||
BROADCAST(&rwl->writeable);
|
||||
UNLOCK(&rwl->lock);
|
||||
}
|
||||
} else {
|
||||
bool wakeup_writers = true;
|
||||
|
||||
/*
|
||||
* Reset the flag, and (implicitly) tell other writers
|
||||
* we are done.
|
||||
*/
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
atomic_fetch_sub_explicit(&rwl->cnt_and_flag, WRITER_ACTIVE,
|
||||
memory_order_relaxed);
|
||||
atomic_fetch_add_explicit(&rwl->write_completions, 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
(void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
|
||||
(void)isc_atomic_xadd(&rwl->write_completions, 1);
|
||||
#endif
|
||||
|
||||
if (rwl->write_granted >= rwl->write_quota ||
|
||||
rwl->write_requests == rwl->write_completions ||
|
||||
(rwl->cnt_and_flag & ~WRITER_ACTIVE) != 0) {
|
||||
/*
|
||||
* We have passed the write quota, no writer is
|
||||
* waiting, or some readers are almost ready, pending
|
||||
* possible writers. Note that the last case can
|
||||
* happen even if write_requests != write_completions
|
||||
* (which means a new writer in the queue), so we need
|
||||
* to catch the case explicitly.
|
||||
*/
|
||||
LOCK(&rwl->lock);
|
||||
if (rwl->readers_waiting > 0) {
|
||||
wakeup_writers = false;
|
||||
BROADCAST(&rwl->readable);
|
||||
}
|
||||
UNLOCK(&rwl->lock);
|
||||
}
|
||||
|
||||
if (rwl->write_requests != rwl->write_completions &&
|
||||
wakeup_writers) {
|
||||
LOCK(&rwl->lock);
|
||||
BROADCAST(&rwl->writeable);
|
||||
UNLOCK(&rwl->lock);
|
||||
}
|
||||
switch (type) {
|
||||
case isc_rwlocktype_read: ck_rwlock_read_unlock(rwl); break;
|
||||
case isc_rwlocktype_write: ck_rwlock_write_unlock(rwl); break;
|
||||
default: INSIST(0);
|
||||
}
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_POSTUNLOCK, "postunlock"),
|
||||
rwl, type);
|
||||
#endif
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
#else /* ISC_RWLOCK_USEATOMIC */
|
||||
|
||||
static isc_result_t
|
||||
doit(isc_rwlock_t *rwl, isc_rwlocktype_t type, bool nonblock) {
|
||||
bool skip = false;
|
||||
bool done = false;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
LOCK(&rwl->lock);
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_PRELOCK, "prelock"), rwl, type);
|
||||
#endif
|
||||
|
||||
if (type == isc_rwlocktype_read) {
|
||||
if (rwl->readers_waiting != 0)
|
||||
skip = true;
|
||||
while (!done) {
|
||||
if (!skip &&
|
||||
((rwl->active == 0 ||
|
||||
(rwl->type == isc_rwlocktype_read &&
|
||||
(rwl->writers_waiting == 0 ||
|
||||
rwl->granted < rwl->read_quota)))))
|
||||
{
|
||||
rwl->type = isc_rwlocktype_read;
|
||||
rwl->active++;
|
||||
rwl->granted++;
|
||||
done = true;
|
||||
} else if (nonblock) {
|
||||
result = ISC_R_LOCKBUSY;
|
||||
done = true;
|
||||
} else {
|
||||
skip = false;
|
||||
rwl->readers_waiting++;
|
||||
WAIT(&rwl->readable, &rwl->lock);
|
||||
rwl->readers_waiting--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (rwl->writers_waiting != 0)
|
||||
skip = true;
|
||||
while (!done) {
|
||||
if (!skip && rwl->active == 0) {
|
||||
rwl->type = isc_rwlocktype_write;
|
||||
rwl->active = 1;
|
||||
rwl->granted++;
|
||||
done = true;
|
||||
} else if (nonblock) {
|
||||
result = ISC_R_LOCKBUSY;
|
||||
done = true;
|
||||
} else {
|
||||
skip = false;
|
||||
rwl->writers_waiting++;
|
||||
WAIT(&rwl->writeable, &rwl->lock);
|
||||
rwl->writers_waiting--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_POSTLOCK, "postlock"), rwl, type);
|
||||
#endif
|
||||
|
||||
UNLOCK(&rwl->lock);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
int32_t cnt = 0;
|
||||
int32_t max_cnt = rwl->spins * 2 + 10;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
if (max_cnt > RWLOCK_MAX_ADAPTIVE_COUNT)
|
||||
max_cnt = RWLOCK_MAX_ADAPTIVE_COUNT;
|
||||
|
||||
do {
|
||||
if (cnt++ >= max_cnt) {
|
||||
result = doit(rwl, type, false);
|
||||
break;
|
||||
}
|
||||
#ifdef ISC_PLATFORM_BUSYWAITNOP
|
||||
ISC_PLATFORM_BUSYWAITNOP;
|
||||
#endif
|
||||
} while (doit(rwl, type, true) != ISC_R_SUCCESS);
|
||||
|
||||
rwl->spins += (cnt - rwl->spins) / 8;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
return (doit(rwl, type, true));
|
||||
}
|
||||
|
||||
inline
|
||||
isc_result_t
|
||||
isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
LOCK(&rwl->lock);
|
||||
REQUIRE(rwl->type == isc_rwlocktype_read);
|
||||
REQUIRE(rwl->active != 0);
|
||||
|
||||
/* If we are the only reader then succeed. */
|
||||
if (rwl->active == 1) {
|
||||
rwl->original = (rwl->original == isc_rwlocktype_none) ?
|
||||
isc_rwlocktype_read : isc_rwlocktype_none;
|
||||
rwl->type = isc_rwlocktype_write;
|
||||
} else
|
||||
result = ISC_R_LOCKBUSY;
|
||||
|
||||
UNLOCK(&rwl->lock);
|
||||
return (result);
|
||||
UNUSED(rwl);
|
||||
return (ISC_R_LOCKBUSY);
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
LOCK(&rwl->lock);
|
||||
REQUIRE(rwl->type == isc_rwlocktype_write);
|
||||
REQUIRE(rwl->active == 1);
|
||||
|
||||
rwl->type = isc_rwlocktype_read;
|
||||
rwl->original = (rwl->original == isc_rwlocktype_none) ?
|
||||
isc_rwlocktype_write : isc_rwlocktype_none;
|
||||
/*
|
||||
* Resume processing any read request that were blocked when
|
||||
* we upgraded.
|
||||
*/
|
||||
if (rwl->original == isc_rwlocktype_none &&
|
||||
(rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) &&
|
||||
rwl->readers_waiting > 0)
|
||||
BROADCAST(&rwl->readable);
|
||||
|
||||
UNLOCK(&rwl->lock);
|
||||
ck_rwlock_write_downgrade(rwl);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
LOCK(&rwl->lock);
|
||||
REQUIRE(rwl->type == type);
|
||||
|
||||
UNUSED(type);
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
|
||||
#endif
|
||||
|
||||
INSIST(rwl->active > 0);
|
||||
rwl->active--;
|
||||
if (rwl->active == 0) {
|
||||
if (rwl->original != isc_rwlocktype_none) {
|
||||
rwl->type = rwl->original;
|
||||
rwl->original = isc_rwlocktype_none;
|
||||
}
|
||||
if (rwl->type == isc_rwlocktype_read) {
|
||||
rwl->granted = 0;
|
||||
if (rwl->writers_waiting > 0) {
|
||||
rwl->type = isc_rwlocktype_write;
|
||||
SIGNAL(&rwl->writeable);
|
||||
} else if (rwl->readers_waiting > 0) {
|
||||
/* Does this case ever happen? */
|
||||
BROADCAST(&rwl->readable);
|
||||
}
|
||||
} else {
|
||||
if (rwl->readers_waiting > 0) {
|
||||
if (rwl->writers_waiting > 0 &&
|
||||
rwl->granted < rwl->write_quota) {
|
||||
SIGNAL(&rwl->writeable);
|
||||
} else {
|
||||
rwl->granted = 0;
|
||||
rwl->type = isc_rwlocktype_read;
|
||||
BROADCAST(&rwl->readable);
|
||||
}
|
||||
} else if (rwl->writers_waiting > 0) {
|
||||
rwl->granted = 0;
|
||||
SIGNAL(&rwl->writeable);
|
||||
} else {
|
||||
rwl->granted = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
INSIST(rwl->original == isc_rwlocktype_none);
|
||||
|
||||
#ifdef ISC_RWLOCK_TRACE
|
||||
print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
|
||||
ISC_MSG_POSTUNLOCK, "postunlock"),
|
||||
rwl, type);
|
||||
#endif
|
||||
|
||||
UNLOCK(&rwl->lock);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
#endif /* ISC_RWLOCK_USEATOMIC */
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = include
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = isc
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,29 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
HEADERS = atomic.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
|
||||
|
||||
install:: installdirs
|
||||
for i in ${HEADERS}; do \
|
||||
${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
|
||||
done
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This code was written based on FreeBSD's kernel source whose copyright
|
||||
* follows:
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 Doug Rabson.
|
||||
* Copyright (c) 2001 Jake Burkholder.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: FreeBSD: src/sys/i386/include/atomic.h,v 1.20 2001/02/11
|
||||
* $FreeBSD: src/sys/sparc64/include/atomic.h,v 1.8 2004/05/22 00:52:16 marius Exp $
|
||||
*/
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#define ASI_P 0x80 /* Primary Address Space Identifier */
|
||||
|
||||
#ifdef ISC_PLATFORM_USEGCCASM
|
||||
|
||||
/*
|
||||
* This routine atomically increments the value stored in 'p' by 'val', and
|
||||
* returns the previous value.
|
||||
*/
|
||||
static inline int32_t
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
int32_t prev, swapped;
|
||||
|
||||
for (prev = *(volatile int32_t *)p; ; prev = swapped) {
|
||||
swapped = prev + val;
|
||||
__asm__ volatile(
|
||||
"casa [%2] %3, %4, %0"
|
||||
: "+r"(swapped), "=m"(*p)
|
||||
: "r"(p), "n"(ASI_P), "r"(prev), "m"(*p));
|
||||
if (swapped == prev)
|
||||
break;
|
||||
}
|
||||
|
||||
return (prev);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine atomically stores the value 'val' in 'p'.
|
||||
*/
|
||||
static inline void
|
||||
isc_atomic_store(int32_t *p, int32_t val) {
|
||||
int32_t prev, swapped;
|
||||
|
||||
for (prev = *(volatile int32_t *)p; ; prev = swapped) {
|
||||
swapped = val;
|
||||
__asm__ volatile(
|
||||
"casa [%2] %3, %4, %0"
|
||||
: "+r"(swapped), "=m"(*p)
|
||||
: "r"(p), "n"(ASI_P), "r"(prev), "m"(*p));
|
||||
if (swapped == prev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine atomically replaces the value in 'p' with 'val', if the
|
||||
* original value is equal to 'cmpval'. The original value is returned in any
|
||||
* case.
|
||||
*/
|
||||
static inline int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
|
||||
int32_t temp = val;
|
||||
|
||||
__asm__ volatile(
|
||||
"casa [%2] %3, %4, %0"
|
||||
: "+r"(temp), "=m"(*p)
|
||||
: "r"(p), "n"(ASI_P), "r"(cmpval), "m"(*p));
|
||||
|
||||
return (temp);
|
||||
}
|
||||
|
||||
#else /* ISC_PLATFORM_USEGCCASM */
|
||||
|
||||
#error "unsupported compiler. disable atomic ops by --disable-atomic"
|
||||
|
||||
#endif /* ISC_PLATFORM_USEGCCASM */
|
||||
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
+50
-341
@@ -17,7 +17,8 @@
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
@@ -27,211 +28,47 @@
|
||||
#include <isc/stats.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVESTDATOMIC)
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
|
||||
#define ISC_STATS_MAGIC ISC_MAGIC('S', 't', 'a', 't')
|
||||
#define ISC_STATS_VALID(x) ISC_MAGIC_VALID(x, ISC_STATS_MAGIC)
|
||||
|
||||
/*%
|
||||
* Local macro confirming prescence of 64-bit
|
||||
* increment and store operations, just to make
|
||||
* the later macros simpler
|
||||
*/
|
||||
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_LONG_LOCK_FREE)) || \
|
||||
(defined(ISC_PLATFORM_HAVEXADDQ) && defined(ISC_PLATFORM_HAVEATOMICSTOREQ))
|
||||
#define ISC_STATS_HAVEATOMICQ 1
|
||||
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_LONG_LOCK_FREE))
|
||||
#define ISC_STATS_HAVESTDATOMICQ 1
|
||||
#endif
|
||||
#else
|
||||
#define ISC_STATS_HAVEATOMICQ 0
|
||||
#endif
|
||||
|
||||
/*%
|
||||
* Only lock the counters if 64-bit atomic operations are
|
||||
* not available but cheap atomic lock operations are.
|
||||
* On a modern 64-bit system this should never be the case.
|
||||
*
|
||||
* Normal locks are too expensive to be used whenever a counter
|
||||
* is updated.
|
||||
*/
|
||||
#if !ISC_STATS_HAVEATOMICQ && defined(ISC_RWLOCK_HAVEATOMIC)
|
||||
#define ISC_STATS_LOCKCOUNTERS 1
|
||||
#else
|
||||
#define ISC_STATS_LOCKCOUNTERS 0
|
||||
#endif
|
||||
|
||||
/*%
|
||||
* If 64-bit atomic operations are not available but
|
||||
* 32-bit operations are then split the counter into two,
|
||||
* using the atomic operations to try to ensure that any carry
|
||||
* from the low word is correctly carried into the high word.
|
||||
*
|
||||
* Otherwise, just rely on standard 64-bit data types
|
||||
* and operations
|
||||
*/
|
||||
#if !ISC_STATS_HAVEATOMICQ && ((defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE)) || defined(ISC_PLATFORM_HAVEXADD))
|
||||
#define ISC_STATS_USEMULTIFIELDS 1
|
||||
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE))
|
||||
#define ISC_STATS_HAVESTDATOMIC 1
|
||||
#endif
|
||||
#else
|
||||
#define ISC_STATS_USEMULTIFIELDS 0
|
||||
#endif
|
||||
|
||||
#if ISC_STATS_USEMULTIFIELDS
|
||||
typedef struct {
|
||||
#if defined(ISC_STATS_HAVESTDATOMIC)
|
||||
atomic_int_fast32_t hi;
|
||||
atomic_int_fast32_t lo;
|
||||
#else
|
||||
uint32_t hi;
|
||||
uint32_t lo;
|
||||
#endif
|
||||
} isc_stat_t;
|
||||
#else
|
||||
#if defined(ISC_STATS_HAVESTDATOMICQ)
|
||||
typedef atomic_int_fast64_t isc_stat_t;
|
||||
#else
|
||||
typedef uint64_t isc_stat_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct isc_stats {
|
||||
/*% Unlocked */
|
||||
unsigned int magic;
|
||||
isc_mem_t *mctx;
|
||||
int ncounters;
|
||||
|
||||
isc_mutex_t lock;
|
||||
unsigned int references; /* locked by lock */
|
||||
unsigned int references;
|
||||
|
||||
/*%
|
||||
* Locked by counterlock or unlocked if efficient rwlock is not
|
||||
* available.
|
||||
*/
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
isc_rwlock_t counterlock;
|
||||
#endif
|
||||
isc_stat_t *counters;
|
||||
|
||||
/*%
|
||||
* We don't want to lock the counters while we are dumping, so we first
|
||||
* copy the current counter values into a local array. This buffer
|
||||
* will be used as the copy destination. It's allocated on creation
|
||||
* of the stats structure so that the dump operation won't fail due
|
||||
* to memory allocation failure.
|
||||
* XXX: this approach is weird for non-threaded build because the
|
||||
* additional memory and the copy overhead could be avoided. We prefer
|
||||
* simplicity here, however, under the assumption that this function
|
||||
* should be only rarely called.
|
||||
*/
|
||||
uint64_t *copiedcounters;
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
|
||||
isc_stats_t *stats;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
REQUIRE(statsp != NULL && *statsp == NULL);
|
||||
|
||||
stats = isc_mem_get(mctx, sizeof(*stats));
|
||||
if (stats == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
result = isc_mutex_init(&stats->lock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto clean_stats;
|
||||
|
||||
stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters);
|
||||
if (stats->counters == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto clean_mutex;
|
||||
}
|
||||
stats->copiedcounters = isc_mem_get(mctx,
|
||||
sizeof(uint64_t) * ncounters);
|
||||
if (stats->copiedcounters == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto clean_counters;
|
||||
}
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
result = isc_rwlock_init(&stats->counterlock, 0, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto clean_copiedcounters;
|
||||
#endif
|
||||
|
||||
stats->references = 1;
|
||||
memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters);
|
||||
stats->mctx = NULL;
|
||||
isc_mem_attach(mctx, &stats->mctx);
|
||||
stats->ncounters = ncounters;
|
||||
stats->magic = ISC_STATS_MAGIC;
|
||||
|
||||
*statsp = stats;
|
||||
|
||||
return (result);
|
||||
|
||||
clean_counters:
|
||||
isc_mem_put(mctx, stats->counters, sizeof(isc_stat_t) * ncounters);
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
clean_copiedcounters:
|
||||
isc_mem_put(mctx, stats->copiedcounters,
|
||||
sizeof(isc_stat_t) * ncounters);
|
||||
#endif
|
||||
|
||||
clean_mutex:
|
||||
DESTROYLOCK(&stats->lock);
|
||||
|
||||
clean_stats:
|
||||
isc_mem_put(mctx, stats, sizeof(*stats));
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp) {
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(statsp != NULL && *statsp == NULL);
|
||||
|
||||
LOCK(&stats->lock);
|
||||
stats->references++;
|
||||
UNLOCK(&stats->lock);
|
||||
ck_pr_inc_uint(&stats->references);
|
||||
|
||||
*statsp = stats;
|
||||
}
|
||||
|
||||
void
|
||||
isc_stats_detach(isc_stats_t **statsp) {
|
||||
isc_stats_t *stats;
|
||||
|
||||
REQUIRE(statsp != NULL && ISC_STATS_VALID(*statsp));
|
||||
|
||||
stats = *statsp;
|
||||
*statsp = NULL;
|
||||
isc_stats_t *stats = *statsp;
|
||||
|
||||
LOCK(&stats->lock);
|
||||
stats->references--;
|
||||
ck_pr_dec_uint(&stats->references);
|
||||
ck_pr_fence_atomic_load();
|
||||
|
||||
if (stats->references == 0) {
|
||||
isc_mem_put(stats->mctx, stats->copiedcounters,
|
||||
sizeof(isc_stat_t) * stats->ncounters);
|
||||
if (ck_pr_load_uint((const unsigned int *)&stats->references) == 0) {
|
||||
isc_mem_put(stats->mctx, stats->counters,
|
||||
sizeof(isc_stat_t) * stats->ncounters);
|
||||
UNLOCK(&stats->lock);
|
||||
DESTROYLOCK(&stats->lock);
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
isc_rwlock_destroy(&stats->counterlock);
|
||||
#endif
|
||||
isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
|
||||
return;
|
||||
}
|
||||
|
||||
UNLOCK(&stats->lock);
|
||||
*statsp = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -241,144 +78,40 @@ isc_stats_ncounters(isc_stats_t *stats) {
|
||||
return (stats->ncounters);
|
||||
}
|
||||
|
||||
static inline void
|
||||
incrementcounter(isc_stats_t *stats, int counter) {
|
||||
int32_t prev;
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
/*
|
||||
* We use a "read" lock to prevent other threads from reading the
|
||||
* counter while we "writing" a counter field. The write access itself
|
||||
* is protected by the atomic operation.
|
||||
*/
|
||||
isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
|
||||
#endif
|
||||
|
||||
#if ISC_STATS_USEMULTIFIELDS
|
||||
#if defined(ISC_STATS_HAVESTDATOMIC)
|
||||
prev = atomic_fetch_add_explicit(&stats->counters[counter].lo, 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
prev = isc_atomic_xadd((int32_t *)&stats->counters[counter].lo, 1);
|
||||
#endif
|
||||
/*
|
||||
* If the lower 32-bit field overflows, increment the higher field.
|
||||
* Note that it's *theoretically* possible that the lower field
|
||||
* overlaps again before the higher field is incremented. It doesn't
|
||||
* matter, however, because we don't read the value until
|
||||
* isc_stats_copy() is called where the whole process is protected
|
||||
* by the write (exclusive) lock.
|
||||
*/
|
||||
if (prev == (int32_t)0xffffffff) {
|
||||
#if defined(ISC_STATS_HAVESTDATOMIC)
|
||||
atomic_fetch_add_explicit(&stats->counters[counter].hi, 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
isc_atomic_xadd((int32_t *)&stats->counters[counter].hi, 1);
|
||||
#endif
|
||||
}
|
||||
#elif ISC_STATS_HAVEATOMICQ
|
||||
UNUSED(prev);
|
||||
#if defined(ISC_STATS_HAVESTDATOMICQ)
|
||||
atomic_fetch_add_explicit(&stats->counters[counter], 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
isc_atomic_xaddq((int64_t *)&stats->counters[counter], 1);
|
||||
#endif
|
||||
#else
|
||||
UNUSED(prev);
|
||||
stats->counters[counter]++;
|
||||
#endif
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
decrementcounter(isc_stats_t *stats, int counter) {
|
||||
int32_t prev;
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
|
||||
#endif
|
||||
|
||||
#if ISC_STATS_USEMULTIFIELDS
|
||||
#if defined(ISC_STATS_HAVESTDATOMIC)
|
||||
prev = atomic_fetch_sub_explicit(&stats->counters[counter].lo, 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
prev = isc_atomic_xadd((int32_t *)&stats->counters[counter].lo, -1);
|
||||
#endif
|
||||
if (prev == 0) {
|
||||
#if defined(ISC_STATS_HAVESTDATOMIC)
|
||||
atomic_fetch_sub_explicit(&stats->counters[counter].hi, 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
isc_atomic_xadd((int32_t *)&stats->counters[counter].hi,
|
||||
-1);
|
||||
#endif
|
||||
}
|
||||
#elif ISC_STATS_HAVEATOMICQ
|
||||
UNUSED(prev);
|
||||
#if defined(ISC_STATS_HAVESTDATOMICQ)
|
||||
atomic_fetch_sub_explicit(&stats->counters[counter], 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
isc_atomic_xaddq((int64_t *)&stats->counters[counter], -1);
|
||||
#endif
|
||||
#else
|
||||
UNUSED(prev);
|
||||
stats->counters[counter]--;
|
||||
#endif
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
copy_counters(isc_stats_t *stats) {
|
||||
int i;
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
/*
|
||||
* We use a "write" lock before "reading" the statistics counters as
|
||||
* an exclusive lock.
|
||||
*/
|
||||
isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < stats->ncounters; i++) {
|
||||
#if ISC_STATS_USEMULTIFIELDS
|
||||
stats->copiedcounters[i] =
|
||||
(uint64_t)(stats->counters[i].hi) << 32 |
|
||||
stats->counters[i].lo;
|
||||
#elif ISC_STATS_HAVEATOMICQ
|
||||
#if defined(ISC_STATS_HAVESTDATOMICQ)
|
||||
stats->copiedcounters[i] =
|
||||
atomic_load_explicit(&stats->counters[i],
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
/* use xaddq(..., 0) as an atomic load */
|
||||
stats->copiedcounters[i] =
|
||||
(uint64_t)isc_atomic_xaddq((int64_t *)&stats->counters[i], 0);
|
||||
#endif
|
||||
#else
|
||||
stats->copiedcounters[i] = stats->counters[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
|
||||
#endif
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters) {
|
||||
REQUIRE(statsp != NULL && *statsp == NULL);
|
||||
|
||||
return (create_stats(mctx, ncounters, statsp));
|
||||
isc_stats_t *stats;
|
||||
|
||||
stats = isc_mem_get(mctx, sizeof(*stats));
|
||||
if (stats == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters);
|
||||
if (stats->counters == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ck_pr_store_uint(&stats->references, 1);
|
||||
|
||||
memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters);
|
||||
stats->mctx = NULL;
|
||||
isc_mem_attach(mctx, &stats->mctx);
|
||||
stats->ncounters = ncounters;
|
||||
stats->magic = ISC_STATS_MAGIC;
|
||||
|
||||
*statsp = stats;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
if (stats != NULL) {
|
||||
isc_mem_put(mctx, stats, sizeof(*stats));
|
||||
}
|
||||
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -386,7 +119,7 @@ isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter) {
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(counter < stats->ncounters);
|
||||
|
||||
incrementcounter(stats, (int)counter);
|
||||
ck_pr_inc_64(&stats->counters[counter]);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -394,24 +127,24 @@ isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter) {
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(counter < stats->ncounters);
|
||||
|
||||
decrementcounter(stats, (int)counter);
|
||||
ck_pr_dec_64(&stats->counters[counter]);
|
||||
}
|
||||
|
||||
void
|
||||
isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn,
|
||||
void *arg, unsigned int options)
|
||||
{
|
||||
int i;
|
||||
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
|
||||
copy_counters(stats);
|
||||
bool verbose = (options & ISC_STATSDUMP_VERBOSE);
|
||||
|
||||
for (i = 0; i < stats->ncounters; i++) {
|
||||
if ((options & ISC_STATSDUMP_VERBOSE) == 0 &&
|
||||
stats->copiedcounters[i] == 0)
|
||||
continue;
|
||||
dump_fn((isc_statscounter_t)i, stats->copiedcounters[i], arg);
|
||||
for (int i = 0; i < stats->ncounters; i++) {
|
||||
if (!verbose && stats->counters[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
dump_fn((isc_statscounter_t)i,
|
||||
ck_pr_load_64((const uint64_t *)stats->counters[i]),
|
||||
arg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,29 +155,5 @@ isc_stats_set(isc_stats_t *stats, uint64_t val,
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(counter < stats->ncounters);
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
/*
|
||||
* We use a "write" lock before "reading" the statistics counters as
|
||||
* an exclusive lock.
|
||||
*/
|
||||
isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
|
||||
#endif
|
||||
|
||||
#if ISC_STATS_USEMULTIFIELDS
|
||||
stats->counters[counter].hi = (uint32_t)((val >> 32) & 0xffffffff);
|
||||
stats->counters[counter].lo = (uint32_t)(val & 0xffffffff);
|
||||
#elif ISC_STATS_HAVEATOMICQ
|
||||
#if defined(ISC_STATS_HAVESTDATOMICQ)
|
||||
atomic_store_explicit(&stats->counters[counter], val,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
isc_atomic_storeq((int64_t *)&stats->counters[counter], val);
|
||||
#endif
|
||||
#else
|
||||
stats->counters[counter] = val;
|
||||
#endif
|
||||
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
|
||||
#endif
|
||||
ck_pr_store_64(&stats->counters[counter], val);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ Content-Type: application/X-atf-atffile; version="1"
|
||||
prop: test-suite = bind9
|
||||
|
||||
tp: aes_test
|
||||
tp: atomic_test
|
||||
tp: buffer_test
|
||||
tp: counter_test
|
||||
tp: errno_test
|
||||
|
||||
@@ -2,7 +2,6 @@ syntax(2)
|
||||
test_suite('bind9')
|
||||
|
||||
atf_test_program{name='aes_test'}
|
||||
atf_test_program{name='atomic_test'}
|
||||
atf_test_program{name='buffer_test'}
|
||||
atf_test_program{name='counter_test'}
|
||||
atf_test_program{name='errno_test'}
|
||||
|
||||
@@ -31,7 +31,7 @@ CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
|
||||
CMOCKA_LIBS = @CMOCKA_LIBS@
|
||||
|
||||
OBJS = isctest.@O@
|
||||
SRCS = isctest.c aes_test.c atomic_test.c buffer_test.c \
|
||||
SRCS = isctest.c aes_test.c buffer_test.c \
|
||||
counter_test.c errno_test.c file_test.c hash_test.c \
|
||||
heap_test.c ht_test.c inet_ntop_test.c lex_test.c \
|
||||
mem_test.c netaddr_test.c parse_test.c pool_test.c \
|
||||
@@ -41,7 +41,7 @@ SRCS = isctest.c aes_test.c atomic_test.c buffer_test.c \
|
||||
taskpool_test.c time_test.c timer_test.c
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS = aes_test@EXEEXT@ atomic_test@EXEEXT@ buffer_test@EXEEXT@ \
|
||||
TARGETS = aes_test@EXEEXT@ buffer_test@EXEEXT@ \
|
||||
counter_test@EXEEXT@ errno_test@EXEEXT@ file_test@EXEEXT@ \
|
||||
hash_test@EXEEXT@ heap_test@EXEEXT@ ht_test@EXEEXT@ \
|
||||
inet_ntop_test@EXEEXT@ lex_test@EXEEXT@ mem_test@EXEEXT@ \
|
||||
@@ -54,10 +54,6 @@ TARGETS = aes_test@EXEEXT@ atomic_test@EXEEXT@ buffer_test@EXEEXT@ \
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
atomic_test@EXEEXT@: atomic_test.@O@ isctest.@O@ ${ISCDEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
|
||||
atomic_test.@O@ isctest.@O@ ${ISCLIBS} ${LIBS}
|
||||
|
||||
aes_test@EXEEXT@: aes_test.@O@ ${ISCDEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
|
||||
aes_test.@O@ ${ISCLIBS} ${LIBS}
|
||||
|
||||
@@ -1,354 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/result.h>
|
||||
|
||||
#include "isctest.h"
|
||||
|
||||
#define TASKS 32
|
||||
#define ITERATIONS 1000
|
||||
#define COUNTS_PER_ITERATION 1000
|
||||
#define INCREMENT_64 (int64_t)0x0000000010000000
|
||||
#define EXPECTED_COUNT_32 (TASKS * ITERATIONS * COUNTS_PER_ITERATION)
|
||||
#define EXPECTED_COUNT_64 (TASKS * ITERATIONS * COUNTS_PER_ITERATION * INCREMENT_64)
|
||||
|
||||
typedef struct {
|
||||
uint32_t iteration;
|
||||
} counter_t;
|
||||
|
||||
counter_t counters[TASKS];
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVEXADD)
|
||||
static int32_t counter_32;
|
||||
|
||||
static void
|
||||
do_xadd(isc_task_t *task, isc_event_t *ev) {
|
||||
counter_t *state = (counter_t *)ev->ev_arg;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < COUNTS_PER_ITERATION ; i++) {
|
||||
isc_atomic_xadd(&counter_32, 1);
|
||||
}
|
||||
|
||||
state->iteration++;
|
||||
if (state->iteration < ITERATIONS) {
|
||||
isc_task_send(task, &ev);
|
||||
} else {
|
||||
isc_event_free(&ev);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC(atomic_xadd);
|
||||
ATF_TC_HEAD(atomic_xadd, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "atomic XADD");
|
||||
}
|
||||
ATF_TC_BODY(atomic_xadd, tc) {
|
||||
isc_result_t result;
|
||||
isc_task_t *tasks[TASKS];
|
||||
isc_event_t *event = NULL;
|
||||
int i;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL, true, 0);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
memset(counters, 0, sizeof(counters));
|
||||
counter_32 = 0;
|
||||
|
||||
/*
|
||||
* Create our tasks, and allocate an event to get the counters going.
|
||||
*/
|
||||
for (i = 0 ; i < TASKS ; i++) {
|
||||
tasks[i] = NULL;
|
||||
ATF_REQUIRE_EQ(isc_task_create(taskmgr, 0, &tasks[i]),
|
||||
ISC_R_SUCCESS);
|
||||
event = isc_event_allocate(mctx, NULL, 1000, do_xadd,
|
||||
&counters[i],
|
||||
sizeof(struct isc_event));
|
||||
ATF_REQUIRE(event != NULL);
|
||||
isc_task_sendanddetach(&tasks[i], &event);
|
||||
}
|
||||
|
||||
isc_test_end();
|
||||
|
||||
printf("32-bit counter %d, expected %d\n",
|
||||
counter_32, EXPECTED_COUNT_32);
|
||||
|
||||
ATF_CHECK_EQ(counter_32, EXPECTED_COUNT_32);
|
||||
counter_32 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVEXADDQ)
|
||||
static int64_t counter_64;
|
||||
|
||||
static void
|
||||
do_xaddq(isc_task_t *task, isc_event_t *ev) {
|
||||
counter_t *state = (counter_t *)ev->ev_arg;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < COUNTS_PER_ITERATION ; i++) {
|
||||
isc_atomic_xaddq(&counter_64, INCREMENT_64);
|
||||
}
|
||||
|
||||
state->iteration++;
|
||||
if (state->iteration < ITERATIONS) {
|
||||
isc_task_send(task, &ev);
|
||||
} else {
|
||||
isc_event_free(&ev);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC(atomic_xaddq);
|
||||
ATF_TC_HEAD(atomic_xaddq, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "atomic XADDQ");
|
||||
}
|
||||
ATF_TC_BODY(atomic_xaddq, tc) {
|
||||
isc_result_t result;
|
||||
isc_task_t *tasks[TASKS];
|
||||
isc_event_t *event = NULL;
|
||||
int i;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL, true, 0);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
memset(counters, 0, sizeof(counters));
|
||||
counter_64 = 0;
|
||||
|
||||
/*
|
||||
* Create our tasks, and allocate an event to get the counters going.
|
||||
*/
|
||||
for (i = 0 ; i < TASKS ; i++) {
|
||||
tasks[i] = NULL;
|
||||
ATF_REQUIRE_EQ(isc_task_create(taskmgr, 0, &tasks[i]),
|
||||
ISC_R_SUCCESS);
|
||||
event = isc_event_allocate(mctx, NULL, 1000, do_xaddq,
|
||||
&counters[i],
|
||||
sizeof(struct isc_event));
|
||||
ATF_REQUIRE(event != NULL);
|
||||
isc_task_sendanddetach(&tasks[i], &event);
|
||||
}
|
||||
|
||||
isc_test_end();
|
||||
|
||||
printf("64-bit counter %" PRId64 ", "
|
||||
"expected %" PRId64 "\n",
|
||||
counter_64, EXPECTED_COUNT_64);
|
||||
|
||||
ATF_CHECK_EQ(counter_64, EXPECTED_COUNT_64);
|
||||
counter_32 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVEATOMICSTORE)
|
||||
static int32_t store_32;
|
||||
|
||||
static void
|
||||
do_store(isc_task_t *task, isc_event_t *ev) {
|
||||
counter_t *state = (counter_t *)ev->ev_arg;
|
||||
int i;
|
||||
uint32_t r;
|
||||
uint32_t val;
|
||||
|
||||
r = random() % 256;
|
||||
val = (r << 24) | (r << 16) | (r << 8) | r;
|
||||
|
||||
for (i = 0 ; i < COUNTS_PER_ITERATION ; i++) {
|
||||
isc_atomic_store(&store_32, val);
|
||||
}
|
||||
|
||||
state->iteration++;
|
||||
if (state->iteration < ITERATIONS) {
|
||||
isc_task_send(task, &ev);
|
||||
} else {
|
||||
isc_event_free(&ev);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC(atomic_store);
|
||||
ATF_TC_HEAD(atomic_store, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "atomic STORE");
|
||||
}
|
||||
ATF_TC_BODY(atomic_store, tc) {
|
||||
isc_result_t result;
|
||||
isc_task_t *tasks[TASKS];
|
||||
isc_event_t *event = NULL;
|
||||
uint32_t val;
|
||||
uint32_t r;
|
||||
int i;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL, true, 0);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
memset(counters, 0, sizeof(counters));
|
||||
store_32 = 0;
|
||||
|
||||
/*
|
||||
* Create our tasks, and allocate an event to get the counters
|
||||
* going.
|
||||
*/
|
||||
for (i = 0 ; i < TASKS ; i++) {
|
||||
tasks[i] = NULL;
|
||||
ATF_REQUIRE_EQ(isc_task_create(taskmgr, 0, &tasks[i]),
|
||||
ISC_R_SUCCESS);
|
||||
event = isc_event_allocate(mctx, NULL, 1000, do_store,
|
||||
&counters[i],
|
||||
sizeof(struct isc_event));
|
||||
ATF_REQUIRE(event != NULL);
|
||||
isc_task_sendanddetach(&tasks[i], &event);
|
||||
}
|
||||
|
||||
isc_test_end();
|
||||
|
||||
r = store_32 & 0xff;
|
||||
val = (r << 24) | (r << 16) | (r << 8) | r;
|
||||
|
||||
printf("32-bit store 0x%x, expected 0x%x\n",
|
||||
(uint32_t) store_32, val);
|
||||
|
||||
ATF_CHECK_EQ((uint32_t) store_32, val);
|
||||
store_32 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVEATOMICSTOREQ)
|
||||
static int64_t store_64;
|
||||
|
||||
static void
|
||||
do_storeq(isc_task_t *task, isc_event_t *ev) {
|
||||
counter_t *state = (counter_t *)ev->ev_arg;
|
||||
int i;
|
||||
uint8_t r;
|
||||
uint64_t val;
|
||||
|
||||
r = random() % 256;
|
||||
val = (((uint64_t) r << 24) |
|
||||
((uint64_t) r << 16) |
|
||||
((uint64_t) r << 8) |
|
||||
(uint64_t) r);
|
||||
val |= ((uint64_t) val << 32);
|
||||
|
||||
for (i = 0 ; i < COUNTS_PER_ITERATION ; i++) {
|
||||
isc_atomic_storeq(&store_64, val);
|
||||
}
|
||||
|
||||
state->iteration++;
|
||||
if (state->iteration < ITERATIONS) {
|
||||
isc_task_send(task, &ev);
|
||||
} else {
|
||||
isc_event_free(&ev);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC(atomic_storeq);
|
||||
ATF_TC_HEAD(atomic_storeq, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "atomic STOREQ");
|
||||
}
|
||||
ATF_TC_BODY(atomic_storeq, tc) {
|
||||
isc_result_t result;
|
||||
isc_task_t *tasks[TASKS];
|
||||
isc_event_t *event = NULL;
|
||||
uint64_t val;
|
||||
uint32_t r;
|
||||
int i;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL, true, 0);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
memset(counters, 0, sizeof(counters));
|
||||
store_64 = 0;
|
||||
|
||||
/*
|
||||
* Create our tasks, and allocate an event to get the counters
|
||||
* going.
|
||||
*/
|
||||
for (i = 0 ; i < TASKS ; i++) {
|
||||
tasks[i] = NULL;
|
||||
ATF_REQUIRE_EQ(isc_task_create(taskmgr, 0, &tasks[i]),
|
||||
ISC_R_SUCCESS);
|
||||
event = isc_event_allocate(mctx, NULL, 1000, do_storeq,
|
||||
&counters[i],
|
||||
sizeof(struct isc_event));
|
||||
ATF_REQUIRE(event != NULL);
|
||||
isc_task_sendanddetach(&tasks[i], &event);
|
||||
}
|
||||
|
||||
isc_test_end();
|
||||
|
||||
r = store_64 & 0xff;
|
||||
val = (((uint64_t) r << 24) |
|
||||
((uint64_t) r << 16) |
|
||||
((uint64_t) r << 8) |
|
||||
(uint64_t) r);
|
||||
val |= ((uint64_t) val << 32);
|
||||
|
||||
printf("64-bit store 0x%" PRIx64 ", "
|
||||
"expected 0x%" PRIx64 "\n",
|
||||
(uint64_t) store_64, val);
|
||||
|
||||
ATF_CHECK_EQ((uint64_t) store_64, val);
|
||||
store_64 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ISC_PLATFORM_HAVEXADD) && \
|
||||
!defined(ISC_PLATFORM_HAVEXADDQ) && \
|
||||
!defined(ISC_PLATFORM_HAVEATOMICSTOREQ)
|
||||
ATF_TC(untested);
|
||||
ATF_TC_HEAD(untested, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "skipping aes test");
|
||||
}
|
||||
ATF_TC_BODY(untested, tc) {
|
||||
UNUSED(tc);
|
||||
atf_tc_skip("AES not available");
|
||||
}
|
||||
#endif /* !HAVEXADD, !HAVEXADDQ, !HAVEATOMICSTOREQ */
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
ATF_TP_ADD_TCS(tp) {
|
||||
#if defined(ISC_PLATFORM_HAVEXADD)
|
||||
ATF_TP_ADD_TC(tp, atomic_xadd);
|
||||
#endif
|
||||
#if defined(ISC_PLATFORM_HAVEXADDQ)
|
||||
ATF_TP_ADD_TC(tp, atomic_xaddq);
|
||||
#endif
|
||||
#ifdef ISC_PLATFORM_HAVEATOMICSTORE
|
||||
ATF_TP_ADD_TC(tp, atomic_store);
|
||||
#endif
|
||||
#if defined(ISC_PLATFORM_HAVEATOMICSTOREQ)
|
||||
ATF_TP_ADD_TC(tp, atomic_storeq);
|
||||
#endif
|
||||
#if !defined(ISC_PLATFORM_HAVEXADD) && \
|
||||
!defined(ISC_PLATFORM_HAVEXADDQ) && \
|
||||
!defined(ISC_PLATFORM_HAVEATOMICSTOREQ)
|
||||
ATF_TP_ADD_TC(tp, untested);
|
||||
#endif
|
||||
|
||||
return (atf_no_error());
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
/*
|
||||
* This routine atomically increments the value stored in 'p' by 'val', and
|
||||
* returns the previous value.
|
||||
*/
|
||||
#ifdef ISC_PLATFORM_HAVEXADD
|
||||
static __inline int32_t
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
return (int32_t) _InterlockedExchangeAdd((long *)p, (long)val);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEXADDQ
|
||||
static __inline int64_t
|
||||
isc_atomic_xaddq(int64_t *p, int64_t val) {
|
||||
return (int64_t) _InterlockedExchangeAdd64((__int64 *)p,
|
||||
(__int64) val);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This routine atomically stores the value 'val' in 'p' (32-bit version).
|
||||
*/
|
||||
#ifdef ISC_PLATFORM_HAVEATOMICSTORE
|
||||
static __inline void
|
||||
isc_atomic_store(int32_t *p, int32_t val) {
|
||||
(void) _InterlockedExchange((long *)p, (long)val);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This routine atomically stores the value 'val' in 'p' (64-bit version).
|
||||
*/
|
||||
#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ
|
||||
static __inline void
|
||||
isc_atomic_storeq(int64_t *p, int64_t val) {
|
||||
(void) _InterlockedExchange64((__int64 *)p, (__int64)val);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This routine atomically replaces the value in 'p' with 'val', if the
|
||||
* original value is equal to 'cmpval'. The original value is returned in any
|
||||
* case.
|
||||
*/
|
||||
#ifdef ISC_PLATFORM_HAVECMPXCHG
|
||||
static __inline int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
|
||||
/* beware: swap arguments */
|
||||
return (int32_t) _InterlockedCompareExchange((long *)p,
|
||||
(long)val,
|
||||
(long)cmpval);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <isc/util.h>
|
||||
|
||||
#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 int_fast32_t volatile atomic_int_fast32_t;
|
||||
typedef uint_fast32_t volatile atomic_uint_fast32_t;
|
||||
typedef int_fast64_t volatile atomic_int_fast64_t;
|
||||
typedef uint_fast64_t volatile atomic_uint_fast64_t;
|
||||
|
||||
#define atomic_init(obj, desired) \
|
||||
(*(obj) = (desired))
|
||||
|
||||
#define atomic_store_explicit32(obj, desired, order) \
|
||||
(order == memory_order_relaxed \
|
||||
? InterlockedExchangeNoFence((atomic_int_fast32_t *)obj, desired) \
|
||||
: (order == memory_order_acquire \
|
||||
? InterlockedExchangeAcquire((atomic_int_fast32_t *)obj, desired) \
|
||||
: InterlockedExchange((atomic_int_fast32_t *)obj, desired)))
|
||||
|
||||
#define atomic_store_explicit64(obj, desired, order) \
|
||||
(order == memory_order_relaxed \
|
||||
? InterlockedExchangeNoFence64((atomic_int_fast64_t *)obj, desired) \
|
||||
: (order == memory_order_acquire \
|
||||
? InterlockedExchangeAcquire64((atomic_int_fast64_t *)obj, desired) \
|
||||
: InterlockedExchange64((atomic_int_fast64_t *)obj, desired)))
|
||||
|
||||
static inline
|
||||
void
|
||||
atomic_store_abort() {
|
||||
INSIST(0);
|
||||
return;
|
||||
}
|
||||
|
||||
#define atomic_store_explicit(obj, desired, order) \
|
||||
(sizeof(*obj) == 8 \
|
||||
? atomic_store_explicit64(obj, desired, order) \
|
||||
: (sizeof(*obj) == 4 \
|
||||
? atomic_store_explicit32(obj, desired, order) \
|
||||
: atomic_store_abort()))
|
||||
|
||||
#define atomic_store(obj, desired) \
|
||||
atomic_store(obj, desider, memory_order_seq_cst)
|
||||
|
||||
#define atomic_load_explicit32(obj, order) \
|
||||
(order == memory_order_relaxed \
|
||||
? (int32_t)InterlockedOrNoFence((atomic_int_fast32_t *)obj, 0) \
|
||||
: (order == memory_order_acquire \
|
||||
? (int32_t)InterlockedOrAcquire((atomic_int_fast32_t *)obj, 0) \
|
||||
: (order == memory_order_release \
|
||||
? (int32_t)InterlockedOrRelease((atomic_int_fast32_t *)obj, 0) \
|
||||
: (int32_t)InterlockedOr((atomic_int_fast32_t *)obj, 0))))
|
||||
|
||||
#define atomic_load_explicit64(obj, order) \
|
||||
(order == memory_order_relaxed \
|
||||
? InterlockedOr64NoFence((atomic_int_fast64_t *)obj, 0) \
|
||||
: (order == memory_order_acquire \
|
||||
? InterlockedOr64Acquire((atomic_int_fast64_t *)obj, 0) \
|
||||
: (order == memory_order_release \
|
||||
? InterlockedOr64Release((atomic_int_fast64_t *)obj, 0) \
|
||||
: InterlockedOr64((atomic_int_fast64_t *)obj, 0))))
|
||||
|
||||
static inline
|
||||
int8_t
|
||||
atomic_load_abort() {
|
||||
INSIST(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define atomic_load_explicit(obj, order) \
|
||||
(sizeof(*obj) == 8 \
|
||||
? atomic_load_explicit64(obj, order) \
|
||||
: (sizeof(*obj == 4) \
|
||||
? atomic_load_explicit32(obj, order) \
|
||||
: atomic_load_abort()))
|
||||
|
||||
#define atomic_load(obj) \
|
||||
atomic_load_explicit(obj, memory_order_seq_cst)
|
||||
|
||||
#define atomic_fetch_add_explicit32(obj, arg, order) \
|
||||
(order == memory_order_relaxed \
|
||||
? InterlockedExchangeAddNoFence((atomic_int_fast32_t *)obj, arg) \
|
||||
: (order == memory_order_acquire \
|
||||
? InterlockedExchangeAddAcquire((atomic_int_fast32_t *)obj, arg) \
|
||||
: (order == memory_order_release \
|
||||
? InterlockedExchangeAddRelease((atomic_int_fast32_t *)obj, arg) \
|
||||
: InterlockedExchange((atomic_int_fast32_t *)obj, arg))))
|
||||
|
||||
#define atomic_fetch_add_explicit64(obj, arg, order) \
|
||||
(order == memory_order_relaxed \
|
||||
? InterlockedExchangeAddNoFence64((atomic_int_fast64_t *)obj, arg) \
|
||||
: (order == memory_order_acquire \
|
||||
? InterlockedExchangeAddAcquire64((atomic_int_fast64_t *)obj, arg) \
|
||||
: (order == memory_order_release \
|
||||
? InterlockedExchangeAddRelease64((atomic_int_fast64_t *)obj, arg) \
|
||||
: InterlockedExchange64((atomic_int_fast64_t *)obj, arg))))
|
||||
|
||||
static inline
|
||||
int8_t
|
||||
atomic_add_abort() {
|
||||
INSIST(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define atomic_fetch_add_explicit(obj, arg, order) \
|
||||
(sizeof(*obj) == 8 \
|
||||
? atomic_fetch_add_explicit64(obj, arg, order) \
|
||||
: (sizeof(*obj) == 4 \
|
||||
? atomic_fetch_add_explicit32(obj, arg, order) \
|
||||
: atomic_add_abort()))
|
||||
|
||||
#define atomic_fetch_add(obj, arg) \
|
||||
atomic_fetch_add_explicit(obj, arg, memory_order_seq_cst)
|
||||
|
||||
#define atomic_fetch_sub_explicit(obj, arg, order) \
|
||||
atomic_fetch_add_explicit(obj, -arg, order)
|
||||
|
||||
#define atomic_fetch_sub(obj, arg) \
|
||||
atomic_fetch_sub_explicit(obj, arg, memory_order_seq_cst)
|
||||
|
||||
static inline bool
|
||||
atomic_compare_exchange_strong_explicit32(atomic_int_fast32_t *obj,
|
||||
int32_t *expected,
|
||||
int32_t desired,
|
||||
memory_order succ,
|
||||
memory_order fail) {
|
||||
bool __r;
|
||||
int32_t __v;
|
||||
REQUIRE(succ == fail);
|
||||
switch (succ) {
|
||||
case memory_order_relaxed:
|
||||
__v = InterlockedCompareExchangeNoFence((atomic_int_fast32_t *)obj, desired, *expected);
|
||||
break;
|
||||
case memory_order_acquire:
|
||||
__v = InterlockedCompareExchangeAcquire((atomic_int_fast32_t *)obj, desired, *expected);
|
||||
break;
|
||||
case memory_order_release:
|
||||
__v = InterlockedCompareExchangeRelease((atomic_int_fast32_t *)obj, desired, *expected);
|
||||
break;
|
||||
default:
|
||||
__v = InterlockedCompareExchange((atomic_int_fast32_t *)obj, desired, *expected);
|
||||
break;
|
||||
}
|
||||
__r = (*(expected) == __v);
|
||||
if (!__r) {
|
||||
*(expected) = __v;
|
||||
}
|
||||
return (__r);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
atomic_compare_exchange_strong_explicit64(atomic_int_fast64_t *obj,
|
||||
int64_t *expected,
|
||||
int64_t desired,
|
||||
memory_order succ,
|
||||
memory_order fail) {
|
||||
bool __r;
|
||||
int64_t __v;
|
||||
REQUIRE(succ == fail);
|
||||
switch (succ) {
|
||||
case memory_order_relaxed:
|
||||
__v = InterlockedCompareExchange64NoFence((atomic_int_fast64_t *)obj, desired, *expected);
|
||||
break;
|
||||
case memory_order_acquire:
|
||||
__v = InterlockedCompareExchange64Acquire((atomic_int_fast64_t *)obj, desired, *expected);
|
||||
break;
|
||||
case memory_order_release:
|
||||
__v = InterlockedCompareExchange64Release((atomic_int_fast64_t *)obj, desired, *expected);
|
||||
break;
|
||||
default:
|
||||
__v = InterlockedCompareExchange64((atomic_int_fast64_t *)obj, desired, *expected);
|
||||
break;
|
||||
}
|
||||
__r = (*(expected) == __v);
|
||||
if (!__r) {
|
||||
*(expected) = __v;
|
||||
}
|
||||
return (__r);
|
||||
}
|
||||
|
||||
static inline
|
||||
bool
|
||||
atomic_compare_exchange_abort() {
|
||||
INSIST(0);
|
||||
return (false);
|
||||
}
|
||||
|
||||
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, \
|
||||
succ, fail) \
|
||||
(sizeof(*obj) == 8 \
|
||||
? atomic_compare_exchange_strong_explicit64(obj, expected, \
|
||||
desired, \
|
||||
succ, fail) \
|
||||
: (sizeof(*obj) == 4 \
|
||||
? atomic_compare_exchange_strong_explicit32(obj, expected, \
|
||||
desired, \
|
||||
succ, fail) \
|
||||
: atomic_compare_exchange_abort()))
|
||||
|
||||
#define atomic_compare_exchange_strong(obj, expected, desired, \
|
||||
succ, fail) \
|
||||
atomic_compare_exchange_strong_explicit(obj, expected, desired, \
|
||||
memory_order_cst_seq, \
|
||||
memory_order_cst_seq)
|
||||
|
||||
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, \
|
||||
succ, fail) \
|
||||
atomic_compare_exchange_strong_explicit(obj, expected, desired, \
|
||||
succ, fail)
|
||||
|
||||
#define atomic_compare_exchange_weak(obj, expected, desired) \
|
||||
atomic_compare_exchange_weak_explicit(obj, expected, desired, \
|
||||
memory_order_cst_seq, \
|
||||
memory_order_cst_seq)
|
||||
@@ -520,7 +520,6 @@ isc_ratelimiter_setpertic
|
||||
isc_ratelimiter_setpushpop
|
||||
isc_ratelimiter_shutdown
|
||||
isc_ratelimiter_stall
|
||||
isc_refcount_init
|
||||
isc_regex_validate
|
||||
isc_region_compare
|
||||
isc_resource_getcurlimit
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
<ClInclude Include="..\include\isc\assertions.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isc\atomic.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isc\backtrace.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -340,6 +343,9 @@
|
||||
<ClInclude Include="include\isc\stat.h">
|
||||
<Filter>Win32 Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\isc\stdatomic.h">
|
||||
<Filter>Win32 Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\isc\stdtime.h">
|
||||
<Filter>Win32 Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -378,13 +384,6 @@
|
||||
<Filter>Win32 Header Files</Filter>
|
||||
</ClInclude>
|
||||
@END PKCS11
|
||||
@IF ATOMIC
|
||||
<ClInclude Include="include\isc\atomic.h">
|
||||
@ELSE ATOMIC
|
||||
<ClInclude Include="..\noatomic\include\isc\atomic.h">
|
||||
@END ATOMIC
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\config.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -608,9 +607,6 @@
|
||||
<ClCompile Include="..\ratelimiter.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\refcount.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\regex.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -293,6 +293,7 @@ copy InstallFiles ..\Build\Release\
|
||||
<ClInclude Include="..\include\isc\aes.h" />
|
||||
<ClInclude Include="..\include\isc\app.h" />
|
||||
<ClInclude Include="..\include\isc\assertions.h" />
|
||||
<ClInclude Include="..\include\isc\atomic.h" />
|
||||
<ClInclude Include="..\include\isc\backtrace.h" />
|
||||
<ClInclude Include="..\include\isc\base32.h" />
|
||||
<ClInclude Include="..\include\isc\base64.h" />
|
||||
@@ -381,11 +382,6 @@ copy InstallFiles ..\Build\Release\
|
||||
<ClInclude Include="..\include\pkcs11\pkcs11f.h" />
|
||||
<ClInclude Include="..\include\pkcs11\pkcs11t.h" />
|
||||
@END PKCS11
|
||||
@IF ATOMIC
|
||||
<ClInclude Include="include\isc\atomic.h" />
|
||||
@ELSE ATOMIC
|
||||
<ClInclude Include="..\noatomic\include\isc\atomic.h" />
|
||||
@END ATOMIC
|
||||
<ClInclude Include="errno2result.h" />
|
||||
<ClInclude Include="include\isc\bindevt.h" />
|
||||
<ClInclude Include="include\isc\bind_registry.h" />
|
||||
@@ -402,6 +398,7 @@ copy InstallFiles ..\Build\Release\
|
||||
<ClInclude Include="include\isc\once.h" />
|
||||
<ClInclude Include="include\isc\platform.h" />
|
||||
<ClInclude Include="include\isc\stat.h" />
|
||||
<ClInclude Include="include\isc\stdatomic.h" />
|
||||
<ClInclude Include="include\isc\stdtime.h" />
|
||||
<ClInclude Include="include\isc\strerror.h" />
|
||||
<ClInclude Include="include\isc\syslog.h" />
|
||||
@@ -409,7 +406,7 @@ copy InstallFiles ..\Build\Release\
|
||||
<ClInclude Include="include\isc\time.h" />
|
||||
<ClInclude Include="include\isc\win32os.h" />
|
||||
<ClInclude Include="../entropy_private.h" />
|
||||
<ClInclude Include="../openssl_shim.h" />
|
||||
<ClInclude Include="../openssl_shim.h" />
|
||||
<ClInclude Include="syslog.h" />
|
||||
<ClInclude Include="unistd.h" />
|
||||
@IF PKCS11
|
||||
@@ -462,7 +459,6 @@ copy InstallFiles ..\Build\Release\
|
||||
<ClCompile Include="..\radix.c" />
|
||||
<ClCompile Include="..\random.c" />
|
||||
<ClCompile Include="..\ratelimiter.c" />
|
||||
<ClCompile Include="..\refcount.c" />
|
||||
<ClCompile Include="..\regex.c" />
|
||||
<ClCompile Include="..\region.c" />
|
||||
<ClCompile Include="..\result.c" />
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = include
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = isc
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
HEADERS = atomic.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
|
||||
|
||||
install:: installdirs
|
||||
for i in ${HEADERS}; do \
|
||||
${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
|
||||
done
|
||||
|
||||
uninstall::
|
||||
for i in ${HEADERS}; do \
|
||||
rm -f ${DESTDIR}${includedir}/isc/$$i ; \
|
||||
done
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#ifdef ISC_PLATFORM_USEGCCASM
|
||||
/*
|
||||
* This routine atomically increments the value stored in 'p' by 'val', and
|
||||
* returns the previous value.
|
||||
*/
|
||||
static __inline__ int32_t
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
int32_t prev = val;
|
||||
|
||||
__asm__ volatile(
|
||||
"lock;"
|
||||
"xadd %0, %1"
|
||||
:"=q"(prev)
|
||||
:"m"(*p), "0"(prev)
|
||||
:"memory", "cc");
|
||||
|
||||
return (prev);
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEXADDQ
|
||||
static __inline__ int64_t
|
||||
isc_atomic_xaddq(int64_t *p, int64_t val) {
|
||||
int64_t prev = val;
|
||||
|
||||
__asm__ volatile(
|
||||
"lock;"
|
||||
"xaddq %0, %1"
|
||||
:"=q"(prev)
|
||||
:"m"(*p), "0"(prev)
|
||||
:"memory", "cc");
|
||||
|
||||
return (prev);
|
||||
}
|
||||
#endif /* ISC_PLATFORM_HAVEXADDQ */
|
||||
|
||||
/*
|
||||
* This routine atomically stores the value 'val' in 'p' (32-bit version).
|
||||
*/
|
||||
static __inline__ void
|
||||
isc_atomic_store(int32_t *p, int32_t val) {
|
||||
__asm__ volatile(
|
||||
/*
|
||||
* xchg should automatically lock memory, but we add it
|
||||
* explicitly just in case (it at least doesn't harm)
|
||||
*/
|
||||
"lock;"
|
||||
|
||||
"xchgl %1, %0"
|
||||
:
|
||||
: "r"(val), "m"(*p)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ
|
||||
/*
|
||||
* This routine atomically stores the value 'val' in 'p' (64-bit version).
|
||||
*/
|
||||
static __inline__ void
|
||||
isc_atomic_storeq(int64_t *p, int64_t val) {
|
||||
__asm__ volatile(
|
||||
/*
|
||||
* xchg should automatically lock memory, but we add it
|
||||
* explicitly just in case (it at least doesn't harm)
|
||||
*/
|
||||
"lock;"
|
||||
|
||||
"xchgq %1, %0"
|
||||
:
|
||||
: "r"(val), "m"(*p)
|
||||
: "memory");
|
||||
}
|
||||
#endif /* ISC_PLATFORM_HAVEATOMICSTOREQ */
|
||||
|
||||
/*
|
||||
* This routine atomically replaces the value in 'p' with 'val', if the
|
||||
* original value is equal to 'cmpval'. The original value is returned in any
|
||||
* case.
|
||||
*/
|
||||
static __inline__ int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
|
||||
__asm__ volatile(
|
||||
"lock;"
|
||||
"cmpxchgl %1, %2"
|
||||
: "=a"(cmpval)
|
||||
: "r"(val), "m"(*p), "a"(cmpval)
|
||||
: "memory");
|
||||
|
||||
return (cmpval);
|
||||
}
|
||||
|
||||
#elif defined(ISC_PLATFORM_USESTDASM)
|
||||
/*
|
||||
* The followings are "generic" assembly code which implements the same
|
||||
* functionality in case the gcc extension cannot be used. It should be
|
||||
* better to avoid inlining below, since we directly refer to specific
|
||||
* positions of the stack frame, which would not actually point to the
|
||||
* intended address in the embedded mnemonic.
|
||||
*/
|
||||
static int32_t
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movl 8(%ebp), %ecx\n"
|
||||
"movl 12(%ebp), %edx\n"
|
||||
"lock;"
|
||||
"xadd %edx, (%ecx)\n"
|
||||
|
||||
/*
|
||||
* set the return value directly in the register so that we
|
||||
* can avoid guessing the correct position in the stack for a
|
||||
* local variable.
|
||||
*/
|
||||
"movl %edx, %eax"
|
||||
);
|
||||
}
|
||||
|
||||
static void
|
||||
isc_atomic_store(int32_t *p, int32_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movl 8(%ebp), %ecx\n"
|
||||
"movl 12(%ebp), %edx\n"
|
||||
"lock;"
|
||||
"xchgl (%ecx), %edx\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
|
||||
(void)(p);
|
||||
(void)(cmpval);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movl 8(%ebp), %ecx\n"
|
||||
"movl 12(%ebp), %eax\n" /* must be %eax for cmpxchgl */
|
||||
"movl 16(%ebp), %edx\n"
|
||||
"lock;"
|
||||
|
||||
/*
|
||||
* If (%ecx) == %eax then (%ecx) := %edx.
|
||||
% %eax is set to old (%ecx), which will be the return value.
|
||||
*/
|
||||
"cmpxchgl %edx, (%ecx)"
|
||||
);
|
||||
}
|
||||
#else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
|
||||
|
||||
#error "unsupported compiler. disable atomic ops by --disable-atomic"
|
||||
|
||||
#endif
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = include
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
SUBDIRS = isc
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
VERSION=@BIND9_VERSION@
|
||||
|
||||
HEADERS = atomic.h
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS =
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
|
||||
|
||||
install:: installdirs
|
||||
for i in ${HEADERS}; do \
|
||||
${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
|
||||
done
|
||||
|
||||
uninstall::
|
||||
for i in ${HEADERS}; do \
|
||||
rm -f ${DESTDIR}${includedir}/isc/$$i ; \
|
||||
done
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ISC_ATOMIC_H
|
||||
#define ISC_ATOMIC_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#ifdef ISC_PLATFORM_USEGCCASM
|
||||
|
||||
/* We share the gcc-version with x86_32 */
|
||||
#error "impossible case. check build configuration"
|
||||
|
||||
#elif defined(ISC_PLATFORM_USESTDASM)
|
||||
/*
|
||||
* The followings are "generic" assembly code which implements the same
|
||||
* functionality in case the gcc extension cannot be used. It should be
|
||||
* better to avoid inlining below, since we directly refer to specific
|
||||
* registers for arguments, which would not actually correspond to the
|
||||
* intended address or value in the embedded mnemonic.
|
||||
*/
|
||||
|
||||
static int32_t
|
||||
isc_atomic_xadd(int32_t *p, int32_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movq %rdi, %rdx\n"
|
||||
"movl %esi, %eax\n"
|
||||
"lock;"
|
||||
"xadd %eax, (%rdx)\n"
|
||||
/*
|
||||
* XXX: assume %eax will be used as the return value.
|
||||
*/
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEXADDQ
|
||||
static int64_t
|
||||
isc_atomic_xaddq(int64_t *p, int64_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movq %rdi, %rdx\n"
|
||||
"movq %rsi, %rax\n"
|
||||
"lock;"
|
||||
"xaddq %rax, (%rdx)\n"
|
||||
/*
|
||||
* XXX: assume %rax will be used as the return value.
|
||||
*/
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
isc_atomic_store(int32_t *p, int32_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movq %rdi, %rax\n"
|
||||
"movl %esi, %edx\n"
|
||||
"lock;"
|
||||
"xchgl (%rax), %edx\n"
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ
|
||||
static void
|
||||
isc_atomic_storeq(int64_t *p, int64_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movq %rdi, %rax\n"
|
||||
"movq %rsi, %rdx\n"
|
||||
"lock;"
|
||||
"xchgq (%rax), %rdx\n"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t
|
||||
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
|
||||
(void)(p);
|
||||
(void)(cmpval);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
/*
|
||||
* p is %rdi, cmpval is %esi, val is %edx.
|
||||
*/
|
||||
"movl %edx, %ecx\n"
|
||||
"movl %esi, %eax\n"
|
||||
"movq %rdi, %rdx\n"
|
||||
|
||||
"lock;"
|
||||
/*
|
||||
* If [%rdi] == %eax then [%rdi] := %ecx (equal to %edx
|
||||
* from above), and %eax is untouched (equal to %esi)
|
||||
* from above.
|
||||
*
|
||||
* Else if [%rdi] != %eax then [%rdi] := [%rdi]
|
||||
* (rewritten in write cycle) and %eax := [%rdi].
|
||||
*/
|
||||
"cmpxchgl %ecx, (%rdx)"
|
||||
);
|
||||
}
|
||||
|
||||
#else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
|
||||
|
||||
#error "unsupported compiler. disable atomic ops by --disable-atomic"
|
||||
|
||||
#endif
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
+3
-12
@@ -36,7 +36,6 @@
|
||||
|
||||
isc_result_t
|
||||
cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret) {
|
||||
isc_result_t result;
|
||||
cfg_aclconfctx_t *actx;
|
||||
|
||||
REQUIRE(mctx != NULL);
|
||||
@@ -46,9 +45,7 @@ cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret) {
|
||||
if (actx == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
result = isc_refcount_init(&actx->references, 1);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
isc_refcount_init(&actx->references, 1);
|
||||
|
||||
actx->mctx = NULL;
|
||||
isc_mem_attach(mctx, &actx->mctx);
|
||||
@@ -60,10 +57,6 @@ cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret) {
|
||||
|
||||
*ret = actx;
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
isc_mem_put(mctx, actx, sizeof(*actx));
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -71,7 +64,7 @@ cfg_aclconfctx_attach(cfg_aclconfctx_t *src, cfg_aclconfctx_t **dest) {
|
||||
REQUIRE(src != NULL);
|
||||
REQUIRE(dest != NULL && *dest == NULL);
|
||||
|
||||
isc_refcount_increment(&src->references, NULL);
|
||||
isc_refcount_increment(&src->references);
|
||||
*dest = src;
|
||||
}
|
||||
|
||||
@@ -79,14 +72,12 @@ void
|
||||
cfg_aclconfctx_detach(cfg_aclconfctx_t **actxp) {
|
||||
cfg_aclconfctx_t *actx;
|
||||
dns_acl_t *dacl, *next;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(actxp != NULL && *actxp != NULL);
|
||||
|
||||
actx = *actxp;
|
||||
|
||||
isc_refcount_decrement(&actx->references, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&actx->references) == 1) {
|
||||
for (dacl = ISC_LIST_HEAD(actx->named_acl_cache);
|
||||
dacl != NULL;
|
||||
dacl = next)
|
||||
|
||||
+7
-19
@@ -451,11 +451,7 @@ cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) {
|
||||
pctx->mctx = NULL;
|
||||
isc_mem_attach(mctx, &pctx->mctx);
|
||||
|
||||
result = isc_refcount_init(&pctx->references, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_putanddetach(&pctx->mctx, pctx, sizeof(*pctx));
|
||||
return (result);
|
||||
}
|
||||
isc_refcount_init(&pctx->references, 1);
|
||||
|
||||
pctx->lctx = lctx;
|
||||
pctx->lexer = NULL;
|
||||
@@ -670,22 +666,20 @@ cfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest) {
|
||||
REQUIRE(src != NULL);
|
||||
REQUIRE(dest != NULL && *dest == NULL);
|
||||
|
||||
isc_refcount_increment(&src->references, NULL);
|
||||
isc_refcount_increment(&src->references);
|
||||
*dest = src;
|
||||
}
|
||||
|
||||
void
|
||||
cfg_parser_destroy(cfg_parser_t **pctxp) {
|
||||
cfg_parser_t *pctx;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(pctxp != NULL && *pctxp != NULL);
|
||||
|
||||
pctx = *pctxp;
|
||||
*pctxp = NULL;
|
||||
|
||||
isc_refcount_decrement(&pctx->references, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&pctx->references) == 1) {
|
||||
isc_lex_destroy(&pctx->lexer);
|
||||
/*
|
||||
* Cleaning up open_files does not
|
||||
@@ -3064,7 +3058,6 @@ cfg_obj_line(const cfg_obj_t *obj) {
|
||||
|
||||
isc_result_t
|
||||
cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
isc_result_t result;
|
||||
cfg_obj_t *obj;
|
||||
|
||||
REQUIRE(pctx != NULL);
|
||||
@@ -3080,11 +3073,8 @@ cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
obj->line = pctx->line;
|
||||
obj->pctx = pctx;
|
||||
|
||||
result = isc_refcount_init(&obj->references, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t));
|
||||
return (result);
|
||||
}
|
||||
isc_refcount_init(&obj->references, 1);
|
||||
|
||||
*ret = obj;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
@@ -3147,15 +3137,13 @@ cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type) {
|
||||
void
|
||||
cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **objp) {
|
||||
cfg_obj_t *obj;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(objp != NULL && *objp != NULL);
|
||||
REQUIRE(pctx != NULL);
|
||||
|
||||
obj = *objp;
|
||||
|
||||
isc_refcount_decrement(&obj->references, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&obj->references) == 1) {
|
||||
obj->type->rep->free(pctx, obj);
|
||||
isc_refcount_destroy(&obj->references);
|
||||
isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t));
|
||||
@@ -3168,7 +3156,7 @@ cfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest) {
|
||||
REQUIRE(src != NULL);
|
||||
REQUIRE(dest != NULL && *dest == NULL);
|
||||
|
||||
isc_refcount_increment(&src->references, NULL);
|
||||
isc_refcount_increment(&src->references);
|
||||
*dest = src;
|
||||
}
|
||||
|
||||
|
||||
+3
-12
@@ -50,9 +50,7 @@ ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview,
|
||||
|
||||
isc_mem_attach(mctx, &sctx->mctx);
|
||||
|
||||
result = isc_refcount_init(&sctx->references, 1);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
isc_refcount_init(&sctx->references, 1);
|
||||
|
||||
CHECKFATAL(isc_quota_init(&sctx->xfroutquota, 10));
|
||||
CHECKFATAL(isc_quota_init(&sctx->tcpquota, 10));
|
||||
@@ -113,11 +111,6 @@ ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview,
|
||||
*sctxp = sctx;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
isc_mem_putanddetach(&sctx->mctx, sctx, sizeof(*sctx));
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -125,7 +118,7 @@ ns_server_attach(ns_server_t *src, ns_server_t **dest) {
|
||||
REQUIRE(SCTX_VALID(src));
|
||||
REQUIRE(dest != NULL && *dest == NULL);
|
||||
|
||||
isc_refcount_increment(&src->references, NULL);
|
||||
isc_refcount_increment(&src->references);
|
||||
|
||||
*dest = src;
|
||||
}
|
||||
@@ -133,14 +126,12 @@ ns_server_attach(ns_server_t *src, ns_server_t **dest) {
|
||||
void
|
||||
ns_server_detach(ns_server_t **sctxp) {
|
||||
ns_server_t *sctx;
|
||||
unsigned int refs;
|
||||
|
||||
REQUIRE(sctxp != NULL);
|
||||
sctx = *sctxp;
|
||||
REQUIRE(SCTX_VALID(sctx));
|
||||
|
||||
isc_refcount_decrement(&sctx->references, &refs);
|
||||
if (refs == 0) {
|
||||
if (isc_refcount_decrement(&sctx->references) == 1) {
|
||||
ns_altsecret_t *altsecret;
|
||||
|
||||
sctx->magic = 0;
|
||||
|
||||
+1
-2
@@ -17,8 +17,7 @@ ISC_INCLUDES = @BIND9_ISC_BUILDINCLUDE@ \
|
||||
-I${top_srcdir}/lib/isc \
|
||||
-I${top_srcdir}/lib/isc/include \
|
||||
-I${top_srcdir}/lib/isc/unix/include \
|
||||
-I${top_srcdir}/lib/isc/pthreads/include \
|
||||
-I${top_srcdir}/lib/isc/@ISC_ARCH_DIR@/include
|
||||
-I${top_srcdir}/lib/isc/pthreads/include
|
||||
|
||||
ISCCC_INCLUDES = @BIND9_ISCCC_BUILDINCLUDE@ \
|
||||
-I${top_srcdir}/lib/isccc/include
|
||||
|
||||
+7
-11
@@ -3336,7 +3336,6 @@
|
||||
./lib/isc/Atffile X 2011,2018
|
||||
./lib/isc/Kyuafile X 2017,2018
|
||||
./lib/isc/aes.c C 2014,2016,2017,2018
|
||||
./lib/isc/alpha/include/isc/atomic.h C 2005,2007,2009,2016,2018
|
||||
./lib/isc/api X 1999,2000,2001,2006,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018
|
||||
./lib/isc/app_api.c C 2009,2013,2014,2015,2016,2018
|
||||
./lib/isc/assertions.c C 1997,1998,1999,2000,2001,2004,2005,2007,2008,2009,2015,2016,2018
|
||||
@@ -3362,10 +3361,12 @@
|
||||
./lib/isc/hmacsha.c C 2005,2006,2007,2009,2011,2012,2013,2014,2015,2016,2017,2018
|
||||
./lib/isc/ht.c C 2016,2017,2018
|
||||
./lib/isc/httpd.c C 2006,2007,2008,2010,2011,2012,2013,2014,2015,2016,2017,2018
|
||||
./lib/isc/ia64/include/isc/atomic.h C 2006,2007,2009,2012,2016,2018
|
||||
./lib/isc/include/Makefile.in MAKE 1998,1999,2000,2001,2004,2007,2012,2014,2016,2018
|
||||
./lib/isc/include/isc/Makefile.in MAKE 1998,1999,2000,2001,2003,2004,2005,2006,2007,2008,2009,2012,2013,2014,2015,2016,2017,2018
|
||||
./lib/isc/include/isc/aes.h C 2014,2016,2018
|
||||
./lib/isc/include/isc/app.h C 1999,2000,2001,2004,2005,2006,2007,2009,2013,2014,2015,2016,2018
|
||||
./lib/isc/include/isc/assertions.h C 1997,1998,1999,2000,2001,2004,2005,2006,2007,2008,2009,2016,2017,2018
|
||||
./lib/isc/include/isc/atomic.h C 2018
|
||||
./lib/isc/include/isc/backtrace.h C 2009,2016,2018
|
||||
./lib/isc/include/isc/base32.h C 2008,2014,2016,2018
|
||||
./lib/isc/include/isc/base64.h C 1999,2000,2001,2004,2005,2006,2007,2016,2018
|
||||
@@ -3437,6 +3438,7 @@
|
||||
./lib/isc/include/isc/sockaddr.h C 1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2009,2012,2015,2016,2018
|
||||
./lib/isc/include/isc/socket.h C 1998,1999,2000,2001,2002,2004,2005,2006,2007,2008,2009,2011,2012,2013,2014,2016,2018
|
||||
./lib/isc/include/isc/stats.h C 2009,2012,2016,2018
|
||||
./lib/isc/include/isc/stdatomic.h C 2018
|
||||
./lib/isc/include/isc/stdio.h C 2000,2001,2004,2005,2006,2007,2013,2016,2018
|
||||
./lib/isc/include/isc/stdlib.h C 2003,2004,2005,2006,2007,2016,2018
|
||||
./lib/isc/include/isc/string.h C 2000,2001,2003,2004,2005,2006,2007,2014,2016,2018
|
||||
@@ -3467,12 +3469,10 @@
|
||||
./lib/isc/log.c C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2009,2011,2012,2013,2014,2016,2017,2018
|
||||
./lib/isc/md5.c C 2000,2001,2004,2005,2007,2009,2014,2015,2016,2017,2018
|
||||
./lib/isc/mem.c C 1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2012,2013,2014,2015,2016,2017,2018
|
||||
./lib/isc/mips/include/isc/atomic.h C 2005,2007,2016,2018
|
||||
./lib/isc/mutexblock.c C 1999,2000,2001,2004,2005,2007,2011,2012,2016,2018
|
||||
./lib/isc/netaddr.c C 1999,2000,2001,2002,2004,2005,2007,2010,2011,2012,2014,2015,2016,2017,2018
|
||||
./lib/isc/netscope.c C 2002,2004,2005,2006,2007,2016,2018
|
||||
./lib/isc/nls/msgcat.c C 1999,2000,2001,2004,2005,2007,2016,2018
|
||||
./lib/isc/noatomic/include/isc/atomic.h C 2005,2007,2016,2018
|
||||
./lib/isc/nonce.c C 2018
|
||||
./lib/isc/openssl_shim.c C 2018
|
||||
./lib/isc/openssl_shim.h C 2018
|
||||
@@ -3481,7 +3481,6 @@
|
||||
./lib/isc/pk11_result.c C 2014,2015,2016,2018
|
||||
./lib/isc/pool.c C 2013,2015,2016,2018
|
||||
./lib/isc/portset.c C 2008,2016,2017,2018
|
||||
./lib/isc/powerpc/include/isc/atomic.h C 2005,2007,2009,2011,2012,2016,2017,2018
|
||||
./lib/isc/pthreads/Makefile.in MAKE 1998,1999,2000,2001,2004,2007,2009,2012,2016,2018
|
||||
./lib/isc/pthreads/condition.c C 1998,1999,2000,2001,2004,2005,2007,2012,2016,2018
|
||||
./lib/isc/pthreads/include/isc/condition.h C 1998,1999,2000,2001,2004,2005,2007,2016,2018
|
||||
@@ -3494,7 +3493,6 @@
|
||||
./lib/isc/radix.c C 2007,2008,2009,2011,2012,2013,2014,2015,2016,2018
|
||||
./lib/isc/random.c C 1999,2000,2001,2002,2003,2004,2005,2007,2009,2013,2014,2016,2017,2018
|
||||
./lib/isc/ratelimiter.c C 1999,2000,2001,2002,2004,2005,2007,2012,2014,2015,2016,2017,2018
|
||||
./lib/isc/refcount.c C 2005,2007,2016,2017,2018
|
||||
./lib/isc/regex.c C 2013,2014.2015,2015,2016,2018
|
||||
./lib/isc/region.c C 2002,2004,2005,2007,2016,2018
|
||||
./lib/isc/result.c C 1998,1999,2000,2001,2003,2004,2005,2007,2008,2012,2014,2015,2016,2017,2018
|
||||
@@ -3504,7 +3502,6 @@
|
||||
./lib/isc/sha2.c C 2005,2006,2007,2009,2011,2012,2014,2016,2017,2018
|
||||
./lib/isc/sockaddr.c C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2010,2011,2012,2014,2015,2016,2017,2018
|
||||
./lib/isc/socket_api.c C 2009,2011,2012,2013,2014,2015,2016,2018
|
||||
./lib/isc/sparc64/include/isc/atomic.h C 2005,2007,2013,2016,2018
|
||||
./lib/isc/stats.c C 2009,2012,2013,2014,2015,2016,2017,2018
|
||||
./lib/isc/string.c C 1999,2000,2001,2003,2004,2005,2006,2007,2011,2012,2014,2015,2016,2018
|
||||
./lib/isc/strtoul.c C 2003,2004,2005,2007,2014,2016,2018
|
||||
@@ -3514,7 +3511,6 @@
|
||||
./lib/isc/tests/Atffile X 2011,2017,2018
|
||||
./lib/isc/tests/Kyuafile X 2017,2018
|
||||
./lib/isc/tests/aes_test.c C 2014,2016,2018
|
||||
./lib/isc/tests/atomic_test.c C 2018
|
||||
./lib/isc/tests/buffer_test.c C 2014,2015,2016,2017,2018
|
||||
./lib/isc/tests/counter_test.c C 2014,2016,2018
|
||||
./lib/isc/tests/errno_test.c C 2016,2018
|
||||
@@ -3593,7 +3589,8 @@
|
||||
./lib/isc/win32/errno2result.h C 2000,2001,2004,2005,2007,2016,2018
|
||||
./lib/isc/win32/file.c C 2000,2001,2002,2004,2007,2009,2011,2012,2013,2014,2015,2016,2017,2018
|
||||
./lib/isc/win32/fsaccess.c C 2000,2001,2002,2004,2007,2013,2016,2017,2018
|
||||
./lib/isc/win32/include/isc/atomic.h C 2013,2015,2016,2018
|
||||
./lib/isc/win32/include/Makefile.in MAKE 1999,2000,2001,2004,2007,2012,2014,2016,2018
|
||||
./lib/isc/win32/include/isc/Makefile.in MAKE 1999,2000,2001,2004,2007,2012,2013,2014,2015,2016,2018
|
||||
./lib/isc/win32/include/isc/bind_registry.h C 2001,2004,2007,2016,2018
|
||||
./lib/isc/win32/include/isc/bindevt.h C 2001,2004,2007,2016,2018
|
||||
./lib/isc/win32/include/isc/condition.h C 1998,1999,2000,2001,2004,2007,2016,2018
|
||||
@@ -3609,6 +3606,7 @@
|
||||
./lib/isc/win32/include/isc/once.h C 1999,2000,2001,2004,2007,2016,2018
|
||||
./lib/isc/win32/include/isc/platform.h.in C 2001,2004,2005,2007,2008,2009,2013,2014,2015,2016,2017,2018
|
||||
./lib/isc/win32/include/isc/stat.h C 2000,2001,2003,2004,2007,2009,2012,2016,2018
|
||||
./lib/isc/win32/include/isc/stdatomic.h C 2018
|
||||
./lib/isc/win32/include/isc/stdtime.h C 1999,2000,2001,2004,2005,2007,2011,2012,2016,2018
|
||||
./lib/isc/win32/include/isc/strerror.h C 2001,2004,2007,2016,2018
|
||||
./lib/isc/win32/include/isc/syslog.h C 1999,2000,2001,2004,2007,2016,2018
|
||||
@@ -3645,8 +3643,6 @@
|
||||
./lib/isc/win32/unistd.h C 2000,2001,2004,2007,2008,2009,2016,2018
|
||||
./lib/isc/win32/version.c C 1998,1999,2000,2001,2004,2007,2016,2018
|
||||
./lib/isc/win32/win32os.c C 2002,2004,2007,2013,2014,2015,2016,2018
|
||||
./lib/isc/x86_32/include/isc/atomic.h C 2005,2007,2008,2015,2016,2017,2018
|
||||
./lib/isc/x86_64/include/isc/atomic.h C 2005,2007,2008,2015,2016,2017,2018
|
||||
./lib/isc/xoshiro128starstar.c C.PORTION 2018
|
||||
./lib/isccc/alist.c C.NOM 2001,2004,2005,2007,2015,2016,2018
|
||||
./lib/isccc/api X 2001,2006,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018
|
||||
|
||||
Reference in New Issue
Block a user