Compare commits

...
Author SHA1 Message Date
Witold Kręcicki f11cc50da2 Revert "Increase nodelock count for both cache and regular db."
This reverts commit 31d71bc30c.
2020-02-14 15:34:58 +01:00
Witold Kręcicki 9455067864 Merge branch 'wpk/perfwork-6-bucketed-stats' into wpk/perftest 2020-02-14 15:03:12 +01:00
Witold Kręcicki a5b705c380 Merge branch 'wpk/perfwork-5-isc-result-rwlock' into wpk/perftest 2020-02-14 14:58:40 +01:00
Witold Kręcicki e5d9620b08 Merge branch 'wpk/perfwork-4-compressctx-arena' into wpk/perftest 2020-02-14 14:58:32 +01:00
Witold Kręcicki 46bea75dcc Merge branch 'wpk/perfwork-3-small-nits' into wpk/perftest 2020-02-14 14:58:00 +01:00
Witold Kręcicki a4e4e9af05 Merge branch 'wpk/perfork-2-libuv-tuning' into wpk/perftest 2020-02-14 14:57:52 +01:00
Witold Kręcicki be952bb48a fixup! Make nm->recvbuf larger and heap allocated, to allow uv_recvmmsg usage. 2020-02-14 14:31:35 +01:00
Witold Kręcicki 473523d7ea Use thread-friendly mctxpool and taskpool in ns_client.
Make ns_client mctxpool more thread-friendly by sharding it by
netmgr threadid, use task pool also sharded by thread id to avoid
lock contention.
2020-02-14 14:16:06 +01:00
Witold Kręcicki f68670503a Bucketed statistics.
Even though statistics are lockless they still use atomics which
might cause contention. Split stats counters into buckets, sharded
by an artificial thread identifier, to increase throughput.
2020-02-14 12:33:33 +01:00
Witold Kręcicki cf75315fbf Use libuv-provided uv_{export,import} if available 2020-02-14 12:32:27 +01:00
Witold Kręcicki bc08966735 Make nm->recvbuf larger and heap allocated, to allow uv_recvmmsg usage. 2020-02-14 12:32:27 +01:00
Witold Kręcicki a247dd540a Don't define NS_CLIENT_TRACE by default 2020-02-14 12:29:16 +01:00
Witold Kręcicki 8c76ef90b1 Increase inactivehandles and inactivereqs size for better reuse. 2020-02-14 12:29:16 +01:00
Witold Kręcicki 31d71bc30c Increase nodelock count for both cache and regular db. 2020-02-14 12:29:16 +01:00
Witold Kręcicki 81a565b48f Use RESOLVER_NTASKS_PERCPU - 32 for regular tuning, 8 for small 2020-02-14 12:29:16 +01:00
Witold Kręcicki 990c65121a use SO_INCOMING_CPU for UDP sockets 2020-02-14 12:29:16 +01:00
Witold Kręcicki cc5b3dbe96 Remove some stale fields from ns_client_t; make sendbuf allocated on heap 2020-02-14 12:29:16 +01:00
Witold Kręcicki 75c6cc8efc Don't update LRU if the node was recently used.
Updating LRU requires write-locking the node, which causes contention.
Update LRU only if time difference is large enough.
2020-02-14 12:29:16 +01:00
Witold Kręcicki 6111554eda We don't need to fill udp local address every time since we are bound to it. 2020-02-14 12:29:16 +01:00
Witold Kręcicki f7459d16bf Don't check if the client is on recursing list (requires locking) if it's not RECURSING 2020-02-14 12:29:16 +01:00
Witold Kręcicki fc4d685865 Use the original threadid when sending a UDP packet to decrease probability of context switching 2020-02-14 12:29:16 +01:00
Witold Kręcicki 8b461258a5 Add an arena to compressctx 2020-02-14 12:22:16 +01:00
Witold Kręcicki cccb053554 Use isc_rwlock for isc_result tables 2020-02-14 12:21:33 +01:00
Witold Kręcicki 2acc4a907f Make isc_task_pause/isc_task_unpause thread safe.
isc_task_pause/unpause were inherently thread-unsafe - a task
could be paused only once by one thread, if the task was running
while we paused it it led to races. Fix it by making sure that
the task will pause if requested to, and by using a 'pause reference
counter' to count task pause requests - a task will be unpaused
iff all threads unpause it.

