C compiler standard atomics support is now required to compile
This commit is contained in:
@@ -595,9 +595,6 @@ int sigwait(const unsigned int *set, int *sig);
|
||||
/* Define if GOST private keys are encoded in ASN.1. */
|
||||
#undef PREFER_GOSTASN1
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
+10
-216
@@ -22,6 +22,10 @@ AC_CANONICAL_HOST
|
||||
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
# Set compiler compatibility flags
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CPP_WERROR
|
||||
|
||||
#
|
||||
# GNU libtool support
|
||||
#
|
||||
@@ -414,8 +418,6 @@ if test "X$CC" = "X" ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
AC_PROG_CC
|
||||
|
||||
#
|
||||
# gcc's optimiser is broken at -02 for ultrasparc
|
||||
#
|
||||
@@ -3895,65 +3897,12 @@ AC_TRY_COMPILE([
|
||||
[
|
||||
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_MSG_RESULT(yes)],
|
||||
[AC_MSG_ERROR([a compiler with atomics support is required])])
|
||||
|
||||
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(
|
||||
ISC_ATOMIC_LIBS=
|
||||
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)
|
||||
@@ -3961,162 +3910,7 @@ if test "X$have_stdatomic" = "Xyes"; then
|
||||
[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)
|
||||
AC_SUBST([ISC_ATOMIC_LIBS])
|
||||
|
||||
#
|
||||
# Check for __builtin_expect
|
||||
|
||||
@@ -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
|
||||
|
||||
/*
|
||||
@@ -160,13 +154,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
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
@@ -1055,7 +1044,6 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
|
||||
* 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)); \
|
||||
@@ -1078,58 +1066,6 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
|
||||
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);
|
||||
|
||||
@@ -135,31 +135,10 @@ typedef isc_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,
|
||||
@@ -180,7 +159,6 @@ typedef isc_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)
|
||||
@@ -194,21 +172,6 @@ typedef isc_rwlock_t nodelock_t;
|
||||
#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
|
||||
|
||||
/*%
|
||||
* Whether to rate-limit updating the LRU to avoid possible thread contention.
|
||||
@@ -467,11 +430,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 */
|
||||
@@ -4479,11 +4438,6 @@ check_stale_header(dns_rbtnode_t *node, rdatasetheader_t *header,
|
||||
isc_rwlocktype_t *locktype, nodelock_t *lock,
|
||||
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;
|
||||
|
||||
@@ -174,17 +174,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
|
||||
|
||||
struct dns_zone {
|
||||
/* Unlocked */
|
||||
@@ -196,11 +189,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 */
|
||||
|
||||
+2
-3
@@ -21,7 +21,6 @@ PROVIDER = @PKCS11_PROVIDER@
|
||||
|
||||
CINCLUDES = -I${srcdir}/unix/include \
|
||||
-I${srcdir}/@ISC_THREAD_DIR@/include \
|
||||
-I${srcdir}/@ISC_ARCH_DIR@/include \
|
||||
-I./include \
|
||||
-I${srcdir}/include ${DNS_INCLUDES} @ISC_OPENSSL_INC@
|
||||
CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\"
|
||||
@@ -81,13 +80,13 @@ SRCS = @ISC_EXTRA_SRCS@ @ISC_PK11_C@ @ISC_PK11_RESULT_C@ \
|
||||
strtoul.c symtab.c task.c taskpool.c timer.c \
|
||||
tm.c version.c
|
||||
|
||||
LIBS = @ISC_OPENSSL_LIBS@ @LIBS@
|
||||
LIBS = @ISC_OPENSSL_LIBS@ @ISC_ATOMIC_LIBS@ @LIBS@
|
||||
|
||||
# Note: the order of SUBDIRS is important.
|
||||
# Attempt to disable parallel processing.
|
||||
.NOTPARALLEL:
|
||||
.NO_PARALLEL:
|
||||
SUBDIRS = include unix nls @ISC_THREAD_DIR@ @ISC_ARCH_DIR@
|
||||
SUBDIRS = include unix nls @ISC_THREAD_DIR@
|
||||
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,178 +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 <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 isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_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(isc_int32_t *p, isc_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 isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_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 isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
|
||||
isc_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(isc_int32_t *p, isc_int32_t val) {
|
||||
isc_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 isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
|
||||
isc_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,94 +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 <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 isc_int32_t
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((unused))
|
||||
#endif
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val)
|
||||
{
|
||||
isc_int32_t prev, swapped;
|
||||
|
||||
for (prev = *(volatile isc_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(isc_int32_t *p, isc_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 isc_int32_t
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((unused))
|
||||
#endif
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val)
|
||||
{
|
||||
isc_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 */
|
||||
@@ -271,57 +271,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.
|
||||
*/
|
||||
@@ -352,12 +301,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
|
||||
|
||||
@@ -13,18 +13,15 @@
|
||||
#ifndef ISC_REFCOUNT_H
|
||||
#define ISC_REFCOUNT_H 1
|
||||
|
||||
#include <stdatomic.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
|
||||
|
||||
/*! \file isc/refcount.h
|
||||
* \brief Implements a locked reference counter.
|
||||
*
|
||||
@@ -93,22 +90,11 @@ ISC_LANG_BEGINDECLS
|
||||
* Sample implementations
|
||||
*/
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#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
|
||||
isc_int32_t refs;
|
||||
#endif
|
||||
} isc_refcount_t;
|
||||
|
||||
#if defined(ISC_REFCOUNT_HAVESTDATOMIC)
|
||||
|
||||
#define isc_refcount_current(rp) \
|
||||
((unsigned int)(atomic_load_explicit(&(rp)->refs, \
|
||||
memory_order_relaxed)))
|
||||
@@ -146,111 +132,6 @@ typedef struct isc_refcount {
|
||||
*_tmp = prev - 1; \
|
||||
} while (0)
|
||||
|
||||
#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); \
|
||||
isc_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); \
|
||||
isc_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); \
|
||||
isc_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) */
|
||||
#else /* ISC_PLATFORM_USETHREADS */
|
||||
|
||||
typedef struct isc_refcount {
|
||||
|
||||
@@ -15,15 +15,14 @@
|
||||
|
||||
/*! \file isc/rwlock.h */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
#include <isc/condition.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVESTDATOMIC)
|
||||
#include <stdint.h>
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
@@ -34,12 +33,6 @@ typedef enum {
|
||||
} isc_rwlocktype_t;
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#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. */
|
||||
@@ -47,7 +40,6 @@ struct isc_rwlock {
|
||||
isc_mutex_t lock;
|
||||
isc_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
|
||||
@@ -62,15 +54,9 @@ struct isc_rwlock {
|
||||
*/
|
||||
|
||||
/* 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
|
||||
isc_int32_t write_requests;
|
||||
isc_int32_t write_completions;
|
||||
isc_int32_t cnt_and_flag;
|
||||
#endif
|
||||
|
||||
/* Locked by lock. */
|
||||
isc_condition_t readable;
|
||||
@@ -82,30 +68,6 @@ struct isc_rwlock {
|
||||
|
||||
/* 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 */
|
||||
};
|
||||
#else /* ISC_PLATFORM_USETHREADS */
|
||||
struct isc_rwlock {
|
||||
|
||||
@@ -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,88 +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 <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 isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, int val) {
|
||||
isc_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(isc_int32_t *p, isc_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 isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, int cmpval, int val) {
|
||||
isc_int32_t orig;
|
||||
isc_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,18 +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
|
||||
|
||||
/* This file is inherently empty. */
|
||||
|
||||
#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,191 +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 <isc/platform.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
/*!\file
|
||||
* static inline isc_int32_t
|
||||
* isc_atomic_xadd(isc_int32_t *p, isc_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, isc_int32_t val);
|
||||
*
|
||||
* This routine atomically stores the value 'val' in 'p'.
|
||||
*
|
||||
* static inline isc_int32_t
|
||||
* isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_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 isc_int32_t
|
||||
#else
|
||||
static isc_int32_t
|
||||
#endif
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_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 isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
|
||||
isc_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, isc_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 isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
|
||||
isc_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 */
|
||||
@@ -24,9 +24,5 @@ isc_refcount_init(isc_refcount_t *ref, unsigned int n) {
|
||||
REQUIRE(ref != NULL);
|
||||
|
||||
ref->refs = n;
|
||||
#if defined(ISC_PLATFORM_USETHREADS) && !defined(ISC_REFCOUNT_HAVEATOMIC)
|
||||
return (isc_mutex_init(&ref->lock));
|
||||
#else
|
||||
return (ISC_R_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/msgs.h>
|
||||
#include <isc/platform.h>
|
||||
@@ -41,10 +40,8 @@
|
||||
#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. */
|
||||
@@ -52,7 +49,6 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
|
||||
|
||||
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,
|
||||
@@ -69,26 +65,6 @@ print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
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 */
|
||||
|
||||
@@ -107,7 +83,6 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
||||
rwl->magic = 0;
|
||||
|
||||
rwl->spins = 0;
|
||||
#if defined(ISC_RWLOCK_USEATOMIC)
|
||||
rwl->write_requests = 0;
|
||||
rwl->write_completions = 0;
|
||||
rwl->cnt_and_flag = 0;
|
||||
@@ -120,20 +95,6 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
||||
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)
|
||||
@@ -176,16 +137,8 @@ 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);
|
||||
@@ -193,8 +146,6 @@ isc_rwlock_destroy(isc_rwlock_t *rwl) {
|
||||
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.
|
||||
@@ -283,13 +234,9 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
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)
|
||||
@@ -339,12 +286,8 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
isc_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) {
|
||||
@@ -357,16 +300,10 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
}
|
||||
|
||||
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
|
||||
isc_int32_t cntflag2;
|
||||
cntflag2 = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
|
||||
WRITER_ACTIVE);
|
||||
#endif
|
||||
|
||||
if (cntflag2 == 0)
|
||||
break;
|
||||
@@ -431,26 +368,17 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
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.
|
||||
@@ -466,29 +394,18 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
}
|
||||
} 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++;
|
||||
}
|
||||
@@ -505,7 +422,6 @@ 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;
|
||||
|
||||
@@ -531,30 +447,6 @@ isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
|
||||
return (ISC_R_LOCKBUSY);
|
||||
|
||||
}
|
||||
#else
|
||||
{
|
||||
isc_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);
|
||||
}
|
||||
@@ -565,7 +457,6 @@ isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
||||
|
||||
REQUIRE(VALID_RWLOCK(rwl));
|
||||
|
||||
#if defined(ISC_RWLOCK_USESTDATOMIC)
|
||||
{
|
||||
/* Become an active reader. */
|
||||
prev_readers = atomic_fetch_add_explicit(&rwl->cnt_and_flag,
|
||||
@@ -580,18 +471,6 @@ isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
||||
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);
|
||||
@@ -612,13 +491,9 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t 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
|
||||
@@ -637,15 +512,10 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
* 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 ||
|
||||
@@ -683,213 +553,6 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
#else /* ISC_RWLOCK_USEATOMIC */
|
||||
|
||||
static isc_result_t
|
||||
doit(isc_rwlock_t *rwl, isc_rwlocktype_t type, isc_boolean_t nonblock) {
|
||||
isc_boolean_t skip = ISC_FALSE;
|
||||
isc_boolean_t done = ISC_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 = ISC_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 = ISC_TRUE;
|
||||
} else if (nonblock) {
|
||||
result = ISC_R_LOCKBUSY;
|
||||
done = ISC_TRUE;
|
||||
} else {
|
||||
skip = ISC_FALSE;
|
||||
rwl->readers_waiting++;
|
||||
WAIT(&rwl->readable, &rwl->lock);
|
||||
rwl->readers_waiting--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (rwl->writers_waiting != 0)
|
||||
skip = ISC_TRUE;
|
||||
while (!done) {
|
||||
if (!skip && rwl->active == 0) {
|
||||
rwl->type = isc_rwlocktype_write;
|
||||
rwl->active = 1;
|
||||
rwl->granted++;
|
||||
done = ISC_TRUE;
|
||||
} else if (nonblock) {
|
||||
result = ISC_R_LOCKBUSY;
|
||||
done = ISC_TRUE;
|
||||
} else {
|
||||
skip = ISC_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) {
|
||||
isc_int32_t cnt = 0;
|
||||
isc_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, ISC_FALSE);
|
||||
break;
|
||||
}
|
||||
#ifdef ISC_PLATFORM_BUSYWAITNOP
|
||||
ISC_PLATFORM_BUSYWAITNOP;
|
||||
#endif
|
||||
} while (doit(rwl, type, ISC_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, ISC_TRUE));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 */
|
||||
#else /* ISC_PLATFORM_USETHREADS */
|
||||
|
||||
isc_result_t
|
||||
|
||||
@@ -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,120 +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 <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 isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
|
||||
isc_int32_t prev, swapped;
|
||||
|
||||
for (prev = *(volatile isc_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(isc_int32_t *p, isc_int32_t val) {
|
||||
isc_int32_t prev, swapped;
|
||||
|
||||
for (prev = *(volatile isc_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 isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
|
||||
isc_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 */
|
||||
+1
-219
@@ -15,8 +15,8 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
@@ -26,77 +26,10 @@
|
||||
#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
|
||||
isc_uint32_t hi;
|
||||
isc_uint32_t lo;
|
||||
#endif
|
||||
} isc_stat_t;
|
||||
#else
|
||||
#if defined(ISC_STATS_HAVESTDATOMICQ)
|
||||
typedef atomic_int_fast64_t isc_stat_t;
|
||||
#else
|
||||
typedef isc_uint64_t isc_stat_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct isc_stats {
|
||||
/*% Unlocked */
|
||||
@@ -111,9 +44,6 @@ struct isc_stats {
|
||||
* Locked by counterlock or unlocked if efficient rwlock is not
|
||||
* available.
|
||||
*/
|
||||
#if ISC_STATS_LOCKCOUNTERS
|
||||
isc_rwlock_t counterlock;
|
||||
#endif
|
||||
isc_stat_t *counters;
|
||||
|
||||
/*%
|
||||
@@ -157,12 +87,6 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
|
||||
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;
|
||||
@@ -177,12 +101,6 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
|
||||
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);
|
||||
|
||||
@@ -223,9 +141,6 @@ isc_stats_detach(isc_stats_t **statsp) {
|
||||
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;
|
||||
}
|
||||
@@ -242,135 +157,25 @@ isc_stats_ncounters(isc_stats_t *stats) {
|
||||
|
||||
static inline void
|
||||
incrementcounter(isc_stats_t *stats, int counter) {
|
||||
isc_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((isc_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 == (isc_int32_t)0xffffffff) {
|
||||
#if defined(ISC_STATS_HAVESTDATOMIC)
|
||||
atomic_fetch_add_explicit(&stats->counters[counter].hi, 1,
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
isc_atomic_xadd((isc_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((isc_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) {
|
||||
isc_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((isc_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((isc_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((isc_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] =
|
||||
(isc_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] =
|
||||
(isc_uint64_t)isc_atomic_xaddq((isc_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
|
||||
@@ -421,29 +226,6 @@ isc_stats_set(isc_stats_t *stats, isc_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 = (isc_uint32_t)((val >> 32) & 0xffffffff);
|
||||
stats->counters[counter].lo = (isc_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((isc_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
|
||||
}
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -28,7 +28,7 @@ ISCDEPLIBS = ../libisc.@A@
|
||||
LIBS = @LIBS@ @ATFLIBS@
|
||||
|
||||
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 \
|
||||
@@ -38,7 +38,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@ \
|
||||
@@ -51,10 +51,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,352 +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 <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 (isc_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 {
|
||||
isc_uint32_t iteration;
|
||||
} counter_t;
|
||||
|
||||
counter_t counters[TASKS];
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVEXADD)
|
||||
static isc_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, ISC_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 isc_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, ISC_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 %"ISC_PRINT_QUADFORMAT"d, "
|
||||
"expected %"ISC_PRINT_QUADFORMAT"d\n",
|
||||
counter_64, EXPECTED_COUNT_64);
|
||||
|
||||
ATF_CHECK_EQ(counter_64, EXPECTED_COUNT_64);
|
||||
counter_32 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVEATOMICSTORE)
|
||||
static isc_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;
|
||||
isc_uint32_t r;
|
||||
isc_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;
|
||||
isc_uint32_t val;
|
||||
isc_uint32_t r;
|
||||
int i;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL, ISC_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",
|
||||
(isc_uint32_t) store_32, val);
|
||||
|
||||
ATF_CHECK_EQ((isc_uint32_t) store_32, val);
|
||||
store_32 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVEATOMICSTOREQ)
|
||||
static isc_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;
|
||||
isc_uint8_t r;
|
||||
isc_uint64_t val;
|
||||
|
||||
r = random() % 256;
|
||||
val = (((isc_uint64_t) r << 24) |
|
||||
((isc_uint64_t) r << 16) |
|
||||
((isc_uint64_t) r << 8) |
|
||||
(isc_uint64_t) r);
|
||||
val |= ((isc_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;
|
||||
isc_uint64_t val;
|
||||
isc_uint32_t r;
|
||||
int i;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL, ISC_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 = (((isc_uint64_t) r << 24) |
|
||||
((isc_uint64_t) r << 16) |
|
||||
((isc_uint64_t) r << 8) |
|
||||
(isc_uint64_t) r);
|
||||
val |= ((isc_uint64_t) val << 32);
|
||||
|
||||
printf("64-bit store 0x%"ISC_PRINT_QUADFORMAT"x, "
|
||||
"expected 0x%"ISC_PRINT_QUADFORMAT"x\n",
|
||||
(isc_uint64_t) store_64, val);
|
||||
|
||||
ATF_CHECK_EQ((isc_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,74 +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 <config.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 isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
|
||||
return (isc_int32_t) _InterlockedExchangeAdd((long *)p, (long)val);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEXADDQ
|
||||
static __inline isc_int64_t
|
||||
isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) {
|
||||
return (isc_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(isc_int32_t *p, isc_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(isc_int64_t *p, isc_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 isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
|
||||
/* beware: swap arguments */
|
||||
return (isc_int32_t) _InterlockedCompareExchange((long *)p,
|
||||
(long)val,
|
||||
(long)cmpval);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ISC_ATOMIC_H */
|
||||
@@ -97,30 +97,6 @@
|
||||
*/
|
||||
@ISC_PLATFORM_WANTAES@
|
||||
|
||||
/*
|
||||
* 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 "atomic swap" operation is available on this architecture,
|
||||
* ISC_PLATFORM_HAVEATOMICSTORE" will be defined.
|
||||
*/
|
||||
@ISC_PLATFORM_HAVEATOMICSTORE@
|
||||
|
||||
/*
|
||||
* If the "compare-and-exchange" operation is available on this architecture,
|
||||
* ISC_PLATFORM_HAVECMPXCHG will be defined.
|
||||
*/
|
||||
@ISC_PLATFORM_HAVECMPXCHG@
|
||||
|
||||
/*
|
||||
* Define with the busy wait nop asm or function call.
|
||||
*/
|
||||
|
||||
@@ -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,190 +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 <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__ isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
|
||||
isc_int32_t prev = val;
|
||||
|
||||
__asm__ volatile(
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"xadd %0, %1"
|
||||
:"=q"(prev)
|
||||
:"m"(*p), "0"(prev)
|
||||
:"memory", "cc");
|
||||
|
||||
return (prev);
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEXADDQ
|
||||
static __inline__ isc_int64_t
|
||||
isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) {
|
||||
isc_int64_t prev = val;
|
||||
|
||||
__asm__ volatile(
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"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(isc_int32_t *p, isc_int32_t val) {
|
||||
__asm__ volatile(
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
/*
|
||||
* xchg should automatically lock memory, but we add it
|
||||
* explicitly just in case (it at least doesn't harm)
|
||||
*/
|
||||
"lock;"
|
||||
#endif
|
||||
|
||||
"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(isc_int64_t *p, isc_int64_t val) {
|
||||
__asm__ volatile(
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
/*
|
||||
* xchg should automatically lock memory, but we add it
|
||||
* explicitly just in case (it at least doesn't harm)
|
||||
*/
|
||||
"lock;"
|
||||
#endif
|
||||
|
||||
"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__ isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
|
||||
__asm__ volatile(
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"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 isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movl 8(%ebp), %ecx\n"
|
||||
"movl 12(%ebp), %edx\n"
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"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(isc_int32_t *p, isc_int32_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movl 8(%ebp), %ecx\n"
|
||||
"movl 12(%ebp), %edx\n"
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"xchgl (%ecx), %edx\n"
|
||||
);
|
||||
}
|
||||
|
||||
static isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_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"
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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,137 +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 <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 isc_int32_t
|
||||
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movq %rdi, %rdx\n"
|
||||
"movl %esi, %eax\n"
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"xadd %eax, (%rdx)\n"
|
||||
/*
|
||||
* XXX: assume %eax will be used as the return value.
|
||||
*/
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEXADDQ
|
||||
static isc_int64_t
|
||||
isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movq %rdi, %rdx\n"
|
||||
"movq %rsi, %rax\n"
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"xaddq %rax, (%rdx)\n"
|
||||
/*
|
||||
* XXX: assume %rax will be used as the return value.
|
||||
*/
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movq %rdi, %rax\n"
|
||||
"movl %esi, %edx\n"
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"xchgl (%rax), %edx\n"
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ
|
||||
static void
|
||||
isc_atomic_storeq(isc_int64_t *p, isc_int64_t val) {
|
||||
(void)(p);
|
||||
(void)(val);
|
||||
|
||||
__asm (
|
||||
"movq %rdi, %rax\n"
|
||||
"movq %rsi, %rdx\n"
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
"xchgq (%rax), %rdx\n"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
static isc_int32_t
|
||||
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_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"
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
"lock;"
|
||||
#endif
|
||||
/*
|
||||
* 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 */
|
||||
+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/@ISC_THREAD_DIR@/include \
|
||||
-I${top_srcdir}/lib/isc/@ISC_ARCH_DIR@/include
|
||||
-I${top_srcdir}/lib/isc/@ISC_THREAD_DIR@/include
|
||||
|
||||
ISCCC_INCLUDES = @BIND9_ISCCC_BUILDINCLUDE@ \
|
||||
-I${top_srcdir}/lib/isccc/include
|
||||
|
||||
Reference in New Issue
Block a user