Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f11cc50da2 | ||
|
|
9455067864 | ||
|
|
a5b705c380 | ||
|
|
e5d9620b08 | ||
|
|
46bea75dcc | ||
|
|
a4e4e9af05 | ||
|
|
be952bb48a | ||
|
|
473523d7ea | ||
|
|
f68670503a | ||
|
|
cf75315fbf | ||
|
|
bc08966735 | ||
|
|
a247dd540a | ||
|
|
8c76ef90b1 | ||
|
|
31d71bc30c | ||
|
|
81a565b48f | ||
|
|
990c65121a | ||
|
|
cc5b3dbe96 | ||
|
|
75c6cc8efc | ||
|
|
6111554eda | ||
|
|
f7459d16bf | ||
|
|
fc4d685865 | ||
|
|
8b461258a5 | ||
|
|
cccb053554 | ||
|
|
2acc4a907f |
+10
-10
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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") {
|
||||
|
||||
Reference in New Issue
Block a user