* Since we have a pool of tasks we bind them to task
* queues to spread the load evenly
*/
- result = isc_task_create_bound(taskmgr, 0,
- &res->buckets[i].task, i);
+ result = isc_task_create_bound(
+ taskmgr, 0, &res->buckets[i].task, ISC_NM_TASK_SLOW(i));
if (result != ISC_R_SUCCESS) {
ntasks = i;
isc_mutex_destroy(&res->buckets[i].lock);
* \li 'handle' is a valid netmgr handle object.
*/
+#define ISC_NM_TASK_SLOW_OFFSET -2
+#define ISC_NM_TASK_SLOW(i) (ISC_NM_TASK_SLOW_OFFSET - 1 - i)
+
void
isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid);
/*%<
void
isc_nm_http_set_endpoints(isc_nmsocket_t *listener,
isc_nm_http_endpoints_t *eps) {
- size_t nworkers;
+ size_t nlisteners;
REQUIRE(VALID_NMSOCK(listener));
REQUIRE(listener->type == isc_nm_httplistener);
atomic_store(&eps->in_use, true);
- nworkers = (size_t)listener->mgr->nworkers;
- for (size_t i = 0; i < nworkers; i++) {
+ nlisteners = (size_t)listener->mgr->nlisteners;
+ for (size_t i = 0; i < nlisteners; i++) {
isc__netievent__http_eps_t *ievent =
isc__nm_get_netievent_httpendpoints(listener->mgr,
listener, eps);
static void
http_init_listener_endpoints(isc_nmsocket_t *listener,
isc_nm_http_endpoints_t *epset) {
- size_t nworkers;
+ size_t nlisteners;
REQUIRE(VALID_NMSOCK(listener));
REQUIRE(VALID_NM(listener->mgr));
REQUIRE(VALID_HTTP_ENDPOINTS(epset));
- nworkers = (size_t)listener->mgr->nworkers;
- INSIST(nworkers > 0);
+ nlisteners = (size_t)listener->mgr->nlisteners;
+ INSIST(nlisteners > 0);
listener->h2.listener_endpoints =
isc_mem_get(listener->mgr->mctx,
- sizeof(isc_nm_http_endpoints_t *) * nworkers);
- listener->h2.n_listener_endpoints = nworkers;
- for (size_t i = 0; i < nworkers; i++) {
+ sizeof(isc_nm_http_endpoints_t *) * nlisteners);
+ listener->h2.n_listener_endpoints = nlisteners;
+ for (size_t i = 0; i < nlisteners; i++) {
listener->h2.listener_endpoints[i] = NULL;
isc_nm_http_endpoints_attach(
epset, &listener->h2.listener_endpoints[i]);
isc_refcount_t references;
isc_mem_t *mctx;
int nworkers;
+ int nlisteners;
isc_mutex_t lock;
isc_condition_t wkstatecond;
isc_condition_t wkpausecond;
}
static void
-isc__nm_threadpool_initialize(uint32_t workers) {
+isc__nm_threadpool_initialize(uint32_t nworkers) {
char buf[11];
int r = uv_os_getenv("UV_THREADPOOL_SIZE", buf,
&(size_t){ sizeof(buf) });
if (r == UV_ENOENT) {
- snprintf(buf, sizeof(buf), "%" PRIu32, workers);
+ snprintf(buf, sizeof(buf), "%" PRIu32, nworkers);
uv_os_setenv("UV_THREADPOOL_SIZE", buf);
}
}
#endif
void
-isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
+isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) {
isc_nm_t *mgr = NULL;
char name[32];
- REQUIRE(workers > 0);
+ REQUIRE(nworkers > 0);
#ifdef MAXIMAL_UV_VERSION
if (uv_version() > MAXIMAL_UV_VERSION) {
uv_version_string(), UV_VERSION_STRING);
}
- isc__nm_threadpool_initialize(workers);
+ isc__nm_threadpool_initialize(nworkers);
mgr = isc_mem_get(mctx, sizeof(*mgr));
- *mgr = (isc_nm_t){ .nworkers = workers };
+ *mgr = (isc_nm_t){
+ .nworkers = nworkers * 2,
+ .nlisteners = nworkers,
+ };
isc_mem_attach(mctx, &mgr->mctx);
isc_mutex_init(&mgr->lock);
atomic_init(&mgr->keepalive, 30000);
atomic_init(&mgr->advertised, 30000);
- isc_barrier_init(&mgr->pausing, workers);
- isc_barrier_init(&mgr->resuming, workers);
+ isc_barrier_init(&mgr->pausing, mgr->nworkers);
+ isc_barrier_init(&mgr->resuming, mgr->nworkers);
- mgr->workers = isc_mem_get(mctx, workers * sizeof(isc__networker_t));
- for (size_t i = 0; i < workers; i++) {
+ mgr->workers = isc_mem_get(mctx,
+ mgr->nworkers * sizeof(isc__networker_t));
+ for (int i = 0; i < mgr->nworkers; i++) {
isc__networker_t *worker = &mgr->workers[i];
int r;
mgr->workers_running++;
isc_thread_create(nm_thread, &mgr->workers[i], &worker->thread);
- snprintf(name, sizeof(name), "isc-net-%04zu", i);
+ snprintf(name, sizeof(name), "isc-net-%04d", i);
isc_thread_setname(worker->thread, name);
}
isc__networker_t *worker = NULL;
if (threadid == -1) {
- tid = (int)isc_random_uniform(nm->nworkers);
+ tid = (int)isc_random_uniform(nm->nlisteners);
+ } else if (threadid == ISC_NM_TASK_SLOW_OFFSET) {
+ tid = nm->nlisteners +
+ (int)isc_random_uniform(nm->nworkers - nm->nlisteners);
+ } else if (threadid < ISC_NM_TASK_SLOW_OFFSET) {
+ tid = nm->nlisteners + (ISC_NM_TASK_SLOW(threadid) %
+ (nm->nworkers - nm->nlisteners));
} else {
- tid = threadid % nm->nworkers;
+ tid = threadid % nm->nlisteners;
}
worker = &nm->workers[tid];
static void
set_tlsctx_workers(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
/* Update the TLS context reference for every worker thread. */
- for (size_t i = 0; i < (size_t)listener->mgr->nworkers; i++) {
+ for (size_t i = 0; i < (size_t)listener->mgr->nlisteners; i++) {
isc__netievent__tlsctx_t *ievent =
isc__nm_get_netievent_settlsctx(listener->mgr, listener,
tlsctx);
isc__nm_connectcb(sock, req, result, false);
} else {
isc__nmsocket_clearcb(sock);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_connectcb(sock, req, result, true);
}
atomic_store(&sock->closed, true);
isc__nm_put_netievent_tcpconnect(mgr, ievent);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
isc__nmsocket_init(sock, mgr, isc_nm_tcplistener, iface);
atomic_init(&sock->rchildren, 0);
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
children_size = sock->nchildren * sizeof(sock->children[0]);
sock->children = isc_mem_get(mgr->mctx, children_size);
memset(sock->children, 0, children_size);
isc__nm_put_netievent_tcpdnsconnect(mgr, ievent);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
isc__nmsocket_init(sock, mgr, isc_nm_tcpdnslistener, iface);
atomic_init(&sock->rchildren, 0);
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
children_size = sock->nchildren * sizeof(sock->children[0]);
sock->children = isc_mem_get(mgr->mctx, children_size);
memset(sock->children, 0, children_size);
isc__nm_put_netievent_tlsdnsconnect(mgr, ievent);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
isc__nmsocket_init(sock, mgr, isc_nm_tlsdnslistener, iface);
atomic_init(&sock->rchildren, 0);
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
children_size = sock->nchildren * sizeof(sock->children[0]);
sock->children = isc_mem_get(mgr->mctx, children_size);
memset(sock->children, 0, children_size);
static void
tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) {
- size_t nworkers;
+ size_t nlisteners;
REQUIRE(VALID_NM(listener->mgr));
REQUIRE(ctx != NULL);
- nworkers = (size_t)listener->mgr->nworkers;
- INSIST(nworkers > 0);
+ nlisteners = (size_t)listener->mgr->nlisteners;
+ INSIST(nlisteners > 0);
listener->tlsstream.listener_tls_ctx = isc_mem_get(
- listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers);
- listener->tlsstream.n_listener_tls_ctx = nworkers;
- for (size_t i = 0; i < nworkers; i++) {
+ listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nlisteners);
+ listener->tlsstream.n_listener_tls_ctx = nlisteners;
+ for (size_t i = 0; i < nlisteners; i++) {
listener->tlsstream.listener_tls_ctx[i] = NULL;
isc_tlsctx_attach(ctx,
&listener->tlsstream.listener_tls_ctx[i]);
REQUIRE(VALID_NM(mgr));
/*
- * We are creating mgr->nworkers duplicated sockets, one
+ * We are creating mgr->nlisteners duplicated sockets, one
* socket for each worker thread.
*/
sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t));
isc__nmsocket_init(sock, mgr, isc_nm_udplistener, iface);
atomic_init(&sock->rchildren, 0);
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
children_size = sock->nchildren * sizeof(sock->children[0]);
sock->children = isc_mem_get(mgr->mctx, children_size);
memset(sock->children, 0, children_size);
isc__nm_put_netievent_udpconnect(mgr, event);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)event);
}