Don't remove from queue when pausing task - we lock the queue lock
(expensive), while it's unlikely that the task will be running -
and we'll remove it anyway in dispatcher
2020-02-14 12:08:19 +01:00
23 changed files with 303 additions and 185 deletions
+10 -10
View File
@@ -145,13 +145,13 @@
#endif /* ifndef SIZE_AS_PERCENT */
#ifdef TUNE_LARGE
#define RESOLVER_NTASKS 523
#define UDPBUFFERS 32768
#define EXCLBUFFERS 32768
#else /* ifdef TUNE_LARGE */
#define RESOLVER_NTASKS 31
#define UDPBUFFERS 1000
#define EXCLBUFFERS 4096
#define RESOLVER_NTASKS_PERCPU 32
#define UDPBUFFERS 32768
#define EXCLBUFFERS 32768
#else
#define RESOLVER_NTASKS_PERCPU 8
#define UDPBUFFERS 1000
#define EXCLBUFFERS 4096
#endif /* TUNE_LARGE */
#define MAX_TCP_TIMEOUT 65535
@@ -4539,8 +4539,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH);
CHECK(dns_view_createresolver(
view, named_g_taskmgr, RESOLVER_NTASKS, ndisp,
named_g_socketmgr, named_g_timermgr, resopts,
view, named_g_taskmgr, RESOLVER_NTASKS_PERCPU * named_g_cpus,
ndisp, named_g_socketmgr, named_g_timermgr, resopts,
named_g_dispatchmgr, dispatch4, dispatch6));
if (dscp4 == -1) {
@@ -9637,7 +9637,7 @@ run_server(isc_task_t *task, isc_event_t *event) {
named_g_mctx, server->sctx, named_g_taskmgr,
named_g_timermgr, named_g_socketmgr, named_g_nm,
named_g_dispatchmgr, server->task, named_g_udpdisp,
geoip, &server->interfacemgr),
geoip, named_g_cpus, &server->interfacemgr),
"creating interface manager");
CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
+3
View File
@@ -471,6 +471,9 @@
/* Define to 1 if you have the `uv_handle_set_data' function. */
#undef HAVE_UV_HANDLE_SET_DATA
/* Define to 1 if you have the `uv_import' function. */
#undef HAVE_UV_IMPORT
/* Use zlib library */
#undef HAVE_ZLIB
+9
View File
@@ -355,6 +355,15 @@ typedef __int64 off_t;
/* Define to 1 if you have the `HMAC_CTX_reset' function. */
@HAVE_HMAC_CTX_RESET@
/* Define to 1 if you have the `uv_handle_get_data' function. */
@HAVE_UV_HANDLE_GET_DATA@
/* Define to 1 if you have the `uv_handle_set_data' function. */
@HAVE_UV_HANDLE_SET_DATA@
/* Define to 1 if you have the `uv_import' function. */
@HAVE_UV_IMPORT@
/*
* Define to nothing if C supports flexible array members, and to 1 if it does
* not. That way, with a declaration like `struct s { int n; double
Vendored
+1 -1
View File
@@ -15960,7 +15960,7 @@ LIBS="$LIBS $LIBUV_LIBS"
# Those functions are only provided in newer versions of libuv, we'll be emulating them
# for now
for ac_func in uv_handle_get_data uv_handle_set_data
for ac_func in uv_handle_get_data uv_handle_set_data uv_import
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+1 -1
View File
@@ -667,7 +667,7 @@ LIBS="$LIBS $LIBUV_LIBS"
# Those functions are only provided in newer versions of libuv, we'll be emulating them
# for now
AC_CHECK_FUNCS([uv_handle_get_data uv_handle_set_data])
AC_CHECK_FUNCS([uv_handle_get_data uv_handle_set_data uv_import])
#
# flockfile is usually provided by pthreads
+15 -3
View File
@@ -129,6 +129,7 @@ dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) {
cctx->mctx = mctx;
cctx->count = 0;
cctx->allowed = DNS_COMPRESS_ENABLED;
cctx->arena_off = 0;
memset(&cctx->table[0], 0, sizeof(cctx->table));
@@ -382,6 +383,7 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
uint16_t toffset;
unsigned char *tmp;
isc_region_t r;
bool allocated = false;
REQUIRE(VALID_CCTX(cctx));
REQUIRE(dns_name_isabsolute(name));
@@ -407,7 +409,13 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
start = 0;
dns_name_toregion(name, &r);
length = r.length;
tmp = isc_mem_get(cctx->mctx, length);
if (cctx->arena_off + length < DNS_COMPRESS_ARENA_SIZE) {
tmp = &cctx->arena[cctx->arena_off];
cctx->arena_off += length;
} else {
allocated = true;
tmp = isc_mem_get(cctx->mctx, length);
}
/*
* Copy name data to 'tmp' and make 'r' use 'tmp'.
*/
@@ -448,7 +456,7 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
* 'node->r.base' becomes 'tmp' when start == 0.
* Record this by setting 0x8000 so it can be freed later.
*/
if (start == 0) {
if (start == 0 && allocated) {
toffset |= 0x8000;
}
node->offset = toffset;
@@ -466,7 +474,11 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
}
if (start == 0) {
isc_mem_put(cctx->mctx, tmp, length);
if (!allocated) {
cctx->arena_off -= length;
} else {
isc_mem_put(cctx->mctx, tmp, length);
}
}
}
+5 -1
View File
@@ -51,7 +51,8 @@ ISC_LANG_BEGINDECLS
#define DNS_COMPRESS_TABLEBITS 6
#define DNS_COMPRESS_TABLESIZE (1U << DNS_COMPRESS_TABLEBITS)
#define DNS_COMPRESS_TABLEMASK (DNS_COMPRESS_TABLESIZE - 1)
#define DNS_COMPRESS_INITIALNODES 16
#define DNS_COMPRESS_INITIALNODES 24
#define DNS_COMPRESS_ARENA_SIZE 640
typedef struct dns_compressnode dns_compressnode_t;
@@ -69,6 +70,9 @@ struct dns_compress {
int edns; /*%< Edns version or -1. */
/*% Global compression table. */
dns_compressnode_t *table[DNS_COMPRESS_TABLESIZE];
/*% Preallocated arena for names. */
unsigned char arena[DNS_COMPRESS_ARENA_SIZE];
off_t arena_off;
/*% Preallocated nodes for the table. */
dns_compressnode_t initialnodes[DNS_COMPRESS_INITIALNODES];
uint16_t count; /*%< Number of nodes. */
+8 -5
View File
@@ -174,8 +174,11 @@ typedef isc_rwlock_t nodelock_t;
* to be 0 by default either with or without threads.
*/
#ifndef DNS_RBTDB_LIMITLRUUPDATE
#define DNS_RBTDB_LIMITLRUUPDATE 0
#endif /* ifndef DNS_RBTDB_LIMITLRUUPDATE */
#define DNS_RBTDB_LIMITLRUUPDATE 1
#endif
#define DNS_RBTDB_LRUUPDATE_GLUE 300
#define DNS_RBTDB_LRUUPDATE_REGULAR 600
/*
* Allow clients with a virtual time of up to 5 minutes in the past to see
@@ -10339,12 +10342,12 @@ need_headerupdate(rdatasetheader_t *header, isc_stdtime_t now) {
* Glue records are updated if at least 60 seconds have passed
* since the previous update time.
*/
return (header->last_used + 60 <= now);
return (header->last_used + DNS_RBTDB_LRUUPDATE_GLUE <= now);
}
/* Other records are updated if 5 minutes have passed. */
return (header->last_used + 300 <= now);
#else /* if DNS_RBTDB_LIMITLRUUPDATE */
return (header->last_used + DNS_RBTDB_LRUUPDATE_REGULAR <= now);
#else
UNUSED(now);
return (true);
+15 -2
View File
@@ -33,7 +33,20 @@
#include "uv-compat.h"
#define ISC_NETMGR_TID_UNKNOWN -1
#define ISC_NETMGR_TID_UNKNOWN -1
#if !defined(WIN32)
/*
* New versions of libuv support recvmmsg on unices.
* Since recvbuf is only allocated per worker allocating a bigger one is not
* that wasteful.
* 20 here is UV__MMSG_MAXWIDTH taken from the current libuv source, nothing
* will break if the original value changes.
*/
#define ISC_NETMGR_RECVBUF_SIZE (20 * 65536)
#else
#define ISC_NETMGR_RECVBUF_SIZE (65536)
#endif
/*
* Single network event loop worker.
@@ -56,7 +69,7 @@ typedef struct isc__networker {
* worker is paused */
isc_refcount_t references;
atomic_int_fast64_t pktcount;
char recvbuf[65536];
char *recvbuf;
bool recvbuf_inuse;
} isc__networker_t;
+13 -5
View File
@@ -196,6 +196,7 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
worker->ievents = isc_queue_new(mgr->mctx, 128);
worker->ievents_prio = isc_queue_new(mgr->mctx, 128);
worker->recvbuf = isc_mem_get(mctx, ISC_NETMGR_RECVBUF_SIZE);
/*
* We need to do this here and not in nm_thread to avoid a
@@ -268,6 +269,8 @@ nm_destroy(isc_nm_t **mgr0) {
isc_queue_destroy(worker->ievents);
isc_queue_destroy(worker->ievents_prio);
isc_mem_put(mgr->mctx, worker->recvbuf,
ISC_NETMGR_RECVBUF_SIZE);
isc_thread_join(worker->thread, NULL);
}
@@ -900,8 +903,8 @@ isc__nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
.iface = iface,
.fd = -1,
.ah_size = 32,
.inactivehandles = isc_astack_new(mgr->mctx, 60),
.inactivereqs = isc_astack_new(mgr->mctx, 60)
.inactivehandles = isc_astack_new(mgr->mctx, 600),
.inactivereqs = isc_astack_new(mgr->mctx, 600)
};
isc_nm_attach(mgr, &sock->mgr);
@@ -960,14 +963,14 @@ isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(isc__nm_in_netthread());
REQUIRE(size <= 65536);
REQUIRE(size <= ISC_NETMGR_RECVBUF_SIZE);
worker = &sock->mgr->workers[sock->tid];
INSIST(!worker->recvbuf_inuse);
buf->base = worker->recvbuf;
worker->recvbuf_inuse = true;
buf->len = size;
buf->len = ISC_NETMGR_RECVBUF_SIZE;
}
void
@@ -982,8 +985,13 @@ isc__nm_free_uvbuf(isc_nmsocket_t *sock, const uv_buf_t *buf) {
worker = &sock->mgr->workers[sock->tid];
REQUIRE(worker->recvbuf_inuse);
if (buf->base > worker->recvbuf &&
buf->base <= worker->recvbuf + ISC_NETMGR_RECVBUF_SIZE)
{
/* Can happen in case of recvmmsg */
return;
}
REQUIRE(buf->base == worker->recvbuf);
worker->recvbuf_inuse = false;
}
+13 -9
View File
@@ -97,6 +97,10 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
#endif /* ifdef WIN32 */
RUNTIME_CHECK(res == 0);
#ifdef SO_INCOMING_CPU
setsockopt(csock->fd, SOL_SOCKET, SO_INCOMING_CPU, &(int){ 1 },
sizeof(int));
#endif
ievent = isc__nm_get_ievent(mgr, netievent_udplisten);
ievent->sock = csock;
isc__nm_enqueue_ievent(&mgr->workers[i],
@@ -284,8 +288,6 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
isc_result_t result;
isc_nmhandle_t *nmhandle = NULL;
isc_sockaddr_t sockaddr;
isc_sockaddr_t localaddr;
struct sockaddr_storage laddr;
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)handle);
isc_region_t region;
uint32_t maxudp;
@@ -319,13 +321,7 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
result = isc_sockaddr_fromsockaddr(&sockaddr, addr);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
uv_udp_getsockname(handle, (struct sockaddr *)&laddr,
&(int){ sizeof(struct sockaddr_storage) });
result = isc_sockaddr_fromsockaddr(&localaddr,
(struct sockaddr *)&laddr);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
nmhandle = isc__nmhandle_get(sock, &sockaddr, &localaddr);
nmhandle = isc__nmhandle_get(sock, &sockaddr, NULL);
region.base = (unsigned char *)buf->base;
region.length = nrecv;
@@ -383,8 +379,16 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
return (ISC_R_CANCELED);
}
/*
* If we're in netthread - send it directly
* If the original packet was received over a regular socket
* - send it over the same thread (assuming cpu affinity)
* Otherwise - use a random thread.
*/
if (isc__nm_in_netthread()) {
ntid = isc_nm_tid();
} else if (sock->type == isc_nm_udpsocket) {
ntid = sock->tid;
} else {
ntid = (int)isc_random_uniform(sock->nchildren);
}
+3
View File
@@ -15,6 +15,7 @@
#include <isc/util.h>
#ifndef HAVE_UV_IMPORT
/*
* XXXWPK: This code goes into libuv internals and it's platform dependent.
* It's ugly, we shouldn't do it, but the alternative with passing sockets
@@ -185,3 +186,5 @@ isc_uv_import(uv_stream_t *stream, isc_uv_stream_info_t *info) {
return (uv_tcp_open(tcp, info->fd));
}
#endif /* ifdef WIN32 */
#endif /* ifndef HAVE_UV_IMPORT */
+10
View File
@@ -33,6 +33,14 @@ uv_handle_set_data(uv_handle_t *handle, void *data) {
}
#endif /* ifndef HAVE_UV_HANDLE_SET_DATA */
#ifdef HAVE_UV_IMPORT
#define isc_uv_stream_info_t uv_stream_info_t
#define isc_uv_export uv_export
#define isc_uv_import uv_import
#else
/*
* These functions are not available in libuv, but they're very internal
* to libuv. We should try to get them merged upstream.
@@ -69,3 +77,5 @@ isc_uv_import(uv_stream_t *stream, isc_uv_stream_info_t *info);
* Imports uv_stream_info_t value into uv_stream_t to initialize a
* shared stream.
*/
#endif
+7 -7
View File
@@ -15,9 +15,9 @@
#include <stdlib.h>
#include <isc/lib.h>
#include <isc/mutex.h>
#include <isc/once.h>
#include <isc/resultclass.h>
#include <isc/rwlock.h>
#include <isc/util.h>
typedef struct resulttable {
@@ -182,7 +182,7 @@ static const char *identifier[ISC_R_NRESULTS] = {
static isc_once_t once = ISC_ONCE_INIT;
static resulttable_list_t description_tables;
static resulttable_list_t identifier_tables;
static isc_mutex_t lock;
static isc_rwlock_t lock;
static isc_result_t
register_table(resulttable_list_t *tables, unsigned int base,
@@ -207,11 +207,11 @@ register_table(resulttable_list_t *tables, unsigned int base,
table->set = set;
ISC_LINK_INIT(table, link);
LOCK(&lock);
RWLOCK(&lock, isc_rwlocktype_write);
ISC_LIST_APPEND(*tables, table, link);
UNLOCK(&lock);
RWUNLOCK(&lock, isc_rwlocktype_write);
return (ISC_R_SUCCESS);
}
@@ -220,7 +220,7 @@ static void
initialize_action(void) {
isc_result_t result;
isc_mutex_init(&lock);
isc_rwlock_init(&lock, 0, 0);
ISC_LIST_INIT(description_tables);
ISC_LIST_INIT(identifier_tables);
@@ -254,7 +254,7 @@ isc_result_tomany_helper(resulttable_list_t *tables, isc_result_t result) {
initialize();
LOCK(&lock);
RWLOCK(&lock, isc_rwlocktype_read);
text = NULL;
for (table = ISC_LIST_HEAD(*tables); table != NULL;
@@ -270,7 +270,7 @@ isc_result_tomany_helper(resulttable_list_t *tables, isc_result_t result) {
text = "(result code text not available)";
}
UNLOCK(&lock);
RWUNLOCK(&lock, isc_rwlocktype_read);
return (text);
}
+46 -11
View File
@@ -22,11 +22,14 @@
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/stats.h>
#include <isc/thread.h>
#include <isc/util.h>
#define ISC_STATS_MAGIC ISC_MAGIC('S', 't', 'a', 't')
#define ISC_STATS_VALID(x) ISC_MAGIC_VALID(x, ISC_STATS_MAGIC)
#define STATS_BUCKETS 64
#if defined(_WIN32) && !defined(_WIN64)
typedef atomic_int_fast32_t isc__atomic_statcounter_t;
#else /* if defined(_WIN32) && !defined(_WIN64) */
@@ -41,6 +44,19 @@ struct isc_stats {
isc__atomic_statcounter_t *counters;
};
ISC_THREAD_LOCAL int isc__stats_thread_v = -1;
static atomic_uint_fast32_t isc__stats_thread_n = 0;
static int
threadhash() {
if (isc__stats_thread_v < 0) {
isc__stats_thread_v =
atomic_fetch_add_relaxed(&isc__stats_thread_n, 1) %
STATS_BUCKETS;
}
return (isc__stats_thread_v);
}
static isc_result_t
create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
isc_stats_t *stats;
@@ -49,7 +65,8 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
REQUIRE(statsp != NULL && *statsp == NULL);
stats = isc_mem_get(mctx, sizeof(*stats));
counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters;
counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters *
STATS_BUCKETS;
stats->counters = isc_mem_get(mctx, counters_alloc_size);
isc_refcount_init(&stats->references, 1);
memset(stats->counters, 0, counters_alloc_size);
@@ -84,7 +101,7 @@ isc_stats_detach(isc_stats_t **statsp) {
isc_refcount_destroy(&stats->references);
isc_mem_put(stats->mctx, stats->counters,
sizeof(isc__atomic_statcounter_t) *
stats->ncounters);
stats->ncounters * STATS_BUCKETS);
isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
}
}
@@ -107,8 +124,8 @@ void
isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter) {
REQUIRE(ISC_STATS_VALID(stats));
REQUIRE(counter < stats->ncounters);
atomic_fetch_add_explicit(&stats->counters[counter], 1,
int idx = threadhash() * stats->ncounters + counter;
atomic_fetch_add_explicit(&stats->counters[idx], 1,
memory_order_relaxed);
}
@@ -117,7 +134,8 @@ isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter) {
REQUIRE(ISC_STATS_VALID(stats));
REQUIRE(counter < stats->ncounters);
atomic_fetch_sub_explicit(&stats->counters[counter], 1,
int idx = threadhash() * stats->ncounters + counter;
atomic_fetch_sub_explicit(&stats->counters[idx], 1,
memory_order_relaxed);
}
@@ -129,8 +147,13 @@ isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn, void *arg,
REQUIRE(ISC_STATS_VALID(stats));
for (i = 0; i < stats->ncounters; i++) {
uint32_t counter = atomic_load_explicit(&stats->counters[i],
uint32_t counter = 0;
int b;
for (b = 0; b < STATS_BUCKETS; b++) {
int idx = stats->ncounters * b + i;
counter += atomic_load_explicit(&stats->counters[idx],
memory_order_relaxed);
}
if ((options & ISC_STATSDUMP_VERBOSE) == 0 && counter == 0) {
continue;
}
@@ -140,11 +163,17 @@ isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn, void *arg,
void
isc_stats_set(isc_stats_t *stats, uint64_t val, isc_statscounter_t counter) {
int i;
REQUIRE(ISC_STATS_VALID(stats));
REQUIRE(counter < stats->ncounters);
atomic_store_explicit(&stats->counters[counter], val,
memory_order_relaxed);
for (i = 1; i < STATS_BUCKETS; i++) {
int idx = stats->ncounters * i + counter;
atomic_store_explicit(&stats->counters[idx], val,
memory_order_relaxed);
}
}
void
@@ -153,9 +182,9 @@ isc_stats_update_if_greater(isc_stats_t *stats, isc_statscounter_t counter,
REQUIRE(ISC_STATS_VALID(stats));
REQUIRE(counter < stats->ncounters);
isc_statscounter_t curr_value =
atomic_load_relaxed(&stats->counters[counter]);
isc_statscounter_t curr_value;
do {
curr_value = atomic_load_relaxed(&stats->counters[counter]);
if (curr_value >= value) {
break;
}
@@ -165,9 +194,15 @@ isc_stats_update_if_greater(isc_stats_t *stats, isc_statscounter_t counter,
isc_statscounter_t
isc_stats_get_counter(isc_stats_t *stats, isc_statscounter_t counter) {
uint32_t value = 0;
int i;
REQUIRE(ISC_STATS_VALID(stats));
REQUIRE(counter < stats->ncounters);
return (atomic_load_explicit(&stats->counters[counter],
memory_order_relaxed));
for (i = 0; i < STATS_BUCKETS; i++) {
int idx = i * stats->ncounters + counter;
value += atomic_load_explicit(&stats->counters[idx],
memory_order_relaxed);
}
return (value);
}
+46 -28
View File
@@ -107,6 +107,7 @@ struct isc__task {
isc_mutex_t lock;
/* Locked by task lock. */
task_state_t state;
int pause_cnt;
isc_refcount_t references;
isc_eventlist_t events;
isc_eventlist_t on_shutdown;
@@ -305,6 +306,7 @@ isc_task_create_bound(isc_taskmgr_t *manager0, unsigned int quantum,
isc_mutex_init(&task->lock);
task->state = task_state_idle;
task->pause_cnt = 0;
isc_refcount_init(&task->references, 1);
INIT_LIST(task->events);
@@ -403,7 +405,7 @@ task_shutdown(isc__task_t *task) {
/*
* Moves a task onto the appropriate run queue.
*
* Caller must NOT hold manager lock.
* Caller must NOT hold queue lock.
*/
static inline void
task_ready(isc__task_t *task) {
@@ -411,7 +413,6 @@ task_ready(isc__task_t *task) {
bool has_privilege = isc_task_privilege((isc_task_t *)task);
REQUIRE(VALID_MANAGER(manager));
REQUIRE(task->state == task_state_ready);
XTRACE("task_ready");
LOCK(&manager->queues[task->threadid].lock);
@@ -952,10 +953,13 @@ pop_readyq(isc__taskmgr_t *manager, int c) {
* Push 'task' onto the ready_tasks queue. If 'task' has the privilege
* flag set, then also push it onto the ready_priority_tasks queue.
*
* Caller must hold the task manager lock.
* Caller must hold the task queue lock.
*/
static inline void
push_readyq(isc__taskmgr_t *manager, isc__task_t *task, int c) {
if (ISC_LINK_LINKED(task, ready_link)) {
return;
}
ENQUEUE(manager->queues[c].ready_tasks, task, ready_link);
if (TASK_PRIVILEGED(task)) {
ENQUEUE(manager->queues[c].ready_priority_tasks, task,
@@ -1115,6 +1119,17 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
memory_order_acquire);
LOCK(&task->lock);
/*
* It is possible because that we have a paused task
* in the queue - it might have been paused in the
* meantime and we never hold both queue and task lock
* to avoid deadlocks, just bail then.
*/
if (task->state != task_state_ready) {
UNLOCK(&task->lock);
LOCK(&manager->queues[threadid].lock);
continue;
}
INSIST(task->state == task_state_ready);
task->state = task_state_running;
XTRACE("running");
@@ -1203,6 +1218,15 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
}
}
done = true;
} else if (task->state == task_state_pausing) {
/*
* We got a pause request on this task,
* stop working on it and switch the
* state to paused.
*/
XTRACE("pausing");
task->state = task_state_paused;
done = true;
} else if (dispatch_count >= task->quantum) {
/*
* Our quantum has expired, but
@@ -1215,17 +1239,8 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
* so the minimum quantum is one.
*/
XTRACE("quantum");
if (task->state == task_state_running) {
/*
* We requeue only if it's
* not paused.
*/
task->state = task_state_ready;
requeue = true;
} else if (task->state ==
task_state_pausing) {
task->state = task_state_paused;
}
task->state = task_state_ready;
requeue = true;
done = true;
}
} while (!done);
@@ -1675,31 +1690,27 @@ void
isc_task_pause(isc_task_t *task0) {
REQUIRE(ISCAPI_TASK_VALID(task0));
isc__task_t *task = (isc__task_t *)task0;
isc__taskmgr_t *manager = task->manager;
bool running = false;
LOCK(&task->lock);
task->pause_cnt++;
if (task->pause_cnt > 1) {
/*
* Someone already paused this thread, just increase
* the number of pausing clients.
*/
UNLOCK(&task->lock);
return;
}
INSIST(task->state == task_state_idle ||
task->state == task_state_ready ||
task->state == task_state_running);
if (task->state == task_state_running) {
running = true;
task->state = task_state_pausing;
} else {
task->state = task_state_paused;
}
UNLOCK(&task->lock);
if (running) {
return;
}
LOCK(&manager->queues[task->threadid].lock);
if (ISC_LINK_LINKED(task, ready_link)) {
DEQUEUE(manager->queues[task->threadid].ready_tasks, task,
ready_link);
}
UNLOCK(&manager->queues[task->threadid].lock);
}
void
@@ -1710,6 +1721,13 @@ isc_task_unpause(isc_task_t *task0) {
REQUIRE(ISCAPI_TASK_VALID(task0));
LOCK(&task->lock);
task->pause_cnt--;
INSIST(task->pause_cnt >= 0);
if (task->pause_cnt > 0) {
UNLOCK(&task->lock);
return;
}
INSIST(task->state == task_state_paused ||
task->state == task_state_pausing);
/* If the task was pausing we can't reschedule it */
-2
View File
@@ -687,8 +687,6 @@ isc_timermgr_destroy
isc_timermgr_poke
isc_tm_timegm
isc_tm_strptime
isc_uv_export
isc_uv_import
isc_win32os_versioncheck
openlog
@IF PKCS11
+80 -70
View File
@@ -79,7 +79,6 @@
* task to change the client, then the client will have to be locked.
*/
#define NS_CLIENT_TRACE
#ifdef NS_CLIENT_TRACE
#define CTRACE(m) \
ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, \
@@ -112,6 +111,21 @@
#define NS_CLIENT_DROPPORT 1
#endif /* ifndef NS_CLIENT_DROPPORT */
#define CLIENT_NMCTXS_PERCPU 8
/*%<
* Number of 'mctx pools' for clients. (Should this be configurable?)
* When enabling threads, we use a pool of memory contexts shared by
* client objects, since concurrent access to a shared context would cause
* heavy contentions. The above constant is expected to be enough for
* completely avoiding contentions among threads for an authoritative-only
* server.
*/
#define CLIENT_NTASKS_PERCPU 32
/*%<
* Number of tasks to be used by clients - those are used only when recursing
*/
#if defined(_WIN32) && !defined(_WIN64)
LIBNS_EXTERNAL_DATA atomic_uint_fast32_t ns_client_requests;
#else /* if defined(_WIN32) && !defined(_WIN64) */
@@ -133,6 +147,8 @@ compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
const unsigned char *secret, isc_buffer_t *buf);
static void
get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp);
static void
get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp);
void
ns_client_recursing(ns_client_t *client) {
@@ -172,21 +188,20 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
static void
ns_client_endrequest(ns_client_t *client) {
INSIST(client->naccepts == 0);
INSIST(client->nreads == 0);
INSIST(client->nsends == 0);
INSIST(client->nrecvs == 0);
INSIST(client->nupdates == 0);
INSIST(client->state == NS_CLIENTSTATE_WORKING ||
client->state == NS_CLIENTSTATE_RECURSING);
CTRACE("endrequest");
LOCK(&client->manager->reclock);
if (ISC_LINK_LINKED(client, rlink)) {
ISC_LIST_UNLINK(client->manager->recursing, client, rlink);
if (client->state == NS_CLIENTSTATE_RECURSING) {
LOCK(&client->manager->reclock);
if (ISC_LINK_LINKED(client, rlink)) {
ISC_LIST_UNLINK(client->manager->recursing, client,
rlink);
}
UNLOCK(&client->manager->reclock);
}
UNLOCK(&client->manager->reclock);
if (client->cleanup != NULL) {
(client->cleanup)(client);
@@ -1594,7 +1609,7 @@ ns__client_put_cb(void *client0) {
clientmgr_detach(&client->manager);
}
isc_mem_put(client->mctx, client->recvbuf, NS_CLIENT_RECV_BUFFER_SIZE);
isc_mem_put(client->mctx, client->sendbuf, NS_CLIENT_SEND_BUFFER_SIZE);
if (client->opt != NULL) {
INSIST(dns_rdataset_isassociated(client->opt));
dns_rdataset_disassociate(client->opt);
@@ -1684,7 +1699,6 @@ ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
}
client->state = NS_CLIENTSTATE_READY;
client->dscp = ifp->dscp;
isc_task_pause(client->task);
if (client->handle == NULL) {
@@ -2231,39 +2245,33 @@ ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
static void
get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
isc_mem_t *clientmctx;
#if CLIENT_NMCTXS > 0
unsigned int nextmctx;
#endif /* if CLIENT_NMCTXS > 0 */
MTRACE("clientmctx");
#if CLIENT_NMCTXS > 0
LOCK(&manager->lock);
if (isc_nm_tid() >= 0) {
nextmctx = isc_nm_tid();
} else {
nextmctx = manager->nextmctx++;
if (manager->nextmctx == CLIENT_NMCTXS) {
manager->nextmctx = 0;
}
INSIST(nextmctx < CLIENT_NMCTXS);
int tid = isc_nm_tid();
if (tid < 0) {
tid = isc_random_uniform(manager->ncpus);
}
int rand = isc_random_uniform(CLIENT_NMCTXS_PERCPU);
int nextmctx = (rand * manager->ncpus) + tid;
clientmctx = manager->mctxpool[nextmctx];
if (clientmctx == NULL) {
isc_mem_create(&clientmctx);
isc_mem_setname(clientmctx, "client", NULL);
manager->mctxpool[nextmctx] = clientmctx;
}
UNLOCK(&manager->lock);
#else /* if CLIENT_NMCTXS > 0 */
clientmctx = manager->mctx;
#endif /* if CLIENT_NMCTXS > 0 */
isc_mem_attach(clientmctx, mctxp);
}
static void
get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp) {
MTRACE("clienttask");
int tid = isc_nm_tid();
if (tid < 0) {
tid = isc_random_uniform(manager->ncpus);
}
int rand = isc_random_uniform(CLIENT_NTASKS_PERCPU);
int nexttask = (rand * manager->ncpus) + tid;
isc_task_attach(manager->taskpool[nexttask], taskp);
}
isc_result_t
ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
isc_result_t result;
@@ -2285,10 +2293,8 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
get_clientmctx(mgr, &client->mctx);
clientmgr_attach(mgr, &client->manager);
ns_server_attach(mgr->sctx, &client->sctx);
result = isc_task_create(mgr->taskmgr, 20, &client->task);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
get_clienttask(mgr, &client->task);
result = dns_message_create(client->mctx,
DNS_MESSAGE_INTENTPARSE,
&client->message);
@@ -2296,8 +2302,8 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
goto cleanup;
}
client->recvbuf = isc_mem_get(client->mctx,
NS_CLIENT_RECV_BUFFER_SIZE);
client->sendbuf = isc_mem_get(client->mctx,
NS_CLIENT_SEND_BUFFER_SIZE);
/*
* Set magic earlier than usual because ns_query_init()
* and the functions it calls will require it.
@@ -2311,7 +2317,7 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
ns_clientmgr_t *oldmgr = client->manager;
ns_server_t *sctx = client->sctx;
isc_task_t *task = client->task;
unsigned char *recvbuf = client->recvbuf;
unsigned char *sendbuf = client->sendbuf;
dns_message_t *message = client->message;
isc_mem_t *oldmctx = client->mctx;
ns_query_t query = client->query;
@@ -2321,14 +2327,13 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
.manager = oldmgr,
.sctx = sctx,
.task = task,
.recvbuf = recvbuf,
.sendbuf = sendbuf,
.message = message,
.query = query };
}
client->state = NS_CLIENTSTATE_INACTIVE;
client->udpsize = 512;
client->dscp = -1;
client->ednsversion = -1;
dns_name_init(&client->signername, NULL);
dns_ecs_init(&client->ecs);
@@ -2345,9 +2350,9 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
return (ISC_R_SUCCESS);
cleanup:
if (client->recvbuf != NULL) {
isc_mem_put(client->mctx, client->recvbuf,
NS_CLIENT_RECV_BUFFER_SIZE);
if (client->sendbuf != NULL) {
isc_mem_put(client->mctx, client->sendbuf,
NS_CLIENT_SEND_BUFFER_SIZE);
}
if (client->message != NULL) {
@@ -2412,22 +2417,19 @@ clientmgr_detach(ns_clientmgr_t **mp) {
static void
clientmgr_destroy(ns_clientmgr_t *manager) {
#if CLIENT_NMCTXS > 0
int i;
#endif /* if CLIENT_NMCTXS > 0 */
MTRACE("clientmgr_destroy");
isc_refcount_destroy(&manager->references);
manager->magic = 0;
#if CLIENT_NMCTXS > 0
for (i = 0; i < CLIENT_NMCTXS; i++) {
if (manager->mctxpool[i] != NULL) {
isc_mem_detach(&manager->mctxpool[i]);
}
for (i = 0; i < manager->ncpus * CLIENT_NMCTXS_PERCPU; i++) {
isc_mem_detach(&manager->mctxpool[i]);
}
#endif /* if CLIENT_NMCTXS > 0 */
isc_mem_put(manager->mctx, manager->mctxpool,
manager->ncpus * CLIENT_NMCTXS_PERCPU *
sizeof(isc_mem_t *));
if (manager->interface != NULL) {
ns_interface_detach(&manager->interface);
@@ -2440,13 +2442,14 @@ clientmgr_destroy(ns_clientmgr_t *manager) {
isc_task_detach(&manager->excl);
}
for (i = 0; i < CLIENT_NTASKS; i++) {
for (i = 0; i < manager->ncpus * CLIENT_NTASKS_PERCPU; i++) {
if (manager->taskpool[i] != NULL) {
isc_task_detach(&manager->taskpool[i]);
}
}
isc_mem_put(manager->mctx, manager->taskpool,
CLIENT_NTASKS * sizeof(isc_task_t *));
manager->ncpus * CLIENT_NTASKS_PERCPU *
sizeof(isc_task_t *));
ns_server_detach(&manager->sctx);
isc_mem_put(manager->mctx, manager, sizeof(*manager));
@@ -2455,12 +2458,11 @@ clientmgr_destroy(ns_clientmgr_t *manager) {
isc_result_t
ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, ns_interface_t *interface,
ns_clientmgr_t **managerp) {
int ncpus, ns_clientmgr_t **managerp) {
ns_clientmgr_t *manager;
isc_result_t result;
#if CLIENT_NMCTXS > 0
int i;
#endif /* if CLIENT_NMCTXS > 0 */
int npools;
manager = isc_mem_get(mctx, sizeof(*manager));
*manager = (ns_clientmgr_t){ .magic = 0 };
@@ -2477,27 +2479,35 @@ ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
manager->mctx = mctx;
manager->taskmgr = taskmgr;
manager->timermgr = timermgr;
manager->ncpus = ncpus;
ns_interface_attach(interface, &manager->interface);
manager->exiting = false;
manager->taskpool = isc_mem_get(mctx,
CLIENT_NTASKS * sizeof(isc_task_t *));
for (i = 0; i < CLIENT_NTASKS; i++) {
int ntasks = CLIENT_NTASKS_PERCPU * manager->ncpus;
manager->taskpool = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
for (i = 0; i < ntasks; i++) {
manager->taskpool[i] = NULL;
isc_task_create(manager->taskmgr, 20, &manager->taskpool[i]);
result = isc_task_create_bound(manager->taskmgr, 20,
&manager->taskpool[i],
i % CLIENT_NTASKS_PERCPU);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
isc_refcount_init(&manager->references, 1);
manager->sctx = NULL;
ns_server_attach(sctx, &manager->sctx);
ISC_LIST_INIT(manager->recursing);
#if CLIENT_NMCTXS > 0
manager->nextmctx = 0;
for (i = 0; i < CLIENT_NMCTXS; i++) {
manager->mctxpool[i] = NULL; /* will be created on-demand */
npools = CLIENT_NMCTXS_PERCPU * manager->ncpus;
manager->mctxpool = isc_mem_get(manager->mctx,
npools * sizeof(isc_mem_t *));
for (i = 0; i < npools; i++) {
manager->mctxpool[i] = NULL;
isc_mem_create(&manager->mctxpool[i]);
isc_mem_setname(manager->mctxpool[i], "client", NULL);
}
#endif /* if CLIENT_NMCTXS > 0 */
manager->magic = MANAGER_MAGIC;
MTRACE("create");
+4 -26
View File
@@ -85,20 +85,6 @@
#define NS_CLIENT_SEND_BUFFER_SIZE 4096
#define NS_CLIENT_RECV_BUFFER_SIZE 4096
#define CLIENT_NMCTXS 100
/*%<
* Number of 'mctx pools' for clients. (Should this be configurable?)
* When enabling threads, we use a pool of memory contexts shared by
* client objects, since concurrent access to a shared context would cause
* heavy contentions. The above constant is expected to be enough for
* completely avoiding contentions among threads for an authoritative-only
* server.
*/
#define CLIENT_NTASKS 100
/*%<
* Number of tasks to be used by clients - those are used only when recursing
*/
/*!
* Client object states. Ordering is significant: higher-numbered
@@ -166,6 +152,7 @@ struct ns_clientmgr {
isc_timermgr_t *timermgr;
isc_task_t * excl;
isc_refcount_t references;
int ncpus;
/* Attached by clients, needed for e.g. recursion */
isc_task_t **taskpool;
@@ -180,11 +167,8 @@ struct ns_clientmgr {
isc_mutex_t reclock;
client_list_t recursing; /*%< Recursing clients */
#if CLIENT_NMCTXS > 0
/*%< mctx pool for clients. */
unsigned int nextmctx;
isc_mem_t * mctxpool[CLIENT_NMCTXS];
#endif /* if CLIENT_NMCTXS > 0 */
isc_mem_t **mctxpool;
};
/*% nameserver client structure */
@@ -195,12 +179,7 @@ struct ns_client {
ns_server_t * sctx;
ns_clientmgr_t * manager;
ns_clientstate_t state;
int naccepts;
int nreads;
int nsends;
int nrecvs;
int nupdates;
int nctls;
bool shuttingdown;
unsigned int attributes;
isc_task_t * task;
@@ -209,8 +188,7 @@ struct ns_client {
isc_nmhandle_t * handle;
unsigned char * tcpbuf;
dns_message_t * message;
unsigned char * recvbuf;
unsigned char sendbuf[NS_CLIENT_SEND_BUFFER_SIZE];
unsigned char * sendbuf;
dns_rdataset_t * opt;
uint16_t udpsize;
uint16_t extflags;
@@ -364,7 +342,7 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds);
isc_result_t
ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, ns_interface_t *ifp,
isc_timermgr_t *timermgr, ns_interface_t *ifp, int ncpus,
ns_clientmgr_t **managerp);
/*%<
* Create a client manager.
+1 -1
View File
@@ -104,7 +104,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
isc_socketmgr_t *socketmgr, isc_nm_t *nm,
dns_dispatchmgr_t *dispatchmgr, isc_task_t *task,
unsigned int udpdisp, dns_geoip_databases_t *geoip,
ns_interfacemgr_t **mgrp);
int ncpus, ns_interfacemgr_t **mgrp);
/*%<
* Create a new interface manager.
*
+5 -2
View File
@@ -77,6 +77,7 @@ struct ns_interfacemgr {
isc_timermgr_t *timermgr; /*%< Timer manager. */
isc_socketmgr_t *socketmgr; /*%< Socket manager. */
isc_nm_t *nm; /*%< Net manager. */
int ncpus; /*%< Number of workers . */
dns_dispatchmgr_t *dispatchmgr;
unsigned int generation; /*%< Current generation no. */
ns_listenlist_t *listenon4;
@@ -183,7 +184,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
isc_socketmgr_t *socketmgr, isc_nm_t *nm,
dns_dispatchmgr_t *dispatchmgr, isc_task_t *task,
unsigned int udpdisp, dns_geoip_databases_t *geoip,
ns_interfacemgr_t **mgrp) {
int ncpus, ns_interfacemgr_t **mgrp) {
isc_result_t result;
ns_interfacemgr_t *mgr;
@@ -220,6 +221,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
mgr->listenon4 = NULL;
mgr->listenon6 = NULL;
mgr->udpdisp = udpdisp;
mgr->ncpus = ncpus;
atomic_init(&mgr->shuttingdown, false);
ISC_LIST_INIT(mgr->interfaces);
@@ -426,7 +428,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
ifp->magic = IFACE_MAGIC;
result = ns_clientmgr_create(mgr->mctx, mgr->sctx, mgr->taskmgr,
mgr->timermgr, ifp, &ifp->clientmgr);
mgr->timermgr, ifp, mgr->ncpus,
&ifp->clientmgr);
if (result != ISC_R_SUCCESS) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
"ns_clientmgr_create() failed: %s",
+1 -1
View File
@@ -234,7 +234,7 @@ create_managers(void) {
CHECK(ns_interfacemgr_create(mctx, sctx, taskmgr, timermgr, socketmgr,
nm, dispatchmgr, maintask, ncpus, NULL,
&interfacemgr));
ncpus, &interfacemgr));
CHECK(ns_listenlist_default(mctx, port, -1, true, &listenon));
ns_interfacemgr_setlistenon4(interfacemgr, listenon);
+7
View File
@@ -223,6 +223,9 @@ my @substdefh = ("CONFIGARGS",
"HAVE_HMAC_CTX_GET_MD",
"HAVE_HMAC_CTX_NEW",
"HAVE_HMAC_CTX_RESET",
"HAVE_UV_HANDLE_GET_DATA",
"HAVE_UV_HANDLE_SET_DATA",
"HAVE_UV_IMPORT",
);
# for platform.h
@@ -1321,6 +1324,10 @@ if ($use_libuv eq "auto") {
last;
}
}
$configdefh{"HAVE_UV_HANDLE_SET_DATA"} = 1;
$configdefh{"HAVE_UV_HANDLE_GET_DATA"} = 1;
$configdefh{"HAVE_UV_IMPORT"} = 1;
# If we have one use it otherwise report the error
if ($use_libuv eq "auto") {