Merge branch '2654-create-isc_managers-api' into 'main'

Destroy netmgr before destroying taskmgr

Closes #2654

See merge request isc-projects/bind9!4983
This commit is contained in:
Evan Hunt 2021-05-07 21:37:01 +00:00
commit 0e92060833
62 changed files with 1697 additions and 1295 deletions

14
CHANGES
View file

@ -1,3 +1,17 @@
5638. [bug] Improvements related to network manager/task manager
integration:
- added isc_managers_create() and _destroy() functions
to handle setup and teardown of netmgr, taskmgr,
timermgr and socketmgr since these require a
precise order of operations now.
- event queue processing is now quantized to prevent
infinite looping.
- the netmgr can now be paused from within a netmgr
thread.
- fixed deadlocks due to conflict between netmgr
pause/resume and listen/stoplistening operations.
[GL #2654]
5637. [placeholder]
5636. [bug] Check that zone files for 'dnssec-policy' zones are

View file

@ -34,6 +34,7 @@
#include <isc/hex.h>
#include <isc/lib.h>
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/md.h>
#include <isc/mem.h>
#include <isc/netmgr.h>
@ -1761,10 +1762,8 @@ main(int argc, char *argv[]) {
isc_mem_create(&mctx);
CHECK(isc_appctx_create(mctx, &actx));
netmgr = isc_nm_start(mctx, 1);
CHECK(isc_taskmgr_create(mctx, 0, netmgr, &taskmgr));
CHECK(isc_socketmgr_create(mctx, &socketmgr));
CHECK(isc_timermgr_create(mctx, &timermgr));
isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr,
&socketmgr);
parse_args(argc, argv);
@ -1867,18 +1866,7 @@ cleanup:
if (client != NULL) {
dns_client_destroy(&client);
}
if (taskmgr != NULL) {
isc_taskmgr_destroy(&taskmgr);
}
if (netmgr != NULL) {
isc_nm_destroy(&netmgr);
}
if (timermgr != NULL) {
isc_timermgr_destroy(&timermgr);
}
if (socketmgr != NULL) {
isc_socketmgr_destroy(&socketmgr);
}
isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr);
if (actx != NULL) {
isc_appctx_destroy(&actx);
}

View file

@ -41,6 +41,7 @@
#include <isc/hex.h>
#include <isc/lang.h>
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/netaddr.h>
#include <isc/netdb.h>
#include <isc/nonce.h>
@ -106,9 +107,9 @@ unsigned int timeout = 0;
unsigned int extrabytes;
isc_mem_t *mctx = NULL;
isc_log_t *lctx = NULL;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_task_t *global_task = NULL;
isc_nm_t *netmgr = NULL;
isc_sockaddr_t localaddr;
isc_refcount_t sendcount = ATOMIC_VAR_INIT(0);
isc_refcount_t recvcount = ATOMIC_VAR_INIT(0);
@ -226,8 +227,9 @@ void (*dighost_shutdown)(void);
/* forward declarations */
#define cancel_lookup(l) _cancel_lookup(l, __FILE__, __LINE__)
static void
cancel_lookup(dig_lookup_t *lookup);
_cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line);
static void
recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
@ -1360,10 +1362,7 @@ setup_libs(void) {
isc_log_setdebuglevel(lctx, 0);
netmgr = isc_nm_start(mctx, 1);
result = isc_taskmgr_create(mctx, 0, netmgr, &taskmgr);
check_result(result, "isc_taskmgr_create");
isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, NULL, NULL);
result = isc_task_create(taskmgr, 0, &global_task);
check_result(result, "isc_task_create");
@ -1696,6 +1695,9 @@ _query_detach(dig_query_t **queryp, const char *file, unsigned int line) {
isc_refcount_current(&query->references) - 1);
if (isc_refcount_decrement(&query->references) == 1) {
INSIST(query->readhandle == NULL);
INSIST(query->sendhandle == NULL);
if (ISC_LINK_LINKED(query, link)) {
ISC_LIST_UNLINK(lookup->q, query, link);
}
@ -1752,13 +1754,18 @@ start_lookup(void) {
* decremented, current_lookup will not be set to NULL.)
*/
static void
clear_current_lookup() {
clear_current_lookup(void) {
dig_lookup_t *lookup = current_lookup;
INSIST(!free_now);
debug("clear_current_lookup()");
if (lookup == NULL) {
debug("current_lookup is already detached");
return;
}
if (ISC_LIST_HEAD(lookup->q) != NULL) {
debug("still have a worker");
return;
@ -2671,11 +2678,12 @@ send_done(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
/*%
* Cancel a lookup, sending canceling reads on all existing sockets.
*/
static void
cancel_lookup(dig_lookup_t *lookup) {
_cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line) {
dig_query_t *query, *next;
debug("cancel_lookup()");
debug("%s:%u:%s()", file, line, __func__);
query = ISC_LIST_HEAD(lookup->q);
while (query != NULL) {
REQUIRE(DIG_VALID_QUERY(query));
@ -2904,6 +2912,7 @@ udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
isc_result_totext(eresult));
}
cancel_lookup(l);
lookup_detach(&l);
query_detach(&query);
return;
@ -2941,6 +2950,7 @@ static void
start_udp(dig_query_t *query) {
isc_result_t result;
dig_query_t *next = NULL;
dig_query_t *connectquery = NULL;
REQUIRE(DIG_VALID_QUERY(query));
@ -2992,8 +3002,10 @@ start_udp(dig_query_t *query) {
}
}
query_attach(query, &connectquery);
isc_nm_udpconnect(netmgr, (isc_nmiface_t *)&localaddr,
(isc_nmiface_t *)&query->sockaddr, udp_ready, query,
(isc_nmiface_t *)&query->sockaddr, udp_ready,
connectquery,
(timeout ? timeout : UDP_TIMEOUT) * 1000, 0);
}
@ -3568,16 +3580,19 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
region, arg);
LOCK_LOOKUP;
lookup_attach(query->lookup, &l);
isc_refcount_decrement0(&recvcount);
debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount));
if (eresult == ISC_R_CANCELED) {
debug("recv_done: cancel");
goto detach_query;
isc_nmhandle_detach(&query->readhandle);
query_detach(&query);
return;
}
lookup_attach(query->lookup, &l);
if (query->lookup->use_usec) {
TIME_NOW_HIRES(&query->time_recv);
} else {
@ -4188,19 +4203,23 @@ cancel_all(void) {
return;
}
atomic_store(&cancel_now, true);
if (current_lookup != NULL) {
while (current_lookup != NULL) {
for (q = ISC_LIST_HEAD(current_lookup->q); q != NULL; q = nq) {
nq = ISC_LIST_NEXT(q, link);
debug("canceling pending query %p, belonging to %p", q,
current_lookup);
if (q->readhandle != NULL) {
isc_refcount_decrement0(&recvcount);
debug("recvcount=%" PRIuFAST32,
isc_refcount_current(&recvcount));
isc_nm_cancelread(q->readhandle);
}
query_detach(&q);
}
lookup_detach(&current_lookup);
/*
* current_lookup could have been detached via query_detach().
*/
if (current_lookup != NULL) {
lookup_detach(&current_lookup);
}
}
l = ISC_LIST_HEAD(lookup_list);
while (l != NULL) {
@ -4226,20 +4245,8 @@ destroy_libs(void) {
debug("freeing task");
isc_task_detach(&global_task);
}
/*
* The taskmgr_destroy() and isc_nm_destroy() calls block until
* all events are cleared.
*/
if (taskmgr != NULL) {
debug("freeing taskmgr");
isc_taskmgr_destroy(&taskmgr);
}
debug("closing down netmgr");
isc_nm_closedown(netmgr);
debug("destroy netmgr");
isc_nm_destroy(&netmgr);
isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL);
LOCK_LOOKUP;
isc_refcount_destroy(&recvcount);

View file

@ -40,6 +40,7 @@
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/hex.h>
#include <isc/managers.h>
#include <isc/md.h>
#include <isc/mem.h>
#include <isc/mutex.h>
@ -3963,13 +3964,7 @@ main(int argc, char *argv[]) {
print_time(outfp);
print_version(outfp);
netmgr = isc_nm_start(mctx, ntasks);
result = isc_taskmgr_create(mctx, 0, netmgr, &taskmgr);
if (result != ISC_R_SUCCESS) {
fatal("failed to create task manager: %s",
isc_result_totext(result));
}
isc_managers_create(mctx, ntasks, 0, 0, &netmgr, &taskmgr, NULL, NULL);
master = NULL;
result = isc_task_create(taskmgr, 0, &master);
@ -4020,8 +4015,7 @@ main(int argc, char *argv[]) {
for (i = 0; i < (int)ntasks; i++) {
isc_task_detach(&tasks[i]);
}
isc_taskmgr_destroy(&taskmgr);
isc_nm_destroy(&netmgr);
isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL);
isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
postsign();
TIME_NOW(&sign_finish);

View file

@ -1164,10 +1164,10 @@ add_listener(named_controls_t *cp, controllistener_t **listenerp,
}
#endif
CHECK(isc_nm_listentcp(named_g_nm, (isc_nmiface_t *)&listener->address,
control_newconn, listener,
sizeof(controlconnection_t), 5, NULL,
&listener->sock));
CHECK(isc_nm_listentcp(
named_g_netmgr, (isc_nmiface_t *)&listener->address,
control_newconn, listener, sizeof(controlconnection_t), 5, NULL,
&listener->sock));
#if 0
/* XXX: no unix socket support yet */
if (type == isc_socktype_unix) {

View file

@ -62,7 +62,7 @@ EXTERN bool named_g_run_done INIT(false);
*/
EXTERN isc_timermgr_t *named_g_timermgr INIT(NULL);
EXTERN isc_socketmgr_t *named_g_socketmgr INIT(NULL);
EXTERN isc_nm_t *named_g_nm INIT(NULL);
EXTERN isc_nm_t *named_g_netmgr INIT(NULL);
EXTERN cfg_parser_t *named_g_parser INIT(NULL);
EXTERN cfg_parser_t *named_g_addparser INIT(NULL);
EXTERN const char *named_g_version INIT(PACKAGE_VERSION);

View file

@ -31,6 +31,7 @@
#include <isc/hash.h>
#include <isc/hp.h>
#include <isc/httpd.h>
#include <isc/managers.h>
#include <isc/netmgr.h>
#include <isc/os.h>
#include <isc/platform.h>
@ -937,45 +938,17 @@ create_managers(void) {
"using %u UDP listener%s per interface", named_g_udpdisp,
named_g_udpdisp == 1 ? "" : "s");
/*
* We have ncpus network threads, ncpus worker threads, ncpus
* old network threads - make it 4x just to be safe. The memory
* impact is negligible.
*/
isc_hp_init(4 * named_g_cpus);
named_g_nm = isc_nm_start(named_g_mctx, named_g_cpus);
if (named_g_nm == NULL) {
UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_nm_start() failed");
return (ISC_R_UNEXPECTED);
result = isc_managers_create(named_g_mctx, named_g_cpus,
0 /* quantum */, maxsocks, &named_g_netmgr,
&named_g_taskmgr, &named_g_timermgr,
&named_g_socketmgr);
if (result != ISC_R_SUCCESS) {
return (result);
}
result = isc_taskmgr_create(named_g_mctx, 0, named_g_nm,
&named_g_taskmgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_taskmgr_create() failed: %s",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
result = isc_timermgr_create(named_g_mctx, &named_g_timermgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_timermgr_create() failed: %s",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
result = isc_socketmgr_create2(named_g_mctx, &named_g_socketmgr,
maxsocks, named_g_cpus);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_socketmgr_create() failed: %s",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
isc_socketmgr_maxudp(named_g_socketmgr, maxudp);
isc_nm_maxudp(named_g_nm, maxudp);
isc_nm_maxudp(named_g_netmgr, maxudp);
result = isc_socketmgr_getmaxsockets(named_g_socketmgr, &socks);
if (result == ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
@ -988,21 +961,8 @@ create_managers(void) {
static void
destroy_managers(void) {
/*
* isc_nm_closedown() closes all active connections, freeing
* attached clients and other resources and preventing new
* connections from being established, but it not does not
* stop all processing or destroy the netmgr yet.
*/
isc_nm_closedown(named_g_nm);
/*
* isc_taskmgr_destroy() will block until all tasks have exited.
*/
isc_taskmgr_destroy(&named_g_taskmgr);
isc_nm_destroy(&named_g_nm);
isc_timermgr_destroy(&named_g_timermgr);
isc_socketmgr_destroy(&named_g_socketmgr);
isc_managers_destroy(&named_g_netmgr, &named_g_taskmgr,
&named_g_timermgr, &named_g_socketmgr);
}
static void

View file

@ -8840,7 +8840,8 @@ load_configuration(const char *filename, named_server_t *server,
advertised = MAX_ADVERTISED_TIMEOUT;
}
isc_nm_settimeouts(named_g_nm, initial, idle, keepalive, advertised);
isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive,
advertised);
/*
* Configure sets of UDP query source ports.
@ -9844,6 +9845,12 @@ view_loaded(void *arg) {
"all zones loaded");
}
/*
* Clear taskmgr privileged mode now that zones are loaded.
*/
isc_taskmgr_setmode(dns_zonemgr_gettaskmgr(server->zonemgr),
isc_taskmgrmode_normal);
CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr),
"forcing zone maintenance");
@ -9866,7 +9873,7 @@ view_loaded(void *arg) {
}
static isc_result_t
load_zones(named_server_t *server, bool reconfig) {
load_zones(named_server_t *server, bool init, bool reconfig) {
isc_result_t result;
dns_view_t *view;
ns_zoneload_t *zl;
@ -9923,6 +9930,19 @@ cleanup:
isc_mem_put(server->mctx, zl, sizeof(*zl));
}
/*
* If we're setting up the server for the first time,
* set the task manager into privileged mode; this ensures
* that no other tasks will begin to run until after
* zone loading is complete.
*
* We do *not* want to do this in the case of reload or
* reconfig, as loading a large zone could cause the server
* to be inactive for too long a time.
*/
isc_taskmgr_setmode(named_g_taskmgr, init ? isc_taskmgrmode_privileged
: isc_taskmgrmode_normal);
isc_task_endexclusive(server->task);
return (result);
}
@ -9950,7 +9970,7 @@ run_server(isc_task_t *task, isc_event_t *event) {
CHECKFATAL(ns_interfacemgr_create(
named_g_mctx, server->sctx, named_g_taskmgr,
named_g_timermgr, named_g_socketmgr, named_g_nm,
named_g_timermgr, named_g_socketmgr, named_g_netmgr,
named_g_dispatchmgr, server->task, named_g_udpdisp,
geoip, named_g_cpus, &server->interfacemgr),
"creating interface manager");
@ -9988,7 +10008,7 @@ run_server(isc_task_t *task, isc_event_t *event) {
CHECKFATAL(load_configuration(named_g_conffile, server, true),
"loading configuration");
CHECKFATAL(load_zones(server, false), "loading zones");
CHECKFATAL(load_zones(server, true, false), "loading zones");
#ifdef ENABLE_AFL
named_g_run_done = true;
#endif /* ifdef ENABLE_AFL */
@ -10181,7 +10201,7 @@ named_server_create(isc_mem_t *mctx, named_server_t **serverp) {
* startup and shutdown of the server, as well as all exclusive
* tasks.
*/
CHECKFATAL(isc_task_create(named_g_taskmgr, 0, &server->task),
CHECKFATAL(isc_task_create_bound(named_g_taskmgr, 0, &server->task, 0),
"creating server task");
isc_task_setname(server->task, "server", server);
isc_taskmgr_setexcltask(named_g_taskmgr, server->task);
@ -10220,7 +10240,7 @@ named_server_create(isc_mem_t *mctx, named_server_t **serverp) {
CHECKFATAL(dns_zonemgr_create(named_g_mctx, named_g_taskmgr,
named_g_timermgr, named_g_socketmgr,
named_g_nm, &server->zonemgr),
named_g_netmgr, &server->zonemgr),
"dns_zonemgr_create");
CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000), "dns_zonemgr_"
"setsize");
@ -10260,7 +10280,7 @@ named_server_create(isc_mem_t *mctx, named_server_t **serverp) {
isc_sockstatscounter_max),
"isc_stats_create");
isc_socketmgr_setstats(named_g_socketmgr, server->sockstats);
isc_nm_setstats(named_g_nm, server->sockstats);
isc_nm_setstats(named_g_netmgr, server->sockstats);
CHECKFATAL(isc_stats_create(named_g_mctx, &server->zonestats,
dns_zonestatscounter_max),
@ -10501,7 +10521,7 @@ reload(named_server_t *server) {
CHECK(loadconfig(server));
result = load_zones(server, false);
result = load_zones(server, false, false);
if (result == ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
@ -10870,7 +10890,7 @@ named_server_reconfigcommand(named_server_t *server) {
CHECK(loadconfig(server));
result = load_zones(server, true);
result = load_zones(server, false, true);
if (result == ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
@ -16342,7 +16362,7 @@ named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) {
return (ISC_R_UNEXPECTEDEND);
}
isc_nm_gettimeouts(named_g_nm, &initial, &idle, &keepalive,
isc_nm_gettimeouts(named_g_netmgr, &initial, &idle, &keepalive,
&advertised);
/* Look for optional arguments. */
@ -16396,7 +16416,7 @@ named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) {
result = isc_task_beginexclusive(named_g_server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
isc_nm_settimeouts(named_g_nm, initial, idle, keepalive,
isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive,
advertised);
isc_task_endexclusive(named_g_server->task);

View file

@ -3612,7 +3612,7 @@ add_listener(named_server_t *server, named_statschannel_t **listenerp,
CHECK(ISC_R_FAMILYNOSUPPORT);
}
CHECK(isc_httpdmgr_create(named_g_nm, server->mctx, addr, client_ok,
CHECK(isc_httpdmgr_create(named_g_netmgr, server->mctx, addr, client_ok,
destroy_listener, listener,
&listener->httpdmgr));

View file

@ -29,6 +29,7 @@
#include <isc/hash.h>
#include <isc/lex.h>
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/nonce.h>
#include <isc/parseint.h>
@ -923,16 +924,8 @@ setup_system(void) {
result = dns_dispatchmgr_create(gmctx, &dispatchmgr);
check_result(result, "dns_dispatchmgr_create");
result = isc_socketmgr_create(gmctx, &socketmgr);
check_result(result, "dns_socketmgr_create");
result = isc_timermgr_create(gmctx, &timermgr);
check_result(result, "dns_timermgr_create");
netmgr = isc_nm_start(gmctx, 1);
result = isc_taskmgr_create(gmctx, 0, netmgr, &taskmgr);
check_result(result, "isc_taskmgr_create");
isc_managers_create(gmctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr,
&socketmgr);
result = isc_task_create(taskmgr, 0, &global_task);
check_result(result, "isc_task_create");
@ -3325,21 +3318,12 @@ cleanup(void) {
dst_key_free(&sig0key);
}
ddebug("Shutting down task manager");
isc_taskmgr_destroy(&taskmgr);
ddebug("Shutting down network manager");
isc_nm_destroy(&netmgr);
ddebug("Shutting down managers");
isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr);
ddebug("Destroying event");
isc_event_free(&global_event);
ddebug("Shutting down socket manager");
isc_socketmgr_destroy(&socketmgr);
ddebug("Shutting down timer manager");
isc_timermgr_destroy(&timermgr);
#ifdef HAVE_GSSAPI
/*
* Cleanup GSSAPI resources after taskmgr has been destroyed.

View file

@ -22,6 +22,7 @@
#include <isc/commandline.h>
#include <isc/file.h>
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/net.h>
#include <isc/netmgr.h>
@ -59,6 +60,7 @@
const char *progname = NULL;
bool verbose;
static isc_nm_t *netmgr = NULL;
static isc_taskmgr_t *taskmgr = NULL;
static isc_task_t *rndc_task = NULL;
@ -72,7 +74,6 @@ static bool local4set = false, local6set = false;
static int nserveraddrs;
static int currentaddr = 0;
static unsigned int remoteport = 0;
static isc_nm_t *netmgr = NULL;
static isc_buffer_t *databuf = NULL;
static isccc_ccmsg_t rndc_ccmsg;
static uint32_t algorithm;
@ -1030,9 +1031,7 @@ main(int argc, char **argv) {
serial = isc_random32();
isc_mem_create(&rndc_mctx);
netmgr = isc_nm_start(rndc_mctx, 1);
DO("create task manager",
isc_taskmgr_create(rndc_mctx, 0, netmgr, &taskmgr));
isc_managers_create(rndc_mctx, 1, 0, 0, &netmgr, &taskmgr, NULL, NULL);
DO("create task", isc_task_create(taskmgr, 0, &rndc_task));
isc_log_create(rndc_mctx, &log, &logconfig);
isc_log_setcontext(log);
@ -1089,9 +1088,7 @@ main(int argc, char **argv) {
}
isc_task_detach(&rndc_task);
isc_taskmgr_destroy(&taskmgr);
isc_nm_closedown(netmgr);
isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL);
/*
* Note: when TCP connections are shut down, there will be a final
@ -1101,8 +1098,6 @@ main(int argc, char **argv) {
*/
isccc_ccmsg_invalidate(&rndc_ccmsg);
isc_nm_destroy(&netmgr);
isc_log_destroy(&log);
isc_log_setcontext(NULL);

View file

@ -20,6 +20,7 @@
#include <isc/commandline.h>
#include <isc/hash.h>
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/net.h>
#include <isc/parseint.h>
@ -208,10 +209,10 @@ main(int argc, char *argv[]) {
isc_logconfig_t *lcfg;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_task_t *task;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
dns_dispatchmgr_t *dispatchmgr;
isc_task_t *task = NULL;
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
dns_dispatchmgr_t *dispatchmgr = NULL;
unsigned int attrs, attrmask;
dns_dispatch_t *dispatchv4;
dns_view_t *view;
@ -277,17 +278,10 @@ main(int argc, char *argv[]) {
RUNCHECK(dst_lib_init(mctx, NULL));
netmgr = isc_nm_start(mctx, 1);
isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr,
&socketmgr);
RUNCHECK(isc_taskmgr_create(mctx, 0, netmgr, &taskmgr));
task = NULL;
RUNCHECK(isc_task_create(taskmgr, 0, &task));
timermgr = NULL;
RUNCHECK(isc_timermgr_create(mctx, &timermgr));
socketmgr = NULL;
RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
dispatchmgr = NULL;
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY |
@ -318,13 +312,10 @@ main(int argc, char *argv[]) {
dns_dispatch_detach(&dispatchv4);
dns_dispatchmgr_destroy(&dispatchmgr);
isc_socketmgr_destroy(&socketmgr);
isc_timermgr_destroy(&timermgr);
isc_task_shutdown(task);
isc_task_detach(&task);
isc_taskmgr_destroy(&taskmgr);
isc_nm_destroy(&netmgr);
isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr);
dst_lib_destroy();

View file

@ -29,6 +29,7 @@
#include <isc/buffer.h>
#include <isc/commandline.h>
#include <isc/lib.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/sockaddr.h>
@ -66,25 +67,8 @@ isc_timermgr_t *ctxs_timermgr = NULL;
static void
ctxs_destroy(void) {
if (ctxs_netmgr != NULL) {
isc_nm_closedown(ctxs_netmgr);
}
if (ctxs_taskmgr != NULL) {
isc_taskmgr_destroy(&ctxs_taskmgr);
}
if (ctxs_netmgr != NULL) {
isc_nm_destroy(&ctxs_netmgr);
}
if (ctxs_timermgr != NULL) {
isc_timermgr_destroy(&ctxs_timermgr);
}
if (ctxs_socketmgr != NULL) {
isc_socketmgr_destroy(&ctxs_socketmgr);
}
isc_managers_destroy(&ctxs_netmgr, &ctxs_taskmgr, &ctxs_timermgr,
&ctxs_socketmgr);
if (ctxs_actx != NULL) {
isc_appctx_destroy(&ctxs_actx);
@ -106,22 +90,8 @@ ctxs_init(void) {
goto fail;
}
ctxs_netmgr = isc_nm_start(ctxs_mctx, 1);
result = isc_taskmgr_create(ctxs_mctx, 0, ctxs_netmgr, &ctxs_taskmgr);
if (result != ISC_R_SUCCESS) {
goto fail;
}
result = isc_socketmgr_create(ctxs_mctx, &ctxs_socketmgr);
if (result != ISC_R_SUCCESS) {
goto fail;
}
result = isc_timermgr_create(ctxs_mctx, &ctxs_timermgr);
if (result != ISC_R_SUCCESS) {
goto fail;
}
isc_managers_create(ctxs_mctx, 1, 0, 0, &ctxs_netmgr, &ctxs_taskmgr,
&ctxs_timermgr, &ctxs_socketmgr);
return (ISC_R_SUCCESS);

View file

@ -16,6 +16,7 @@
#include <isc/base64.h>
#include <isc/hash.h>
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/nonce.h>
#include <isc/print.h>
@ -191,21 +192,21 @@ sendquery(isc_task_t *task, isc_event_t *event) {
int
main(int argc, char *argv[]) {
char *ourkeyname;
char *ourkeyname = NULL;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
isc_socket_t *sock;
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
isc_socket_t *sock = NULL;
unsigned int attrs, attrmask;
isc_sockaddr_t bind_any;
dns_dispatchmgr_t *dispatchmgr;
dns_dispatch_t *dispatchv4;
dns_view_t *view;
dns_tkeyctx_t *tctx;
isc_log_t *log;
isc_logconfig_t *logconfig;
isc_task_t *task;
dns_dispatchmgr_t *dispatchmgr = NULL;
dns_dispatch_t *dispatchv4 = NULL;
dns_view_t *view = NULL;
dns_tkeyctx_t *tctx = NULL;
isc_log_t *log = NULL;
isc_logconfig_t *logconfig = NULL;
isc_task_t *task = NULL;
isc_result_t result;
int type;
@ -235,17 +236,12 @@ main(int argc, char *argv[]) {
RUNCHECK(dst_lib_init(mctx, NULL));
netmgr = isc_nm_start(mctx, 1);
isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr,
&socketmgr);
RUNCHECK(isc_taskmgr_create(mctx, 0, netmgr, &taskmgr));
task = NULL;
RUNCHECK(isc_task_create(taskmgr, 0, &task));
timermgr = NULL;
RUNCHECK(isc_timermgr_create(mctx, &timermgr));
socketmgr = NULL;
RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
dispatchmgr = NULL;
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
isc_sockaddr_any(&bind_any);
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY |
DNS_DISPATCHATTR_IPV4;
@ -293,11 +289,8 @@ main(int argc, char *argv[]) {
dns_dispatchmgr_destroy(&dispatchmgr);
isc_task_shutdown(task);
isc_task_detach(&task);
isc_taskmgr_destroy(&taskmgr);
isc_nm_destroy(&netmgr);
isc_socket_detach(&sock);
isc_socketmgr_destroy(&socketmgr);
isc_timermgr_destroy(&timermgr);
isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr);
dst_key_free(&ourkey);
dns_tsigkey_detach(&initialkey);

View file

@ -16,6 +16,7 @@
#include <isc/base64.h>
#include <isc/hash.h>
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/netmgr.h>
#include <isc/print.h>
@ -135,22 +136,22 @@ sendquery(isc_task_t *task, isc_event_t *event) {
int
main(int argc, char **argv) {
char *keyname;
isc_nm_t *netmgr;
char *keyname = NULL;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
isc_socket_t *sock;
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
isc_socket_t *sock = NULL;
unsigned int attrs, attrmask;
isc_sockaddr_t bind_any;
dns_dispatchmgr_t *dispatchmgr;
dns_dispatch_t *dispatchv4;
dns_view_t *view;
dns_tkeyctx_t *tctx;
dst_key_t *dstkey;
isc_log_t *log;
isc_logconfig_t *logconfig;
isc_task_t *task;
dns_dispatchmgr_t *dispatchmgr = NULL;
dns_dispatch_t *dispatchv4 = NULL;
dns_view_t *view = NULL;
dns_tkeyctx_t *tctx = NULL;
dst_key_t *dstkey = NULL;
isc_log_t *log = NULL;
isc_logconfig_t *logconfig = NULL;
isc_task_t *task = NULL;
isc_result_t result;
int type;
@ -179,16 +180,10 @@ main(int argc, char **argv) {
RUNCHECK(dst_lib_init(mctx, NULL));
netmgr = isc_nm_start(mctx, 1);
isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr,
&socketmgr);
RUNCHECK(isc_taskmgr_create(mctx, 0, netmgr, &taskmgr));
task = NULL;
RUNCHECK(isc_task_create(taskmgr, 0, &task));
timermgr = NULL;
RUNCHECK(isc_timermgr_create(mctx, &timermgr));
socketmgr = NULL;
RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
dispatchmgr = NULL;
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
isc_sockaddr_any(&bind_any);
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY |
@ -237,11 +232,8 @@ main(int argc, char **argv) {
dns_dispatchmgr_destroy(&dispatchmgr);
isc_task_shutdown(task);
isc_task_detach(&task);
isc_taskmgr_destroy(&taskmgr);
isc_nm_destroy(&netmgr);
isc_socket_detach(&sock);
isc_socketmgr_destroy(&socketmgr);
isc_timermgr_destroy(&timermgr);
isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr);
dns_tsigkeyring_detach(&ring);

View file

@ -23,6 +23,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/netaddr.h>
#include <isc/netmgr.h>
@ -307,7 +308,7 @@ setup(void) {
isc_mem_create(&mctx);
netmgr = isc_nm_start(mctx, workers);
isc_managers_create(mctx, workers, 0, 0, &netmgr, NULL, NULL, NULL);
}
static void
@ -316,7 +317,7 @@ teardown(void) {
close(out);
}
isc_nm_destroy(&netmgr);
isc_managers_destroy(&netmgr, NULL, NULL, NULL);
isc_mem_destroy(&mctx);
if (tls_ctx) {
isc_tlsctx_free(&tls_ctx);
@ -464,8 +465,6 @@ run(void) {
}
waitforsignal();
isc_nm_closedown(netmgr);
}
int

View file

@ -17,6 +17,7 @@
#include <stdlib.h>
#include <strings.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/netaddr.h>
#include <isc/netmgr.h>
@ -188,12 +189,12 @@ setup(void) {
isc_mem_create(&mctx);
netmgr = isc_nm_start(mctx, workers);
isc_managers_create(mctx, workers, 0, 0, &netmgr, NULL, NULL, NULL);
}
static void
teardown(void) {
isc_nm_destroy(&netmgr);
isc_managers_destroy(&netmgr, NULL, NULL, NULL);
isc_mem_destroy(&mctx);
if (tls_ctx) {
isc_tlsctx_free(&tls_ctx);

View file

@ -21,6 +21,7 @@
#include <isc/hash.h>
#include <isc/hex.h>
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/net.h>
#include <isc/nonce.h>
@ -2070,10 +2071,10 @@ main(int argc, char *argv[]) {
isc_logconfig_t *lcfg;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_task_t *task;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
dns_dispatchmgr_t *dispatchmgr;
isc_task_t *task = NULL;
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
dns_dispatchmgr_t *dispatchmgr = NULL;
unsigned int attrs, attrmask;
dns_dispatch_t *dispatchvx;
dns_view_t *view;
@ -2130,17 +2131,11 @@ main(int argc, char *argv[]) {
fatal("can't choose between IPv4 and IPv6");
}
netmgr = isc_nm_start(mctx, 1);
isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr,
&socketmgr);
RUNCHECK(isc_taskmgr_create(mctx, 0, netmgr, &taskmgr));
task = NULL;
RUNCHECK(isc_task_create(taskmgr, 0, &task));
timermgr = NULL;
RUNCHECK(isc_timermgr_create(mctx, &timermgr));
socketmgr = NULL;
RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
dispatchmgr = NULL;
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY;
@ -2206,13 +2201,10 @@ main(int argc, char *argv[]) {
dns_dispatch_detach(&dispatchvx);
dns_dispatchmgr_destroy(&dispatchmgr);
isc_socketmgr_destroy(&socketmgr);
isc_timermgr_destroy(&timermgr);
isc_task_shutdown(task);
isc_task_detach(&task);
isc_taskmgr_destroy(&taskmgr);
isc_nm_destroy(&netmgr);
isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr);
dst_lib_destroy();

View file

@ -1735,6 +1735,12 @@ dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
*\li 'zone->zmgr' == NULL;
*/
isc_taskmgr_t *
dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr);
/*%
* Get the tasmkgr object attached to 'zmgr'.
*/
void
dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value);
/*%<
@ -1746,7 +1752,7 @@ dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value);
*/
uint32_t
dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr);
dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr);
/*%<
* Return the maximum number of simultaneous transfers in allowed.
*
@ -1764,7 +1770,7 @@ dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value);
*/
uint32_t
dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr);
dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr);
/*%<
* Return the number of transfers allowed per nameserver.
*

View file

@ -32,6 +32,7 @@
#include <isc/hash.h>
#include <isc/hex.h>
#include <isc/lex.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/os.h>
#include <isc/print.h>
@ -95,18 +96,10 @@ cleanup_managers(void) {
isc_task_shutdown(maintask);
isc_task_destroy(&maintask);
}
if (socketmgr != NULL) {
isc_socketmgr_destroy(&socketmgr);
}
if (taskmgr != NULL) {
isc_taskmgr_destroy(&taskmgr);
}
if (netmgr != NULL) {
isc_nm_destroy(&netmgr);
}
if (timermgr != NULL) {
isc_timermgr_destroy(&timermgr);
}
isc_managers_destroy(netmgr == NULL ? NULL : &netmgr,
taskmgr == NULL ? NULL : &taskmgr,
timermgr == NULL ? NULL : &timermgr,
socketmgr == NULL ? NULL : &socketmgr);
if (app_running) {
isc_app_finish();
}
@ -117,10 +110,8 @@ create_managers(void) {
isc_result_t result;
ncpus = isc_os_ncpus();
netmgr = isc_nm_start(dt_mctx, ncpus);
CHECK(isc_taskmgr_create(dt_mctx, 0, netmgr, &taskmgr));
CHECK(isc_timermgr_create(dt_mctx, &timermgr));
CHECK(isc_socketmgr_create(dt_mctx, &socketmgr));
isc_managers_create(dt_mctx, ncpus, 0, 0, &netmgr, &taskmgr, &timermgr,
&socketmgr);
CHECK(isc_task_create(taskmgr, 0, &maintask));
return (ISC_R_SUCCESS);

View file

@ -1389,8 +1389,9 @@ dns_zonemgr_getiolimit
dns_zonemgr_getnotifyrate
dns_zonemgr_getserialqueryrate
dns_zonemgr_getstartupnotifyrate
dns_zonemgr_getttransfersin
dns_zonemgr_getttransfersperns
dns_zonemgr_gettaskmgr
dns_zonemgr_gettransfersin
dns_zonemgr_gettransfersperns
dns_zonemgr_managezone
dns_zonemgr_releasezone
dns_zonemgr_resumexfrs

View file

@ -18478,7 +18478,7 @@ dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
}
uint32_t
dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
return (zmgr->transfersin);
@ -18492,12 +18492,19 @@ dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
}
uint32_t
dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
return (zmgr->transfersperns);
}
isc_taskmgr_t *
dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
return (zmgr->taskmgr);
}
/*
* Try to start a new incoming zone transfer to fill a quota
* slot that was just vacated.

View file

@ -11,6 +11,7 @@ libisc_la_HEADERS = \
include/isc/atomic.h \
include/isc/attributes.h \
include/isc/backtrace.h \
include/isc/barrier.h \
include/isc/base32.h \
include/isc/base64.h \
include/isc/bind9.h \
@ -46,6 +47,7 @@ libisc_la_HEADERS = \
include/isc/list.h \
include/isc/log.h \
include/isc/magic.h \
include/isc/managers.h \
include/isc/md.h \
include/isc/mem.h \
include/isc/meminfo.h \
@ -182,6 +184,7 @@ libisc_la_SOURCES = \
lex.c \
lib.c \
log.c \
managers.c \
md.c \
mem.c \
mutexblock.c \
@ -222,6 +225,10 @@ libisc_la_SOURCES = \
pthreads/thread.c \
entropy_private.h \
fsaccess_common_p.h \
task_p.h \
timer_p.h \
socket_p.h \
netmgr_p.h \
lib_p.h \
mem_p.h \
tls_p.h

View file

@ -82,6 +82,9 @@ tid(void) {
void
isc_hp_init(int max_threads) {
if (isc__hp_max_threads > max_threads) {
return;
}
isc__hp_max_threads = max_threads;
isc__hp_max_retired = max_threads * HP_MAX_HPS;
}

View file

@ -0,0 +1,37 @@
/*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <isc/util.h>
#if __SANITIZE_THREAD__ && !defined(WIN32)
#include <pthread.h>
#define isc_barrier_t pthread_barrier_t
#define isc_barrier_init(barrier, count) \
pthread_barrier_init(barrier, NULL, count)
#define isc_barrier_destroy(barrier) pthread_barrier_destroy(barrier)
#define isc_barrier_wait(barrier) pthread_barrier_wait(barrier)
#else
#include <uv.h>
#define isc_barrier_t uv_barrier_t
#define isc_barrier_init(barrier, count) uv_barrier_init(barrier, count)
#define isc_barrier_destroy(barrier) uv_barrier_destroy(barrier)
#define isc_barrier_wait(barrier) uv_barrier_wait(barrier)
#endif /* __SANITIZE_THREAD__ */

View file

@ -66,8 +66,10 @@ typedef void(isc_hp_deletefunc_t)(void *);
void
isc_hp_init(int max_threads);
/*%<
* Initialize hazard pointer constants - isc__hp_max_threads. If more threads
* will try to access hp it will assert.
* Initialize hazard pointer constants, isc__hp_max_threads and
* isc__hp_max_retired. If more threads try to access hp, it
* will assert. Calling this function repeatedly can be used
* to increase the limits, but cannot reduce them.
*/
isc_hp_t *

View file

@ -0,0 +1,30 @@
/*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <isc/netmgr.h>
#include <isc/result.h>
#include <isc/socket.h>
#include <isc/task.h>
#include <isc/timer.h>
typedef struct isc_managers isc_managers_t;
isc_result_t
isc_managers_create(isc_mem_t *mctx, size_t workers, size_t quantum,
size_t sockets, isc_nm_t **netmgrp,
isc_taskmgr_t **taskmgrp, isc_timermgr_t **timermgrp,
isc_socketmgr_t **socketmgrp);
void
isc_managers_destroy(isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp,
isc_timermgr_t **timermgrp, isc_socketmgr_t **socketmgrp);

View file

@ -68,19 +68,10 @@ typedef void (*isc_nm_opaquecb_t)(void *arg);
* callbacks.
*/
isc_nm_t *
isc_nm_start(isc_mem_t *mctx, uint32_t workers);
/*%<
* Creates a new network manager with 'workers' worker threads,
* and starts it running.
*/
void
isc_nm_attach(isc_nm_t *mgr, isc_nm_t **dst);
void
isc_nm_detach(isc_nm_t **mgr0);
void
isc_nm_destroy(isc_nm_t **mgr0);
/*%<
* Attach/detach a network manager. When all references have been
* released, the network manager is shut down, freeing all resources.
@ -88,15 +79,6 @@ isc_nm_destroy(isc_nm_t **mgr0);
* for all other references to be gone.
*/
void
isc_nm_closedown(isc_nm_t *mgr);
/*%<
* Close down all active connections, freeing associated resources;
* prevent new connections from being established. This can optionally
* be called prior to shutting down the netmgr, to stop all processing
* before shutting down the task manager.
*/
/* Return thread ID of current thread, or ISC_NETMGR_TID_UNKNOWN */
int
isc_nm_tid(void);

View file

@ -9,8 +9,7 @@
* information regarding copyright ownership.
*/
#ifndef ISC_SOCKET_H
#define ISC_SOCKET_H 1
#pragma once
/*****
***** Module Info
@ -676,42 +675,6 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
*/
/*@}*/
isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
isc_result_t
isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
unsigned int maxsocks, int nthreads);
/*%<
* Create a socket manager. If "maxsocks" is non-zero, it specifies the
* maximum number of sockets that the created manager should handle.
* isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with
* "maxsocks" being zero.
*
* Notes:
*
*\li All memory will be allocated in memory context 'mctx'.
*
* Requires:
*
*\li 'mctx' is a valid memory context.
*
*\li 'managerp' points to a NULL isc_socketmgr_t.
*
*\li 'actx' is a valid application context (for createinctx()).
*
* Ensures:
*
*\li '*managerp' is a valid isc_socketmgr_t.
*
* Returns:
*
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOMEMORY
*\li #ISC_R_UNEXPECTED
*\li #ISC_R_NOTIMPLEMENTED
*/
isc_result_t
isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp);
/*%<
@ -741,31 +704,6 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats);
* (see above).
*/
void
isc_socketmgr_destroy(isc_socketmgr_t **managerp);
/*%<
* Destroy a socket manager.
*
* Notes:
*
*\li This routine blocks until there are no sockets left in the manager,
* so if the caller holds any socket references using the manager, it
* must detach them before calling isc_socketmgr_destroy() or it will
* block forever.
*
* Requires:
*
*\li '*managerp' is a valid isc_socketmgr_t.
*
*\li All sockets managed by this manager are fully detached.
*
* Ensures:
*
*\li *managerp == NULL
*
*\li All resources used by the manager have been freed.
*/
isc_sockettype_t
isc_socket_gettype(isc_socket_t *sock);
/*%<
@ -908,5 +846,3 @@ typedef isc_result_t (*isc_socketmgrcreatefunc_t)(isc_mem_t * mctx,
isc_socketmgr_t **managerp);
ISC_LANG_ENDDECLS
#endif /* ISC_SOCKET_H */

View file

@ -9,12 +9,11 @@
* information regarding copyright ownership.
*/
#ifndef ISC_TASK_H
#define ISC_TASK_H 1
#pragma once
/*****
***** Module Info
*****/
***** Module Info
*****/
/*! \file isc/task.h
* \brief The task system provides a lightweight execution context, which is
@ -85,8 +84,8 @@
#define ISC_TASKEVENT_LASTEVENT (ISC_EVENTCLASS_TASK + 65535)
/*****
***** Tasks.
*****/
***** Tasks.
*****/
ISC_LANG_BEGINDECLS
@ -137,6 +136,12 @@ isc_task_create_bound(isc_taskmgr_t *manager, unsigned int quantum,
*\li #ISC_R_SHUTTINGDOWN
*/
void
isc_task_ready(isc_task_t *task);
/*%<
* Enqueue the task onto netmgr queue.
*/
isc_result_t
isc_task_run(isc_task_t *task);
/*%<
@ -606,15 +611,15 @@ isc_task_setprivilege(isc_task_t *task, bool priv);
* but when the task manager has been set to privileged execution mode via
* isc_taskmgr_setmode(), only tasks with the flag set will be executed,
* and all other tasks will wait until they're done. Once all privileged
* tasks have finished executing, the task manager will automatically
* return to normal execution mode and nonprivileged task can resume.
* tasks have finished executing, the task manager resumes running
* non-privileged tasks.
*
* Requires:
*\li 'task' is a valid task.
*/
bool
isc_task_privilege(isc_task_t *task);
isc_task_getprivilege(isc_task_t *task);
/*%<
* Returns the current value of the task's privilege flag.
*
@ -622,83 +627,47 @@ isc_task_privilege(isc_task_t *task);
*\li 'task' is a valid task.
*/
/*****
***** Task Manager.
*****/
isc_result_t
isc_taskmgr_create(isc_mem_t *mctx, unsigned int default_quantum, isc_nm_t *nm,
isc_taskmgr_t **managerp);
bool
isc_task_privileged(isc_task_t *task);
/*%<
* Create a new task manager.
*
* Notes:
*
*\li If 'default_quantum' is non-zero, then it will be used as the default
* quantum value when tasks are created. If zero, then an implementation
* defined default quantum will be used.
*
*\li If 'nm' is set then netmgr is paused when an exclusive task mode
* is requested.
* Returns true if the task's privilege flag is set *and* the task
* manager is currently in privileged mode.
*
* Requires:
*
*\li 'mctx' is a valid memory context.
*
*\li managerp != NULL && *managerp == NULL
*
* Ensures:
*
*\li On success, '*managerp' will be attached to the newly created task
* manager.
*
* Returns:
*
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOMEMORY
*\li #ISC_R_NOTHREADS No threads could be created.
*\li #ISC_R_UNEXPECTED An unexpected error occurred.
*\li #ISC_R_SHUTTINGDOWN The non-threaded, shared, task
* manager shutting down.
*\li 'task' is a valid task.
*/
/*****
***** Task Manager.
*****/
void
isc_taskmgr_attach(isc_taskmgr_t *, isc_taskmgr_t **);
void
isc_taskmgr_detach(isc_taskmgr_t *);
/*%<
* Attach/detach the task manager.
*/
void
isc_taskmgr_destroy(isc_taskmgr_t **managerp);
isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode);
isc_taskmgrmode_t
isc_taskmgr_mode(isc_taskmgr_t *manager);
/*%<
* Destroy '*managerp'.
* Set/get the operating mode of the task manager. Valid modes are:
*
* Notes:
*\li isc_taskmgrmode_normal
*\li isc_taskmgrmode_privileged
*
*\li Calling isc_taskmgr_destroy() will shutdown all tasks managed by
* *managerp that haven't already been shutdown. The call will block
* until all tasks have entered the done state.
*
*\li isc_taskmgr_destroy() must not be called by a task event action,
* because it would block forever waiting for the event action to
* complete. An event action that wants to cause task manager shutdown
* should request some non-event action thread of execution to do the
* shutdown, e.g. by signaling a condition variable or using
* isc_app_shutdown().
*
*\li Task manager references are not reference counted, so the caller
* must ensure that no attempt will be made to use the manager after
* isc_taskmgr_destroy() returns.
* In privileged execution mode, only tasks that have had the "privilege"
* flag set via isc_task_setprivilege() can be executed. When all such
* tasks are complete, non-privileged tasks resume running. The task calling
* this function should be in task-exclusive mode; the privileged tasks
* will be run after isc_task_endexclusive() is called.
*
* Requires:
*
*\li '*managerp' is a valid task manager.
*
*\li isc_taskmgr_destroy() has not be called previously on '*managerp'.
*
* Ensures:
*
*\li All resources used by the task manager, and any tasks it managed,
* have been freed.
*\li 'manager' is a valid task manager.
*/
void
@ -736,5 +705,3 @@ isc_taskmgr_renderjson(isc_taskmgr_t *mgr, void *tasksobj0);
#endif /* HAVE_JSON_C */
ISC_LANG_ENDDECLS
#endif /* ISC_TASK_H */

View file

@ -9,8 +9,7 @@
* information regarding copyright ownership.
*/
#ifndef ISC_TIMER_H
#define ISC_TIMER_H 1
#pragma once
/*****
***** Module Info
@ -276,58 +275,7 @@ isc_timer_gettype(isc_timer_t *timer);
*\li 'timer' to be a valid timer.
*/
isc_result_t
isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
/*%<
* Create a timer manager.
*
* Notes:
*
*\li All memory will be allocated in memory context 'mctx'.
*
* Requires:
*
*\li 'mctx' is a valid memory context.
*
*\li 'managerp' points to a NULL isc_timermgr_t.
*
* Ensures:
*
*\li '*managerp' is a valid isc_timermgr_t.
*
* Returns:
*
*\li Success
*\li No memory
*\li Unexpected error
*/
void
isc_timermgr_destroy(isc_timermgr_t **managerp);
/*%<
* Destroy a timer manager.
*
* Notes:
*
*\li This routine blocks until there are no timers left in the manager,
* so if the caller holds any timer references using the manager, it
* must detach them before calling isc_timermgr_destroy() or it will
* block forever.
*
* Requires:
*
*\li '*managerp' is a valid isc_timermgr_t.
*
* Ensures:
*
*\li *managerp == NULL
*
*\li All resources used by the manager have been freed.
*/
void
isc_timermgr_poke(isc_timermgr_t *m);
ISC_LANG_ENDDECLS
#endif /* ISC_TIMER_H */

144
lib/isc/managers.c Normal file
View file

@ -0,0 +1,144 @@
/*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <isc/hp.h>
#include <isc/managers.h>
#include <isc/util.h>
#include "netmgr_p.h"
#include "socket_p.h"
#include "task_p.h"
#include "timer_p.h"
isc_result_t
isc_managers_create(isc_mem_t *mctx, size_t workers, size_t quantum,
size_t sockets, isc_nm_t **netmgrp,
isc_taskmgr_t **taskmgrp, isc_timermgr_t **timermgrp,
isc_socketmgr_t **socketmgrp) {
isc_result_t result;
isc_nm_t *netmgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_timermgr_t *timermgr = NULL;
/*
* We have ncpus network threads, ncpus old network threads - make
* it 4x just to be on the safe side.
*/
isc_hp_init(4 * workers);
REQUIRE(netmgrp != NULL && *netmgrp == NULL);
isc__netmgr_create(mctx, workers, &netmgr);
*netmgrp = netmgr;
INSIST(netmgr != NULL);
REQUIRE(taskmgrp == NULL || *taskmgrp == NULL);
if (taskmgrp != NULL) {
INSIST(netmgr != NULL);
result = isc__taskmgr_create(mctx, quantum, netmgr, &taskmgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_taskmgr_create() failed: %s",
isc_result_totext(result));
goto fail;
}
*taskmgrp = taskmgr;
}
REQUIRE(timermgrp == NULL || *timermgrp == NULL);
if (timermgrp != NULL) {
result = isc__timermgr_create(mctx, &timermgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_timermgr_create() failed: %s",
isc_result_totext(result));
goto fail;
}
*timermgrp = timermgr;
}
REQUIRE(socketmgrp == NULL || *socketmgrp == NULL);
if (socketmgrp != NULL) {
result = isc__socketmgr_create(mctx, &socketmgr, sockets,
workers);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_socketmgr_create() failed: %s",
isc_result_totext(result));
goto fail;
}
*socketmgrp = socketmgr;
}
return (ISC_R_SUCCESS);
fail:
isc_managers_destroy(netmgrp, taskmgrp, timermgrp, socketmgrp);
return (result);
}
void
isc_managers_destroy(isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp,
isc_timermgr_t **timermgrp, isc_socketmgr_t **socketmgrp) {
/*
* If we have a taskmgr to clean up, then we must also have a netmgr.
*/
REQUIRE(taskmgrp != NULL || netmgrp == NULL);
/*
* The sequence of operations here is important:
*
* 1. Initiate shutdown of the taskmgr, sending shutdown events to
* all tasks that are not already shutting down.
*/
if (taskmgrp != NULL) {
INSIST(*taskmgrp != NULL);
isc__taskmgr_shutdown(*taskmgrp);
}
/*
* 2. Initiate shutdown of the network manager, freeing clients
* and other resources and preventing new connections, but do
* not stop processing of existing events.
*/
if (netmgrp != NULL) {
INSIST(*netmgrp != NULL);
isc__netmgr_shutdown(*netmgrp);
}
/*
* 3. Finish destruction of the task manager when all tasks
* have completed.
*/
if (taskmgrp != NULL) {
isc__taskmgr_destroy(taskmgrp);
}
/*
* 4. Finish destruction of the netmgr, and wait until all
* references have been released.
*/
if (netmgrp != NULL) {
isc__netmgr_destroy(netmgrp);
}
/*
* 5. Clean up the remaining managers.
*/
if (timermgrp != NULL) {
INSIST(*timermgrp != NULL);
isc__timermgr_destroy(timermgrp);
}
if (socketmgrp != NULL) {
INSIST(*socketmgrp != NULL);
isc__socketmgr_destroy(socketmgrp);
}
}

View file

@ -1199,7 +1199,7 @@ isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
sock->extrahandlesize = extrahandlesize;
sock->connect_timeout = timeout;
sock->result = ISC_R_DEFAULT;
sock->result = ISC_R_UNSET;
sock->connect_cb = cb;
sock->connect_cbarg = cbarg;
atomic_init(&sock->client, true);
@ -2170,8 +2170,8 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog,
isc__nmsocket_attach(sock, &sock->outer->h2.httpserver);
sock->nchildren = sock->outer->nchildren;
sock->result = ISC_R_DEFAULT;
sock->tid = isc_random_uniform(sock->nchildren);
sock->result = ISC_R_UNSET;
sock->tid = 0;
sock->fd = (uv_os_sock_t)-1;
atomic_store(&sock->listening, true);
@ -2239,8 +2239,6 @@ isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb,
void
isc__nm_http_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_httpstop_t *ievent = NULL;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_httplistener);
@ -2250,9 +2248,16 @@ isc__nm_http_stoplistening(isc_nmsocket_t *sock) {
ISC_UNREACHABLE();
}
ievent = isc__nm_get_netievent_httpstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
if (!isc__nm_in_netthread()) {
isc__netievent_httpstop_t *ievent =
isc__nm_get_netievent_httpstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
} else {
REQUIRE(isc_nm_tid() == sock->tid);
isc__netievent_httpstop_t ievent = { .sock = sock };
isc__nm_async_httpstop(NULL, (isc__netievent_t *)&ievent);
}
}
static void
@ -2294,7 +2299,6 @@ isc__nm_async_httpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
UNUSED(worker);
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
atomic_store(&sock->listening, false);
atomic_store(&sock->closing, false);

View file

@ -19,6 +19,7 @@
#include <isc/astack.h>
#include <isc/atomic.h>
#include <isc/barrier.h>
#include <isc/buffer.h>
#include <isc/condition.h>
#include <isc/magic.h>
@ -39,6 +40,8 @@
#include "uv-compat.h"
#define ISC_NETMGR_QUANTUM_DEFAULT 128
#define ISC_NETMGR_TID_UNKNOWN -1
/* Must be different from ISC_NETMGR_TID_UNKNOWN */
@ -172,7 +175,6 @@ typedef struct isc__networker {
uv_async_t async; /* async channel to send
* data to this networker */
isc_mutex_t lock;
isc_condition_t cond;
bool paused;
bool finished;
isc_thread_t thread;
@ -183,11 +185,14 @@ typedef struct isc__networker {
* used for listening etc.
* can be processed while
* worker is paused */
isc_condition_t cond_prio;
isc_refcount_t references;
atomic_int_fast64_t pktcount;
char *recvbuf;
char *sendbuf;
bool recvbuf_inuse;
unsigned int quantum;
} isc__networker_t;
/*
@ -244,7 +249,6 @@ typedef enum isc__netievent_type {
netievent_udpclose,
netievent_udpsend,
netievent_udpread,
netievent_udpstop,
netievent_udpcancel,
netievent_tcpconnect,
@ -253,7 +257,6 @@ typedef enum isc__netievent_type {
netievent_tcpstartread,
netievent_tcppauseread,
netievent_tcpaccept,
netievent_tcpstop,
netievent_tcpcancel,
netievent_tcpdnsaccept,
@ -262,7 +265,6 @@ typedef enum isc__netievent_type {
netievent_tcpdnssend,
netievent_tcpdnsread,
netievent_tcpdnscancel,
netievent_tcpdnsstop,
netievent_tlsclose,
netievent_tlssend,
@ -277,12 +279,10 @@ typedef enum isc__netievent_type {
netievent_tlsdnssend,
netievent_tlsdnsread,
netievent_tlsdnscancel,
netievent_tlsdnsstop,
netievent_tlsdnscycle,
netievent_tlsdnsshutdown,
netievent_httpclose,
netievent_httpstop,
netievent_httpsend,
netievent_shutdown,
@ -296,19 +296,26 @@ typedef enum isc__netievent_type {
netievent_task,
netievent_privilegedtask,
netievent_prio = 0xff, /* event type values higher than this
* will be treated as high-priority
* events, which can be processed
* while the netmgr is paused.
*/
/*
* event type values higher than this will be treated
* as high-priority events, which can be processed
* while the netmgr is pausing or paused.
*/
netievent_prio = 0xff,
netievent_udplisten,
netievent_udpstop,
netievent_tcplisten,
netievent_tcpstop,
netievent_tcpdnslisten,
netievent_tcpdnsstop,
netievent_tlsdnslisten,
netievent_tlsdnsstop,
netievent_httpstop,
netievent_resume,
netievent_detach,
netievent_close,
} isc__netievent_type;
typedef union {
@ -653,7 +660,7 @@ struct isc_nm {
int magic;
isc_refcount_t references;
isc_mem_t *mctx;
uint32_t nworkers;
int nworkers;
isc_mutex_t lock;
isc_condition_t wkstatecond;
isc_condition_t wkpausecond;
@ -668,7 +675,7 @@ struct isc_nm {
isc_mutex_t evlock;
uint_fast32_t workers_running;
uint_fast32_t workers_paused;
atomic_uint_fast32_t workers_paused;
atomic_uint_fast32_t maxudp;
atomic_bool paused;
@ -699,6 +706,9 @@ struct isc_nm {
atomic_uint_fast32_t keepalive;
atomic_uint_fast32_t advertised;
isc_barrier_t pausing;
isc_barrier_t resuming;
#ifdef NETMGR_TRACE
ISC_LIST(isc_nmsocket_t) active_sockets;
#endif
@ -833,6 +843,9 @@ struct isc_nmsocket {
/*% Self socket */
isc_nmsocket_t *self;
isc_barrier_t startlistening;
isc_barrier_t stoplistening;
/*% TLS stuff */
struct tls {
isc_tls_t *tls;
@ -927,7 +940,7 @@ struct isc_nmsocket {
/* Atomic */
/*% Number of running (e.g. listening) child sockets */
uint_fast32_t rchildren;
atomic_uint_fast32_t rchildren;
/*%
* Socket is active if it's listening, working, etc. If it's

View file

@ -15,6 +15,7 @@
#include <isc/atomic.h>
#include <isc/backtrace.h>
#include <isc/barrier.h>
#include <isc/buffer.h>
#include <isc/condition.h>
#include <isc/errno.h>
@ -37,6 +38,7 @@
#include <isc/util.h>
#include "netmgr-int.h"
#include "netmgr_p.h"
#include "openssl_shim.h"
#include "uv-compat.h"
@ -134,15 +136,29 @@ nm_thread(isc_threadarg_t worker0);
static void
async_cb(uv_async_t *handle);
static bool
process_queue(isc__networker_t *worker, isc_queue_t *queue);
process_netievent(isc__networker_t *worker, isc__netievent_t *ievent);
static bool
process_priority_queue(isc__networker_t *worker);
process_queue(isc__networker_t *worker, isc_queue_t *queue,
unsigned int *quantump);
static void
process_privilege_queue(isc__networker_t *worker);
static void
process_tasks_queue(isc__networker_t *worker);
static void
process_normal_queue(isc__networker_t *worker);
wait_for_priority_queue(isc__networker_t *worker);
static bool
process_priority_queue(isc__networker_t *worker, unsigned int *quantump);
static bool
process_privilege_queue(isc__networker_t *worker, unsigned int *quantump);
static bool
process_task_queue(isc__networker_t *worker, unsigned int *quantump);
static bool
process_normal_queue(isc__networker_t *worker, unsigned int *quantump);
#define drain_priority_queue(worker) \
(void)process_priority_queue(worker, &(unsigned int){ UINT_MAX })
#define drain_privilege_queue(worker) \
(void)process_privilege_queue(worker, &(unsigned int){ UINT_MAX })
#define drain_task_queue(worker) \
(void)process_task_queue(worker, &(unsigned int){ UINT_MAX })
#define drain_normal_queue(worker) \
(void)process_normal_queue(worker, &(unsigned int){ UINT_MAX })
static void
isc__nm_async_stop(isc__networker_t *worker, isc__netievent_t *ev0);
@ -206,8 +222,8 @@ isc__nm_winsock_destroy(void) {
}
#endif /* WIN32 */
isc_nm_t *
isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
void
isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
isc_nm_t *mgr = NULL;
char name[32];
@ -227,6 +243,7 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
isc_refcount_init(&mgr->references, 1);
atomic_init(&mgr->maxudp, 0);
atomic_init(&mgr->interlocked, ISC_NETMGR_NON_INTERLOCKED);
atomic_init(&mgr->workers_paused, 0);
#ifdef NETMGR_TRACE
ISC_LIST_INIT(mgr->active_sockets);
@ -256,6 +273,9 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
isc_mempool_associatelock(mgr->evpool, &mgr->evlock);
isc_mempool_setfillcount(mgr->evpool, 32);
isc_barrier_init(&mgr->pausing, workers);
isc_barrier_init(&mgr->resuming, workers);
mgr->workers = isc_mem_get(mctx, workers * sizeof(isc__networker_t));
for (size_t i = 0; i < workers; i++) {
int r;
@ -263,6 +283,7 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
*worker = (isc__networker_t){
.mgr = mgr,
.id = i,
.quantum = ISC_NETMGR_QUANTUM_DEFAULT,
};
r = uv_loop_init(&worker->loop);
@ -274,12 +295,13 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
RUNTIME_CHECK(r == 0);
isc_mutex_init(&worker->lock);
isc_condition_init(&worker->cond);
worker->ievents = isc_queue_new(mgr->mctx, 128);
worker->ievents_priv = isc_queue_new(mgr->mctx, 128);
worker->ievents_task = isc_queue_new(mgr->mctx, 128);
worker->ievents_priv = isc_queue_new(mgr->mctx, 128);
worker->ievents_prio = isc_queue_new(mgr->mctx, 128);
isc_condition_init(&worker->cond_prio);
worker->recvbuf = isc_mem_get(mctx, ISC_NETMGR_RECVBUF_SIZE);
worker->sendbuf = isc_mem_get(mctx, ISC_NETMGR_SENDBUF_SIZE);
@ -296,7 +318,7 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
}
mgr->magic = NM_MAGIC;
return (mgr);
*netmgrp = mgr;
}
/*
@ -314,7 +336,7 @@ nm_destroy(isc_nm_t **mgr0) {
mgr->magic = 0;
for (size_t i = 0; i < mgr->nworkers; i++) {
for (int i = 0; i < mgr->nworkers; i++) {
isc__networker_t *worker = &mgr->workers[i];
isc__netievent_t *event = isc__nm_get_netievent_stop(mgr);
isc__nm_enqueue_ievent(worker, event);
@ -326,7 +348,7 @@ nm_destroy(isc_nm_t **mgr0) {
}
UNLOCK(&mgr->lock);
for (size_t i = 0; i < mgr->nworkers; i++) {
for (int i = 0; i < mgr->nworkers; i++) {
isc__networker_t *worker = &mgr->workers[i];
isc__netievent_t *ievent = NULL;
int r;
@ -348,6 +370,7 @@ nm_destroy(isc_nm_t **mgr0) {
{
isc_mempool_put(mgr->evpool, ievent);
}
isc_condition_destroy(&worker->cond_prio);
r = uv_loop_close(&worker->loop);
INSIST(r == 0);
@ -357,7 +380,6 @@ nm_destroy(isc_nm_t **mgr0) {
isc_queue_destroy(worker->ievents_task);
isc_queue_destroy(worker->ievents_prio);
isc_mutex_destroy(&worker->lock);
isc_condition_destroy(&worker->cond);
isc_mem_put(mgr->mctx, worker->sendbuf,
ISC_NETMGR_SENDBUF_SIZE);
@ -370,6 +392,9 @@ nm_destroy(isc_nm_t **mgr0) {
isc_stats_detach(&mgr->stats);
}
isc_barrier_destroy(&mgr->resuming);
isc_barrier_destroy(&mgr->pausing);
isc_condition_destroy(&mgr->wkstatecond);
isc_condition_destroy(&mgr->wkpausecond);
isc_mutex_destroy(&mgr->lock);
@ -389,34 +414,70 @@ nm_destroy(isc_nm_t **mgr0) {
#endif /* WIN32 */
}
static void
enqueue_pause(isc__networker_t *worker) {
isc__netievent_pause_t *event =
isc__nm_get_netievent_pause(worker->mgr);
isc__nm_enqueue_ievent(worker, (isc__netievent_t *)event);
}
static void
isc__nm_async_pause(isc__networker_t *worker, isc__netievent_t *ev0) {
UNUSED(ev0);
REQUIRE(worker->paused == false);
worker->paused = true;
uv_stop(&worker->loop);
}
void
isc_nm_pause(isc_nm_t *mgr) {
REQUIRE(VALID_NM(mgr));
uint_fast32_t pausing = 0;
REQUIRE(!atomic_load(&mgr->paused));
isc__nm_acquire_interlocked_force(mgr);
for (size_t i = 0; i < mgr->nworkers; i++) {
if (isc__nm_in_netthread()) {
REQUIRE(isc_nm_tid() == 0);
}
for (int i = 0; i < mgr->nworkers; i++) {
isc__networker_t *worker = &mgr->workers[i];
if (i != (size_t)isc_nm_tid()) {
isc__netievent_resume_t *event =
isc__nm_get_netievent_pause(mgr);
pausing++;
isc__nm_enqueue_ievent(worker,
(isc__netievent_t *)event);
} else {
if (i == isc_nm_tid()) {
isc__nm_async_pause(worker, NULL);
} else {
enqueue_pause(worker);
}
}
if (isc__nm_in_netthread()) {
atomic_fetch_add(&mgr->workers_paused, 1);
isc_barrier_wait(&mgr->pausing);
}
LOCK(&mgr->lock);
while (mgr->workers_paused != pausing) {
while (atomic_load(&mgr->workers_paused) != mgr->workers_running) {
WAIT(&mgr->wkstatecond, &mgr->lock);
}
UNLOCK(&mgr->lock);
REQUIRE(atomic_compare_exchange_strong(&mgr->paused, &(bool){ false },
true));
UNLOCK(&mgr->lock);
}
static void
enqueue_resume(isc__networker_t *worker) {
isc__netievent_resume_t *event =
isc__nm_get_netievent_resume(worker->mgr);
isc__nm_enqueue_ievent(worker, (isc__netievent_t *)event);
}
static void
isc__nm_async_resume(isc__networker_t *worker, isc__netievent_t *ev0) {
UNUSED(ev0);
REQUIRE(worker->paused == true);
worker->paused = false;
}
void
@ -424,26 +485,36 @@ isc_nm_resume(isc_nm_t *mgr) {
REQUIRE(VALID_NM(mgr));
REQUIRE(atomic_load(&mgr->paused));
for (size_t i = 0; i < mgr->nworkers; i++) {
if (isc__nm_in_netthread()) {
REQUIRE(isc_nm_tid() == 0);
drain_priority_queue(&mgr->workers[isc_nm_tid()]);
}
for (int i = 0; i < mgr->nworkers; i++) {
isc__networker_t *worker = &mgr->workers[i];
if (i != (size_t)isc_nm_tid()) {
isc__netievent_resume_t *event =
isc__nm_get_netievent_resume(mgr);
isc__nm_enqueue_ievent(worker,
(isc__netievent_t *)event);
} else {
if (i == isc_nm_tid()) {
isc__nm_async_resume(worker, NULL);
} else {
enqueue_resume(worker);
}
}
if (isc__nm_in_netthread()) {
drain_privilege_queue(&mgr->workers[isc_nm_tid()]);
atomic_fetch_sub(&mgr->workers_paused, 1);
isc_barrier_wait(&mgr->resuming);
}
LOCK(&mgr->lock);
while (mgr->workers_paused != 0) {
while (atomic_load(&mgr->workers_paused) != 0) {
WAIT(&mgr->wkstatecond, &mgr->lock);
}
UNLOCK(&mgr->lock);
REQUIRE(atomic_compare_exchange_strong(&mgr->paused, &(bool){ true },
false));
BROADCAST(&mgr->wkpausecond);
UNLOCK(&mgr->lock);
isc__nm_drop_interlocked(mgr);
}
@ -473,11 +544,11 @@ isc_nm_detach(isc_nm_t **mgr0) {
}
void
isc_nm_closedown(isc_nm_t *mgr) {
isc__netmgr_shutdown(isc_nm_t *mgr) {
REQUIRE(VALID_NM(mgr));
atomic_store(&mgr->closing, true);
for (size_t i = 0; i < mgr->nworkers; i++) {
for (int i = 0; i < mgr->nworkers; i++) {
isc__netievent_t *event = NULL;
event = isc__nm_get_netievent_shutdown(mgr);
isc__nm_enqueue_ievent(&mgr->workers[i], event);
@ -485,19 +556,18 @@ isc_nm_closedown(isc_nm_t *mgr) {
}
void
isc_nm_destroy(isc_nm_t **mgr0) {
isc__netmgr_destroy(isc_nm_t **netmgrp) {
isc_nm_t *mgr = NULL;
int counter = 0;
REQUIRE(mgr0 != NULL);
REQUIRE(VALID_NM(*mgr0));
REQUIRE(VALID_NM(*netmgrp));
mgr = *mgr0;
mgr = *netmgrp;
/*
* Close active connections.
*/
isc_nm_closedown(mgr);
isc__netmgr_shutdown(mgr);
/*
* Wait for the manager to be dereferenced elsewhere.
@ -524,7 +594,7 @@ isc_nm_destroy(isc_nm_t **mgr0) {
/*
* Detach final reference.
*/
isc_nm_detach(mgr0);
isc_nm_detach(netmgrp);
}
void
@ -615,43 +685,29 @@ nm_thread(isc_threadarg_t worker0) {
if (worker->paused) {
INSIST(atomic_load(&mgr->interlocked) != isc_nm_tid());
/*
* We need to lock the worker first; otherwise
* isc_nm_resume() might slip in before WAIT() in
* the while loop starts, then the signal never
* gets delivered and we are stuck forever in the
* paused loop.
*/
LOCK(&worker->lock);
LOCK(&mgr->lock);
mgr->workers_paused++;
SIGNAL(&mgr->wkstatecond);
UNLOCK(&mgr->lock);
atomic_fetch_add(&mgr->workers_paused, 1);
if (isc_barrier_wait(&mgr->pausing) != 0) {
LOCK(&mgr->lock);
SIGNAL(&mgr->wkstatecond);
UNLOCK(&mgr->lock);
}
while (worker->paused) {
WAIT(&worker->cond, &worker->lock);
UNLOCK(&worker->lock);
(void)process_priority_queue(worker);
LOCK(&worker->lock);
wait_for_priority_queue(worker);
}
LOCK(&mgr->lock);
mgr->workers_paused--;
SIGNAL(&mgr->wkstatecond);
UNLOCK(&mgr->lock);
UNLOCK(&worker->lock);
/*
* All workers must run the privileged event
* All workers must drain the privileged event
* queue before we resume from pause.
*/
process_privilege_queue(worker);
drain_privilege_queue(worker);
LOCK(&mgr->lock);
while (atomic_load(&mgr->paused)) {
WAIT(&mgr->wkpausecond, &mgr->lock);
atomic_fetch_sub(&mgr->workers_paused, 1);
if (isc_barrier_wait(&mgr->resuming) != 0) {
LOCK(&mgr->lock);
SIGNAL(&mgr->wkstatecond);
UNLOCK(&mgr->lock);
}
UNLOCK(&mgr->lock);
}
if (r == 0) {
@ -660,16 +716,6 @@ nm_thread(isc_threadarg_t worker0) {
}
INSIST(!worker->finished);
/*
* We've fully resumed from pause. Drain the normal
* asynchronous event queues before resuming the uv_run()
* loop. (This is not strictly necessary, it just ensures
* that all pending events are processed before another
* pause can slip in.)
*/
process_tasks_queue(worker);
process_normal_queue(worker);
}
/*
@ -677,8 +723,8 @@ nm_thread(isc_threadarg_t worker0) {
* (they may include shutdown events) but do not process
* the netmgr event queue.
*/
process_privilege_queue(worker);
process_tasks_queue(worker);
drain_privilege_queue(worker);
drain_task_queue(worker);
LOCK(&mgr->lock);
mgr->workers_running--;
@ -688,6 +734,23 @@ nm_thread(isc_threadarg_t worker0) {
return ((isc_threadresult_t)0);
}
static bool
process_all_queues(isc__networker_t *worker, unsigned int quantum) {
/*
* The queue processing functions will return false when the
* system is pausing or stopping, or if we have completed
* 'quantum' events.
*
* We don't want to proceed to a new queue until the previous one
* has been fully drained, so whenever one queue is interrupted,
* we skip all the later ones.
*/
return (process_priority_queue(worker, &quantum) &&
process_privilege_queue(worker, &quantum) &&
process_task_queue(worker, &quantum) &&
process_normal_queue(worker, &quantum));
}
/*
* async_cb() is a universal callback for 'async' events sent to event loop.
* It's the only way to safely pass data to the libuv event loop. We use a
@ -697,18 +760,14 @@ nm_thread(isc_threadarg_t worker0) {
static void
async_cb(uv_async_t *handle) {
isc__networker_t *worker = (isc__networker_t *)handle->loop->data;
unsigned int quantum = worker->quantum;
/*
* process_priority_queue() returns false when pausing or stopping,
* so we don't want to process the other queues in that case.
*/
if (!process_priority_queue(worker)) {
return;
if (!process_all_queues(worker, quantum)) {
/* If we didn't process all the events, we need to enqueue
* async_cb to be run in the next iteration of the uv_loop
*/
uv_async_send(handle);
}
process_privilege_queue(worker);
process_tasks_queue(worker);
process_normal_queue(worker);
}
static void
@ -719,23 +778,6 @@ isc__nm_async_stop(isc__networker_t *worker, isc__netievent_t *ev0) {
uv_close((uv_handle_t *)&worker->async, NULL);
}
static void
isc__nm_async_pause(isc__networker_t *worker, isc__netievent_t *ev0) {
UNUSED(ev0);
REQUIRE(worker->paused == false);
worker->paused = true;
uv_stop(&worker->loop);
}
static void
isc__nm_async_resume(isc__networker_t *worker, isc__netievent_t *ev0) {
UNUSED(ev0);
REQUIRE(worker->paused == true);
worker->paused = false;
}
void
isc_nm_task_enqueue(isc_nm_t *nm, isc_task_t *task, int threadid) {
isc__netievent_t *event = NULL;
@ -750,7 +792,7 @@ isc_nm_task_enqueue(isc_nm_t *nm, isc_task_t *task, int threadid) {
worker = &nm->workers[tid];
if (isc_task_privilege(task)) {
if (isc_task_privileged(task)) {
event = (isc__netievent_t *)
isc__nm_get_netievent_privilegedtask(nm, task);
} else {
@ -775,8 +817,7 @@ isc__nm_async_task(isc__networker_t *worker, isc__netievent_t *ev0) {
switch (result) {
case ISC_R_QUOTA:
isc_nm_task_enqueue(worker->mgr, (isc_task_t *)ievent->task,
isc_nm_tid());
isc_task_ready(ievent->task);
return;
case ISC_R_SUCCESS:
return;
@ -786,24 +827,52 @@ isc__nm_async_task(isc__networker_t *worker, isc__netievent_t *ev0) {
}
}
static void
wait_for_priority_queue(isc__networker_t *worker) {
isc_queue_t *queue = worker->ievents_prio;
isc_condition_t *cond = &worker->cond_prio;
bool wait_for_work = true;
while (true) {
isc__netievent_t *ievent;
LOCK(&worker->lock);
ievent = (isc__netievent_t *)isc_queue_dequeue(queue);
if (wait_for_work) {
while (ievent == NULL) {
WAIT(cond, &worker->lock);
ievent = (isc__netievent_t *)isc_queue_dequeue(
queue);
}
}
UNLOCK(&worker->lock);
wait_for_work = false;
if (ievent == NULL) {
return;
}
(void)process_netievent(worker, ievent);
}
}
static bool
process_priority_queue(isc__networker_t *worker) {
return (process_queue(worker, worker->ievents_prio));
process_priority_queue(isc__networker_t *worker, unsigned int *quantump) {
return (process_queue(worker, worker->ievents_prio, quantump));
}
static void
process_privilege_queue(isc__networker_t *worker) {
(void)process_queue(worker, worker->ievents_priv);
static bool
process_privilege_queue(isc__networker_t *worker, unsigned int *quantump) {
return (process_queue(worker, worker->ievents_priv, quantump));
}
static void
process_tasks_queue(isc__networker_t *worker) {
(void)process_queue(worker, worker->ievents_task);
static bool
process_task_queue(isc__networker_t *worker, unsigned int *quantump) {
return (process_queue(worker, worker->ievents_task, quantump));
}
static void
process_normal_queue(isc__networker_t *worker) {
(void)process_queue(worker, worker->ievents);
static bool
process_normal_queue(isc__networker_t *worker, unsigned int *quantump) {
return (process_queue(worker, worker->ievents, quantump));
}
/*
@ -905,16 +974,27 @@ process_netievent(isc__networker_t *worker, isc__netievent_t *ievent) {
}
static bool
process_queue(isc__networker_t *worker, isc_queue_t *queue) {
isc__netievent_t *ievent = NULL;
process_queue(isc__networker_t *worker, isc_queue_t *queue,
unsigned int *quantump) {
while (*quantump > 0) {
isc__netievent_t *ievent =
(isc__netievent_t *)isc_queue_dequeue(queue);
if (ievent == NULL) {
/* We fully drained this queue */
return (true);
}
(*quantump)--;
while ((ievent = (isc__netievent_t *)isc_queue_dequeue(queue)) != NULL)
{
if (!process_netievent(worker, ievent)) {
/* Netievent told us to stop */
return (false);
}
}
return (true);
/* No more quantum */
return (false);
}
void *
@ -1017,7 +1097,7 @@ isc__nm_enqueue_ievent(isc__networker_t *worker, isc__netievent_t *event) {
*/
LOCK(&worker->lock);
isc_queue_enqueue(worker->ievents_prio, (uintptr_t)event);
SIGNAL(&worker->cond);
SIGNAL(&worker->cond_prio);
UNLOCK(&worker->lock);
} else if (event->type == netievent_privilegedtask) {
isc_queue_enqueue(worker->ievents_priv, (uintptr_t)event);
@ -1105,7 +1185,14 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
}
/*
* This was a parent socket; free the children.
* This was a parent socket: destroy the listening
* barriers that synchronized the children.
*/
isc_barrier_destroy(&sock->startlistening);
isc_barrier_destroy(&sock->stoplistening);
/*
* Now free them.
*/
isc_mem_put(sock->mgr->mctx, sock->children,
sock->nchildren * sizeof(*sock));
@ -1152,7 +1239,6 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
isc_mem_free(sock->mgr->mctx, sock->ah_frees);
isc_mem_free(sock->mgr->mctx, sock->ah_handles);
isc_mutex_destroy(&sock->lock);
isc_condition_destroy(&sock->cond);
isc_condition_destroy(&sock->scond);
isc__nm_tls_cleanup_data(sock);
isc__nm_http_cleanup_data(sock);
@ -1399,7 +1485,6 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
}
isc_mutex_init(&sock->lock);
isc_condition_init(&sock->cond);
isc_condition_init(&sock->scond);
isc_refcount_init(&sock->references, 1);
@ -2690,16 +2775,25 @@ isc__nm_async_shutdown(isc__networker_t *worker, isc__netievent_t *ev0) {
bool
isc__nm_acquire_interlocked(isc_nm_t *mgr) {
if (!isc__nm_in_netthread()) {
return (false);
}
LOCK(&mgr->lock);
bool success = atomic_compare_exchange_strong(
&mgr->interlocked, &(int){ ISC_NETMGR_NON_INTERLOCKED },
isc_nm_tid());
UNLOCK(&mgr->lock);
return (success);
}
void
isc__nm_drop_interlocked(isc_nm_t *mgr) {
if (!isc__nm_in_netthread()) {
return;
}
LOCK(&mgr->lock);
int tid = atomic_exchange(&mgr->interlocked,
ISC_NETMGR_NON_INTERLOCKED);
@ -2710,6 +2804,10 @@ isc__nm_drop_interlocked(isc_nm_t *mgr) {
void
isc__nm_acquire_interlocked_force(isc_nm_t *mgr) {
if (!isc__nm_in_netthread()) {
return;
}
LOCK(&mgr->lock);
while (!atomic_compare_exchange_strong(
&mgr->interlocked, &(int){ ISC_NETMGR_NON_INTERLOCKED },

View file

@ -14,6 +14,7 @@
#include <uv.h>
#include <isc/atomic.h>
#include <isc/barrier.h>
#include <isc/buffer.h>
#include <isc/condition.h>
#include <isc/errno.h>
@ -116,7 +117,7 @@ failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult) {
static isc_result_t
tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
isc__networker_t *worker = NULL;
isc_result_t result = ISC_R_DEFAULT;
isc_result_t result = ISC_R_UNSET;
int r;
REQUIRE(VALID_NMSOCK(sock));
@ -302,7 +303,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
sock->extrahandlesize = extrahandlesize;
sock->connect_timeout = timeout;
sock->result = ISC_R_DEFAULT;
sock->result = ISC_R_UNSET;
sock->fd = (uv_os_sock_t)-1;
atomic_init(&sock->client, true);
@ -344,7 +345,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
(isc__netievent_t *)ievent);
}
LOCK(&sock->lock);
while (sock->result == ISC_R_DEFAULT) {
while (sock->result == ISC_R_UNSET) {
WAIT(&sock->cond, &sock->lock);
}
atomic_store(&sock->active, true);
@ -375,6 +376,47 @@ isc__nm_tcp_lb_socket(sa_family_t sa_family) {
return (sock);
}
static void
start_tcp_child(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nmsocket_t *sock,
uv_os_sock_t fd, int tid) {
isc__netievent_tcplisten_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[tid];
isc__nmsocket_init(csock, mgr, isc_nm_tcpsocket, iface);
csock->parent = sock;
csock->accept_cb = sock->accept_cb;
csock->accept_cbarg = sock->accept_cbarg;
csock->extrahandlesize = sock->extrahandlesize;
csock->backlog = sock->backlog;
csock->tid = tid;
/*
* We don't attach to quota, just assign - to avoid
* increasing quota unnecessarily.
*/
csock->pquota = sock->pquota;
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
UNUSED(fd);
csock->fd = isc__nm_tcp_lb_socket(iface->addr.type.sa.sa_family);
#else
csock->fd = dup(fd);
#endif
REQUIRE(csock->fd >= 0);
ievent = isc__nm_get_netievent_tcplisten(mgr, csock);
isc__nm_maybe_enqueue_ievent(&mgr->workers[tid],
(isc__netievent_t *)ievent);
}
static void
enqueue_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_tcpstop_t *ievent =
isc__nm_get_netievent_tcpstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
isc_result_t
isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
@ -382,18 +424,15 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
isc_nmsocket_t **sockp) {
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *sock = NULL;
sa_family_t sa_family = iface->addr.type.sa.sa_family;
size_t children_size = 0;
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
uv_os_sock_t fd = -1;
#endif
REQUIRE(VALID_NM(mgr));
sock = isc_mem_get(mgr->mctx, sizeof(*sock));
isc__nmsocket_init(sock, mgr, isc_nm_tcplistener, iface);
sock->rchildren = 0;
atomic_init(&sock->rchildren, 0);
#if defined(WIN32)
sock->nchildren = 1;
#else
@ -403,42 +442,32 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
sock->children = isc_mem_get(mgr->mctx, children_size);
memset(sock->children, 0, children_size);
sock->result = ISC_R_DEFAULT;
sock->tid = isc_random_uniform(sock->nchildren);
sock->result = ISC_R_UNSET;
sock->accept_cb = accept_cb;
sock->accept_cbarg = accept_cbarg;
sock->extrahandlesize = extrahandlesize;
sock->backlog = backlog;
sock->pquota = quota;
sock->tid = 0;
sock->fd = -1;
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
fd = isc__nm_tcp_lb_socket(sa_family);
fd = isc__nm_tcp_lb_socket(iface->addr.type.sa.sa_family);
#endif
isc_barrier_init(&sock->startlistening, sock->nchildren);
for (size_t i = 0; i < sock->nchildren; i++) {
isc__netievent_tcplisten_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[i];
if ((int)i == isc_nm_tid()) {
continue;
}
start_tcp_child(mgr, iface, sock, fd, i);
}
isc__nmsocket_init(csock, mgr, isc_nm_tcpsocket, iface);
csock->parent = sock;
csock->accept_cb = accept_cb;
csock->accept_cbarg = accept_cbarg;
csock->extrahandlesize = extrahandlesize;
csock->backlog = backlog;
csock->tid = i;
/*
* We don't attach to quota, just assign - to avoid
* increasing quota unnecessarily.
*/
csock->pquota = quota;
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
csock->fd = isc__nm_tcp_lb_socket(sa_family);
#else
csock->fd = dup(fd);
#endif
REQUIRE(csock->fd >= 0);
ievent = isc__nm_get_netievent_tcplisten(mgr, csock);
isc__nm_maybe_enqueue_ievent(&mgr->workers[i],
(isc__netievent_t *)ievent);
if (isc__nm_in_netthread()) {
start_tcp_child(mgr, iface, sock, fd, isc_nm_tid());
}
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
@ -446,21 +475,21 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
#endif
LOCK(&sock->lock);
while (sock->rchildren != sock->nchildren) {
while (atomic_load(&sock->rchildren) != sock->nchildren) {
WAIT(&sock->cond, &sock->lock);
}
result = sock->result;
atomic_store(&sock->active, true);
BROADCAST(&sock->scond);
UNLOCK(&sock->lock);
INSIST(result != ISC_R_DEFAULT);
INSIST(result != ISC_R_UNSET);
if (result == ISC_R_SUCCESS) {
REQUIRE(sock->rchildren == sock->nchildren);
REQUIRE(atomic_load(&sock->rchildren) == sock->nchildren);
*sockp = sock;
} else {
atomic_store(&sock->active, false);
isc__nm_tcp_stoplistening(sock);
enqueue_stoplistening(sock);
isc_nmsocket_close(&sock);
}
@ -565,16 +594,14 @@ done:
sock->pquota = NULL;
}
sock->parent->rchildren += 1;
if (sock->parent->result == ISC_R_DEFAULT) {
atomic_fetch_add(&sock->parent->rchildren, 1);
if (sock->parent->result == ISC_R_UNSET) {
sock->parent->result = result;
}
SIGNAL(&sock->parent->cond);
if (!atomic_load(&sock->parent->active)) {
WAIT(&sock->parent->scond, &sock->parent->lock);
}
INSIST(atomic_load(&sock->parent->active));
UNLOCK(&sock->parent->lock);
isc_barrier_wait(&sock->parent->startlistening);
}
static void
@ -619,14 +646,6 @@ done:
}
}
static void
enqueue_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_tcpstop_t *ievent =
isc__nm_get_netievent_tcpstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
void
isc__nm_tcp_stoplistening(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
@ -637,7 +656,12 @@ isc__nm_tcp_stoplistening(isc_nmsocket_t *sock) {
INSIST(0);
ISC_UNREACHABLE();
}
enqueue_stoplistening(sock);
if (!isc__nm_in_netthread()) {
enqueue_stoplistening(sock);
} else {
stop_tcp_parent(sock);
}
}
void
@ -1194,8 +1218,6 @@ timer_close_cb(uv_handle_t *handle) {
static void
stop_tcp_child(isc_nmsocket_t *sock) {
bool last_child = false;
REQUIRE(sock->type == isc_nm_tcpsocket);
REQUIRE(sock->tid == isc_nm_tid());
@ -1206,33 +1228,42 @@ stop_tcp_child(isc_nmsocket_t *sock) {
tcp_close_direct(sock);
LOCK(&sock->parent->lock);
sock->parent->rchildren -= 1;
last_child = (sock->parent->rchildren == 0);
UNLOCK(&sock->parent->lock);
atomic_fetch_sub(&sock->parent->rchildren, 1);
if (last_child) {
atomic_store(&sock->parent->closed, true);
isc__nmsocket_prep_destroy(sock->parent);
}
isc_barrier_wait(&sock->parent->stoplistening);
}
static void
stop_tcp_parent(isc_nmsocket_t *sock) {
isc_nmsocket_t *csock = NULL;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(sock->type == isc_nm_tcplistener);
isc_barrier_init(&sock->stoplistening, sock->nchildren);
for (size_t i = 0; i < sock->nchildren; i++) {
isc__netievent_tcpstop_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[i];
csock = &sock->children[i];
REQUIRE(VALID_NMSOCK(csock));
atomic_store(&csock->active, false);
if ((int)i == isc_nm_tid()) {
/*
* We need to schedule closing the other sockets first
*/
continue;
}
ievent = isc__nm_get_netievent_tcpstop(sock->mgr, csock);
isc__nm_enqueue_ievent(&sock->mgr->workers[csock->tid],
(isc__netievent_t *)ievent);
atomic_store(&csock->active, false);
enqueue_stoplistening(csock);
}
csock = &sock->children[isc_nm_tid()];
atomic_store(&csock->active, false);
stop_tcp_child(csock);
atomic_store(&sock->closed, true);
isc__nmsocket_prep_destroy(sock);
}
static void

View file

@ -14,6 +14,7 @@
#include <uv.h>
#include <isc/atomic.h>
#include <isc/barrier.h>
#include <isc/buffer.h>
#include <isc/condition.h>
#include <isc/errno.h>
@ -85,7 +86,7 @@ stop_tcpdns_child(isc_nmsocket_t *sock);
static isc_result_t
tcpdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
isc__networker_t *worker = NULL;
isc_result_t result = ISC_R_DEFAULT;
isc_result_t result = ISC_R_UNSET;
int r;
REQUIRE(VALID_NMSOCK(sock));
@ -269,7 +270,7 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
sock->extrahandlesize = extrahandlesize;
sock->connect_timeout = timeout;
sock->result = ISC_R_DEFAULT;
sock->result = ISC_R_UNSET;
atomic_init(&sock->client, true);
req = isc__nm_uvreq_get(mgr, sock);
@ -311,7 +312,7 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
}
LOCK(&sock->lock);
while (sock->result == ISC_R_DEFAULT) {
while (sock->result == ISC_R_UNSET) {
WAIT(&sock->cond, &sock->lock);
}
atomic_store(&sock->active, true);
@ -342,6 +343,48 @@ isc__nm_tcpdns_lb_socket(sa_family_t sa_family) {
return (sock);
}
static void
enqueue_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_tcpdnsstop_t *ievent =
isc__nm_get_netievent_tcpdnsstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
static void
start_tcpdns_child(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nmsocket_t *sock,
uv_os_sock_t fd, int tid) {
isc__netievent_tcpdnslisten_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[tid];
isc__nmsocket_init(csock, mgr, isc_nm_tcpdnssocket, iface);
csock->parent = sock;
csock->accept_cb = sock->accept_cb;
csock->accept_cbarg = sock->accept_cbarg;
csock->recv_cb = sock->recv_cb;
csock->recv_cbarg = sock->recv_cbarg;
csock->extrahandlesize = sock->extrahandlesize;
csock->backlog = sock->backlog;
csock->tid = tid;
/*
* We don't attach to quota, just assign - to avoid
* increasing quota unnecessarily.
*/
csock->pquota = sock->pquota;
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
UNUSED(fd);
csock->fd = isc__nm_tcpdns_lb_socket(iface->addr.type.sa.sa_family);
#else
csock->fd = dup(fd);
#endif
REQUIRE(csock->fd >= 0);
ievent = isc__nm_get_netievent_tcpdnslisten(mgr, csock);
isc__nm_maybe_enqueue_ievent(&mgr->workers[tid],
(isc__netievent_t *)ievent);
}
isc_result_t
isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
isc_nm_recv_cb_t recv_cb, void *recv_cbarg,
@ -350,18 +393,15 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
isc_nmsocket_t **sockp) {
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *sock = NULL;
sa_family_t sa_family = iface->addr.type.sa.sa_family;
size_t children_size = 0;
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
uv_os_sock_t fd = -1;
#endif
REQUIRE(VALID_NM(mgr));
sock = isc_mem_get(mgr->mctx, sizeof(*sock));
isc__nmsocket_init(sock, mgr, isc_nm_tcpdnslistener, iface);
sock->rchildren = 0;
atomic_init(&sock->rchildren, 0);
#if defined(WIN32)
sock->nchildren = 1;
#else
@ -371,44 +411,33 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
sock->children = isc_mem_get(mgr->mctx, children_size);
memset(sock->children, 0, children_size);
sock->result = ISC_R_DEFAULT;
sock->tid = isc_random_uniform(sock->nchildren);
sock->result = ISC_R_UNSET;
sock->accept_cb = accept_cb;
sock->accept_cbarg = accept_cbarg;
sock->recv_cb = recv_cb;
sock->recv_cbarg = recv_cbarg;
sock->extrahandlesize = extrahandlesize;
sock->backlog = backlog;
sock->pquota = quota;
sock->tid = 0;
sock->fd = -1;
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
fd = isc__nm_tcpdns_lb_socket(sa_family);
fd = isc__nm_tcpdns_lb_socket(iface->addr.type.sa.sa_family);
#endif
isc_barrier_init(&sock->startlistening, sock->nchildren);
for (size_t i = 0; i < sock->nchildren; i++) {
isc__netievent_tcpdnslisten_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[i];
if ((int)i == isc_nm_tid()) {
continue;
}
start_tcpdns_child(mgr, iface, sock, fd, i);
}
isc__nmsocket_init(csock, mgr, isc_nm_tcpdnssocket, iface);
csock->parent = sock;
csock->accept_cb = accept_cb;
csock->accept_cbarg = accept_cbarg;
csock->recv_cb = recv_cb;
csock->recv_cbarg = recv_cbarg;
csock->extrahandlesize = extrahandlesize;
csock->backlog = backlog;
csock->tid = i;
/*
* We don't attach to quota, just assign - to avoid
* increasing quota unnecessarily.
*/
csock->pquota = quota;
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
csock->fd = isc__nm_tcpdns_lb_socket(sa_family);
#else
csock->fd = dup(fd);
#endif
REQUIRE(csock->fd >= 0);
ievent = isc__nm_get_netievent_tcpdnslisten(mgr, csock);
isc__nm_maybe_enqueue_ievent(&mgr->workers[i],
(isc__netievent_t *)ievent);
if (isc__nm_in_netthread()) {
start_tcpdns_child(mgr, iface, sock, fd, isc_nm_tid());
}
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
@ -416,21 +445,21 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
#endif
LOCK(&sock->lock);
while (sock->rchildren != sock->nchildren) {
while (atomic_load(&sock->rchildren) != sock->nchildren) {
WAIT(&sock->cond, &sock->lock);
}
result = sock->result;
atomic_store(&sock->active, true);
BROADCAST(&sock->scond);
UNLOCK(&sock->lock);
INSIST(result != ISC_R_DEFAULT);
INSIST(result != ISC_R_UNSET);
if (result == ISC_R_SUCCESS) {
REQUIRE(sock->rchildren == sock->nchildren);
REQUIRE(atomic_load(&sock->rchildren) == sock->nchildren);
*sockp = sock;
} else {
atomic_store(&sock->active, false);
isc__nm_tcpdns_stoplistening(sock);
enqueue_stoplistening(sock);
isc_nmsocket_close(&sock);
}
@ -446,7 +475,7 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
int r;
int flags = 0;
isc_nmsocket_t *sock = NULL;
isc_result_t result = ISC_R_DEFAULT;
isc_result_t result = ISC_R_UNSET;
REQUIRE(VALID_NMSOCK(ievent->sock));
REQUIRE(ievent->sock->tid == isc_nm_tid());
@ -534,16 +563,14 @@ done:
sock->pquota = NULL;
}
sock->parent->rchildren += 1;
if (sock->parent->result == ISC_R_DEFAULT) {
atomic_fetch_add(&sock->parent->rchildren, 1);
if (sock->parent->result == ISC_R_UNSET) {
sock->parent->result = result;
}
SIGNAL(&sock->parent->cond);
if (!atomic_load(&sock->parent->active)) {
WAIT(&sock->parent->scond, &sock->parent->lock);
}
INSIST(atomic_load(&sock->parent->active));
UNLOCK(&sock->parent->lock);
isc_barrier_wait(&sock->parent->startlistening);
}
static void
@ -589,14 +616,6 @@ done:
}
}
static void
enqueue_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_tcpdnsstop_t *ievent =
isc__nm_get_netievent_tcpdnsstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
void
isc__nm_tcpdns_stoplistening(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
@ -607,7 +626,12 @@ isc__nm_tcpdns_stoplistening(isc_nmsocket_t *sock) {
INSIST(0);
ISC_UNREACHABLE();
}
enqueue_stoplistening(sock);
if (!isc__nm_in_netthread()) {
enqueue_stoplistening(sock);
} else {
stop_tcpdns_parent(sock);
}
}
void
@ -1224,8 +1248,6 @@ timer_close_cb(uv_handle_t *timer) {
static void
stop_tcpdns_child(isc_nmsocket_t *sock) {
bool last_child = false;
REQUIRE(sock->type == isc_nm_tcpdnssocket);
REQUIRE(sock->tid == isc_nm_tid());
@ -1236,33 +1258,42 @@ stop_tcpdns_child(isc_nmsocket_t *sock) {
tcpdns_close_direct(sock);
LOCK(&sock->parent->lock);
sock->parent->rchildren -= 1;
last_child = (sock->parent->rchildren == 0);
UNLOCK(&sock->parent->lock);
atomic_fetch_sub(&sock->parent->rchildren, 1);
if (last_child) {
atomic_store(&sock->parent->closed, true);
isc__nmsocket_prep_destroy(sock->parent);
}
isc_barrier_wait(&sock->parent->stoplistening);
}
static void
stop_tcpdns_parent(isc_nmsocket_t *sock) {
isc_nmsocket_t *csock = NULL;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(sock->type == isc_nm_tcpdnslistener);
isc_barrier_init(&sock->stoplistening, sock->nchildren);
for (size_t i = 0; i < sock->nchildren; i++) {
isc__netievent_tcpdnsstop_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[i];
csock = &sock->children[i];
REQUIRE(VALID_NMSOCK(csock));
atomic_store(&csock->active, false);
if ((int)i == isc_nm_tid()) {
/*
* We need to schedule closing the other sockets first
*/
continue;
}
ievent = isc__nm_get_netievent_tcpdnsstop(sock->mgr, csock);
isc__nm_enqueue_ievent(&sock->mgr->workers[csock->tid],
(isc__netievent_t *)ievent);
atomic_store(&csock->active, false);
enqueue_stoplistening(csock);
}
csock = &sock->children[isc_nm_tid()];
atomic_store(&csock->active, false);
stop_tcpdns_child(csock);
atomic_store(&sock->closed, true);
isc__nmsocket_prep_destroy(sock);
}
static void

View file

@ -14,6 +14,7 @@
#include <uv.h>
#include <isc/atomic.h>
#include <isc/barrier.h>
#include <isc/buffer.h>
#include <isc/condition.h>
#include <isc/errno.h>
@ -97,7 +98,7 @@ can_log_tlsdns_quota(void) {
static isc_result_t
tlsdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
isc__networker_t *worker = NULL;
isc_result_t result = ISC_R_DEFAULT;
isc_result_t result = ISC_R_UNSET;
int r;
REQUIRE(VALID_NMSOCK(sock));
@ -324,7 +325,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
sock->extrahandlesize = extrahandlesize;
sock->connect_timeout = timeout;
sock->result = ISC_R_DEFAULT;
sock->result = ISC_R_UNSET;
sock->tls.ctx = sslctx;
atomic_init(&sock->client, true);
atomic_init(&sock->connecting, true);
@ -364,7 +365,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
(isc__netievent_t *)ievent);
}
LOCK(&sock->lock);
while (sock->result == ISC_R_DEFAULT) {
while (sock->result == ISC_R_UNSET) {
WAIT(&sock->cond, &sock->lock);
}
atomic_store(&sock->active, true);
@ -407,6 +408,51 @@ isc__nm_tlsdns_lb_socket(sa_family_t sa_family) {
return (sock);
}
static void
start_tlsdns_child(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nmsocket_t *sock,
uv_os_sock_t fd, int tid) {
isc__netievent_tlsdnslisten_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[tid];
isc__nmsocket_init(csock, mgr, isc_nm_tlsdnssocket, iface);
csock->parent = sock;
csock->accept_cb = sock->accept_cb;
csock->accept_cbarg = sock->accept_cbarg;
csock->recv_cb = sock->recv_cb;
csock->recv_cbarg = sock->recv_cbarg;
csock->extrahandlesize = sock->extrahandlesize;
csock->backlog = sock->backlog;
csock->tid = tid;
csock->tls.ctx = sock->tls.ctx;
/*
* We don't attach to quota, just assign - to avoid
* increasing quota unnecessarily.
*/
csock->pquota = sock->pquota;
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
UNUSED(fd);
csock->fd = isc__nm_tlsdns_lb_socket(iface->addr.type.sa.sa_family);
#else
csock->fd = dup(fd);
#endif
REQUIRE(csock->fd >= 0);
ievent = isc__nm_get_netievent_tlsdnslisten(mgr, csock);
isc__nm_maybe_enqueue_ievent(&mgr->workers[tid],
(isc__netievent_t *)ievent);
}
static void
enqueue_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_tlsdnsstop_t *ievent =
isc__nm_get_netievent_tlsdnsstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
isc_result_t
isc_nm_listentlsdns(isc_nm_t *mgr, isc_nmiface_t *iface,
isc_nm_recv_cb_t recv_cb, void *recv_cbarg,
@ -415,18 +461,15 @@ isc_nm_listentlsdns(isc_nm_t *mgr, isc_nmiface_t *iface,
isc_tlsctx_t *sslctx, isc_nmsocket_t **sockp) {
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *sock = NULL;
sa_family_t sa_family = iface->addr.type.sa.sa_family;
size_t children_size = 0;
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
uv_os_sock_t fd = -1;
#endif
REQUIRE(VALID_NM(mgr));
sock = isc_mem_get(mgr->mctx, sizeof(*sock));
isc__nmsocket_init(sock, mgr, isc_nm_tlsdnslistener, iface);
sock->rchildren = 0;
atomic_init(&sock->rchildren, 0);
#if defined(WIN32)
sock->nchildren = 1;
#else
@ -436,47 +479,35 @@ isc_nm_listentlsdns(isc_nm_t *mgr, isc_nmiface_t *iface,
sock->children = isc_mem_get(mgr->mctx, children_size);
memset(sock->children, 0, children_size);
sock->result = ISC_R_DEFAULT;
sock->tid = isc_random_uniform(sock->nchildren);
sock->fd = -1;
sock->result = ISC_R_UNSET;
sock->accept_cb = accept_cb;
sock->accept_cbarg = accept_cbarg;
sock->recv_cb = recv_cb;
sock->recv_cbarg = recv_cbarg;
sock->extrahandlesize = extrahandlesize;
sock->backlog = backlog;
sock->pquota = quota;
sock->tls.ctx = sslctx;
sock->tid = 0;
sock->fd = -1;
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
fd = isc__nm_tlsdns_lb_socket(sa_family);
fd = isc__nm_tlsdns_lb_socket(iface->addr.type.sa.sa_family);
#endif
isc_barrier_init(&sock->startlistening, sock->nchildren);
for (size_t i = 0; i < sock->nchildren; i++) {
isc__netievent_tlsdnslisten_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[i];
if ((int)i == isc_nm_tid()) {
continue;
}
start_tlsdns_child(mgr, iface, sock, fd, i);
}
isc__nmsocket_init(csock, mgr, isc_nm_tlsdnssocket, iface);
csock->parent = sock;
csock->accept_cb = accept_cb;
csock->accept_cbarg = accept_cbarg;
csock->recv_cb = recv_cb;
csock->recv_cbarg = recv_cbarg;
csock->extrahandlesize = extrahandlesize;
csock->backlog = backlog;
csock->tid = i;
csock->tls.ctx = sslctx;
/*
* We don't attach to quota, just assign - to avoid
* increasing quota unnecessarily.
*/
csock->pquota = quota;
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
csock->fd = isc__nm_tlsdns_lb_socket(sa_family);
#else
csock->fd = dup(fd);
#endif
REQUIRE(csock->fd >= 0);
ievent = isc__nm_get_netievent_tlsdnslisten(mgr, csock);
isc__nm_maybe_enqueue_ievent(&mgr->workers[i],
(isc__netievent_t *)ievent);
if (isc__nm_in_netthread()) {
start_tlsdns_child(mgr, iface, sock, fd, isc_nm_tid());
}
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
@ -484,21 +515,21 @@ isc_nm_listentlsdns(isc_nm_t *mgr, isc_nmiface_t *iface,
#endif
LOCK(&sock->lock);
while (sock->rchildren != sock->nchildren) {
while (atomic_load(&sock->rchildren) != sock->nchildren) {
WAIT(&sock->cond, &sock->lock);
}
result = sock->result;
atomic_store(&sock->active, true);
BROADCAST(&sock->scond);
UNLOCK(&sock->lock);
INSIST(result != ISC_R_DEFAULT);
INSIST(result != ISC_R_UNSET);
if (result == ISC_R_SUCCESS) {
REQUIRE(sock->rchildren == sock->nchildren);
REQUIRE(atomic_load(&sock->rchildren) == sock->nchildren);
*sockp = sock;
} else {
atomic_store(&sock->active, false);
isc__nm_tlsdns_stoplistening(sock);
enqueue_stoplistening(sock);
isc_nmsocket_close(&sock);
}
@ -514,7 +545,7 @@ isc__nm_async_tlsdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
int r;
int flags = 0;
isc_nmsocket_t *sock = NULL;
isc_result_t result = ISC_R_DEFAULT;
isc_result_t result = ISC_R_UNSET;
REQUIRE(VALID_NMSOCK(ievent->sock));
REQUIRE(ievent->sock->tid == isc_nm_tid());
@ -603,16 +634,14 @@ done:
sock->pquota = NULL;
}
sock->parent->rchildren += 1;
if (sock->parent->result == ISC_R_DEFAULT) {
atomic_fetch_add(&sock->parent->rchildren, 1);
if (sock->parent->result == ISC_R_UNSET) {
sock->parent->result = result;
}
SIGNAL(&sock->parent->cond);
if (!atomic_load(&sock->parent->active)) {
WAIT(&sock->parent->scond, &sock->parent->lock);
}
INSIST(atomic_load(&sock->parent->active));
UNLOCK(&sock->parent->lock);
isc_barrier_wait(&sock->parent->startlistening);
}
static void
@ -658,14 +687,6 @@ done:
}
}
static void
enqueue_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_tlsdnsstop_t *ievent =
isc__nm_get_netievent_tlsdnsstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
void
isc__nm_tlsdns_stoplistening(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
@ -676,7 +697,12 @@ isc__nm_tlsdns_stoplistening(isc_nmsocket_t *sock) {
INSIST(0);
ISC_UNREACHABLE();
}
enqueue_stoplistening(sock);
if (!isc__nm_in_netthread()) {
enqueue_stoplistening(sock);
} else {
stop_tlsdns_parent(sock);
}
}
static void
@ -1770,8 +1796,6 @@ timer_close_cb(uv_handle_t *handle) {
static void
stop_tlsdns_child(isc_nmsocket_t *sock) {
bool last_child = false;
REQUIRE(sock->type == isc_nm_tlsdnssocket);
REQUIRE(sock->tid == isc_nm_tid());
@ -1782,34 +1806,43 @@ stop_tlsdns_child(isc_nmsocket_t *sock) {
tlsdns_close_direct(sock);
LOCK(&sock->parent->lock);
sock->parent->rchildren -= 1;
last_child = (sock->parent->rchildren == 0);
UNLOCK(&sock->parent->lock);
atomic_fetch_sub(&sock->parent->rchildren, 1);
if (last_child) {
atomic_store(&sock->parent->closed, true);
isc__nmsocket_prep_destroy(sock->parent);
}
isc_barrier_wait(&sock->parent->stoplistening);
}
static void
stop_tlsdns_parent(isc_nmsocket_t *sock) {
isc_nmsocket_t *csock = NULL;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(sock->type == isc_nm_tlsdnslistener);
isc_barrier_init(&sock->stoplistening, sock->nchildren);
for (size_t i = 0; i < sock->nchildren; i++) {
isc__netievent_tlsdnsstop_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[i];
csock = &sock->children[i];
REQUIRE(VALID_NMSOCK(csock));
atomic_store(&csock->active, false);
if ((int)i == isc_nm_tid()) {
/*
* We need to schedule closing the other sockets first
*/
continue;
}
ievent = isc__nm_get_netievent_tlsdnsstop(sock->mgr, csock);
isc__nm_enqueue_ievent(&sock->mgr->workers[csock->tid],
(isc__netievent_t *)ievent);
atomic_store(&csock->active, false);
enqueue_stoplistening(csock);
}
csock = &sock->children[isc_nm_tid()];
atomic_store(&csock->active, false);
stop_tlsdns_child(csock);
atomic_store(&sock->closed, true);
isc__nmsocket_prep_destroy(sock);
}
static void

View file

@ -621,7 +621,7 @@ isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface,
tlssock->tlsstream.server_iface = *iface;
ISC_LINK_INIT(&tlssock->tlsstream.server_iface.addr, link);
tlssock->iface = &tlssock->tlsstream.server_iface;
tlssock->result = ISC_R_DEFAULT;
tlssock->result = ISC_R_UNSET;
tlssock->accept_cb = accept_cb;
tlssock->accept_cbarg = accept_cbarg;
tlssock->extrahandlesize = extrahandlesize;
@ -643,19 +643,12 @@ isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface,
/* wait for listen result */
isc__nmsocket_attach(tlssock->outer, &tsock);
LOCK(&tlssock->outer->lock);
while (tlssock->outer->rchildren != tlssock->outer->nchildren) {
WAIT(&tlssock->outer->cond, &tlssock->outer->lock);
}
result = tlssock->outer->result;
tlssock->result = result;
atomic_store(&tlssock->active, true);
INSIST(tlssock->outer->tlsstream.tlslistener == NULL);
isc__nmsocket_attach(tlssock, &tlssock->outer->tlsstream.tlslistener);
BROADCAST(&tlssock->outer->scond);
UNLOCK(&tlssock->outer->lock);
isc__nmsocket_detach(&tsock);
INSIST(result != ISC_R_DEFAULT);
INSIST(result != ISC_R_UNSET);
if (result == ISC_R_SUCCESS) {
atomic_store(&tlssock->listening, true);
@ -849,6 +842,12 @@ isc__nm_tls_stoplistening(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_tlslistener);
if (!atomic_compare_exchange_strong(&sock->closing, &(bool){ false },
true)) {
INSIST(0);
ISC_UNREACHABLE();
}
atomic_store(&sock->listening, false);
atomic_store(&sock->closed, true);
sock->recv_cb = NULL;
@ -885,7 +884,7 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
ISC_LINK_INIT(&nsock->tlsstream.local_iface.addr, link);
nsock->iface = &nsock->tlsstream.local_iface;
nsock->extrahandlesize = extrahandlesize;
nsock->result = ISC_R_DEFAULT;
nsock->result = ISC_R_UNSET;
nsock->connect_cb = cb;
nsock->connect_cbarg = cbarg;
nsock->connect_timeout = timeout;

View file

@ -13,6 +13,7 @@
#include <uv.h>
#include <isc/atomic.h>
#include <isc/barrier.h>
#include <isc/buffer.h>
#include <isc/condition.h>
#include <isc/errno.h>
@ -77,18 +78,52 @@ isc__nm_udp_lb_socket(sa_family_t sa_family) {
return (sock);
}
static void
start_udp_child(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nmsocket_t *sock,
uv_os_sock_t fd, int tid) {
isc_nmsocket_t *csock;
isc__netievent_udplisten_t *ievent = NULL;
csock = &sock->children[tid];
isc__nmsocket_init(csock, mgr, isc_nm_udpsocket, iface);
csock->parent = sock;
csock->iface = sock->iface;
csock->reading = true;
csock->recv_cb = sock->recv_cb;
csock->recv_cbarg = sock->recv_cbarg;
csock->extrahandlesize = sock->extrahandlesize;
csock->tid = tid;
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
UNUSED(fd);
csock->fd = isc__nm_udp_lb_socket(iface->addr.type.sa.sa_family);
#else
csock->fd = dup(fd);
#endif
REQUIRE(csock->fd >= 0);
ievent = isc__nm_get_netievent_udplisten(mgr, csock);
isc__nm_maybe_enqueue_ievent(&mgr->workers[tid],
(isc__netievent_t *)ievent);
}
static void
enqueue_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_udpstop_t *ievent =
isc__nm_get_netievent_udpstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
isc_result_t
isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
void *cbarg, size_t extrahandlesize, isc_nmsocket_t **sockp) {
isc_result_t result = ISC_R_SUCCESS;
isc_nmsocket_t *sock = NULL;
sa_family_t sa_family = iface->addr.type.sa.sa_family;
size_t children_size = 0;
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
uv_os_sock_t fd = -1;
#endif
REQUIRE(VALID_NM(mgr));
uv_os_sock_t fd = -1;
/*
* We are creating mgr->nworkers duplicated sockets, one
@ -97,7 +132,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t));
isc__nmsocket_init(sock, mgr, isc_nm_udplistener, iface);
sock->rchildren = 0;
atomic_init(&sock->rchildren, 0);
#if defined(WIN32)
sock->nchildren = 1;
#else
@ -111,37 +146,26 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
sock->recv_cb = cb;
sock->recv_cbarg = cbarg;
sock->extrahandlesize = extrahandlesize;
sock->result = ISC_R_DEFAULT;
sock->tid = isc_random_uniform(sock->nchildren);
sock->result = ISC_R_UNSET;
sock->tid = 0;
sock->fd = -1;
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
fd = isc__nm_udp_lb_socket(sa_family);
fd = isc__nm_udp_lb_socket(iface->addr.type.sa.sa_family);
#endif
isc_barrier_init(&sock->startlistening, sock->nchildren);
for (size_t i = 0; i < sock->nchildren; i++) {
isc__netievent_udplisten_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[i];
if ((int)i == isc_nm_tid()) {
continue;
}
start_udp_child(mgr, iface, sock, fd, i);
}
isc__nmsocket_init(csock, mgr, isc_nm_udpsocket, iface);
csock->parent = sock;
csock->iface = sock->iface;
csock->reading = true;
csock->recv_cb = cb;
csock->recv_cbarg = cbarg;
csock->extrahandlesize = sock->extrahandlesize;
csock->tid = i;
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
csock->fd = isc__nm_udp_lb_socket(sa_family);
#else
csock->fd = dup(fd);
#endif
REQUIRE(csock->fd >= 0);
ievent = isc__nm_get_netievent_udplisten(mgr, csock);
isc__nm_maybe_enqueue_ievent(&mgr->workers[i],
(isc__netievent_t *)ievent);
if (isc__nm_in_netthread()) {
start_udp_child(mgr, iface, sock, fd, isc_nm_tid());
}
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
@ -149,21 +173,21 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
#endif
LOCK(&sock->lock);
while (sock->rchildren != sock->nchildren) {
while (atomic_load(&sock->rchildren) != sock->nchildren) {
WAIT(&sock->cond, &sock->lock);
}
result = sock->result;
atomic_store(&sock->active, true);
BROADCAST(&sock->scond);
UNLOCK(&sock->lock);
INSIST(result != ISC_R_DEFAULT);
INSIST(result != ISC_R_UNSET);
if (result == ISC_R_SUCCESS) {
REQUIRE(sock->rchildren == sock->nchildren);
REQUIRE(atomic_load(&sock->rchildren) == sock->nchildren);
*sockp = sock;
} else {
atomic_store(&sock->active, false);
isc__nm_udp_stoplistening(sock);
enqueue_stoplistening(sock);
isc_nmsocket_close(&sock);
}
@ -181,7 +205,7 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
int r, uv_bind_flags = 0;
int uv_init_flags = 0;
sa_family_t sa_family;
isc_result_t result = ISC_R_DEFAULT;
isc_result_t result = ISC_R_UNSET;
REQUIRE(VALID_NMSOCK(ievent->sock));
REQUIRE(ievent->sock->tid == isc_nm_tid());
@ -269,24 +293,14 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
done:
result = isc__nm_uverr2result(r);
sock->parent->rchildren += 1;
if (sock->parent->result == ISC_R_DEFAULT) {
atomic_fetch_add(&sock->parent->rchildren, 1);
if (sock->parent->result == ISC_R_UNSET) {
sock->parent->result = result;
}
SIGNAL(&sock->parent->cond);
if (!atomic_load(&sock->parent->active)) {
WAIT(&sock->parent->scond, &sock->parent->lock);
}
INSIST(atomic_load(&sock->parent->active));
UNLOCK(&sock->parent->lock);
}
static void
enqueue_stoplistening(isc_nmsocket_t *sock) {
isc__netievent_udpstop_t *ievent =
isc__nm_get_netievent_udpstop(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
isc_barrier_wait(&sock->parent->startlistening);
}
void
@ -300,7 +314,11 @@ isc__nm_udp_stoplistening(isc_nmsocket_t *sock) {
ISC_UNREACHABLE();
}
enqueue_stoplistening(sock);
if (!isc__nm_in_netthread()) {
enqueue_stoplistening(sock);
} else {
stop_udp_parent(sock);
}
}
/*
@ -321,9 +339,6 @@ isc__nm_async_udpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
return;
}
/*
* If network manager is paused, re-enqueue the event for later.
*/
stop_udp_parent(sock);
}
@ -590,7 +605,7 @@ static isc_result_t
udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
isc__networker_t *worker = NULL;
int uv_bind_flags = UV_UDP_REUSEADDR;
isc_result_t result = ISC_R_DEFAULT;
isc_result_t result = ISC_R_UNSET;
int tries = 3;
int r;
@ -690,7 +705,6 @@ isc__nm_async_udpconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(sock->parent == NULL);
REQUIRE(sock->tid == isc_nm_tid());
req->handle = isc__nmhandle_get(sock, &req->peer, &sock->iface->addr);
result = udp_connect_direct(sock, req);
if (result != ISC_R_SUCCESS) {
atomic_store(&sock->active, false);
@ -734,7 +748,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
sock->read_timeout = timeout;
sock->extrahandlesize = extrahandlesize;
sock->peer = peer->addr;
sock->result = ISC_R_DEFAULT;
sock->result = ISC_R_UNSET;
atomic_init(&sock->client, true);
req = isc__nm_uvreq_get(mgr, sock);
@ -742,6 +756,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
req->cbarg = cbarg;
req->peer = peer->addr;
req->local = local->addr;
req->handle = isc__nmhandle_get(sock, &req->peer, &sock->iface->addr);
result = isc__nm_socket(sa_family, SOCK_DGRAM, 0, &sock->fd);
if (result != ISC_R_SUCCESS) {
@ -782,7 +797,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
(isc__netievent_t *)event);
}
LOCK(&sock->lock);
while (sock->result == ISC_R_DEFAULT) {
while (sock->result == ISC_R_UNSET) {
WAIT(&sock->cond, &sock->lock);
}
atomic_store(&sock->active, true);
@ -970,8 +985,6 @@ stop_udp_child(isc_nmsocket_t *sock) {
REQUIRE(sock->type == isc_nm_udpsocket);
REQUIRE(sock->tid == isc_nm_tid());
bool last_child = false;
if (!atomic_compare_exchange_strong(&sock->closing, &(bool){ false },
true)) {
return;
@ -979,33 +992,42 @@ stop_udp_child(isc_nmsocket_t *sock) {
udp_close_direct(sock);
LOCK(&sock->parent->lock);
sock->parent->rchildren -= 1;
last_child = (sock->parent->rchildren == 0);
UNLOCK(&sock->parent->lock);
atomic_fetch_sub(&sock->parent->rchildren, 1);
if (last_child) {
atomic_store(&sock->parent->closed, true);
isc__nmsocket_prep_destroy(sock->parent);
}
isc_barrier_wait(&sock->parent->stoplistening);
}
static void
stop_udp_parent(isc_nmsocket_t *sock) {
isc_nmsocket_t *csock = NULL;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(sock->type == isc_nm_udplistener);
isc_barrier_init(&sock->stoplistening, sock->nchildren);
for (size_t i = 0; i < sock->nchildren; i++) {
isc__netievent_udpstop_t *ievent = NULL;
isc_nmsocket_t *csock = &sock->children[i];
csock = &sock->children[i];
REQUIRE(VALID_NMSOCK(csock));
atomic_store(&csock->active, false);
if ((int)i == isc_nm_tid()) {
/*
* We need to schedule closing the other sockets first
*/
continue;
}
ievent = isc__nm_get_netievent_udpstop(sock->mgr, csock);
isc__nm_enqueue_ievent(&sock->mgr->workers[i],
(isc__netievent_t *)ievent);
atomic_store(&csock->active, false);
enqueue_stoplistening(csock);
}
csock = &sock->children[isc_nm_tid()];
atomic_store(&csock->active, false);
stop_udp_child(csock);
atomic_store(&sock->closed, true);
isc__nmsocket_prep_destroy(sock);
}
static void

36
lib/isc/netmgr_p.h Normal file
View file

@ -0,0 +1,36 @@
/*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <isc/mem.h>
#include <isc/result.h>
void
isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netgmrp);
/*%<
* Creates a new network manager with 'workers' worker threads,
* and starts it running.
*/
void
isc__netmgr_destroy(isc_nm_t **netmgrp);
/*%<
* Similar to isc_nm_detach(), but actively waits for all other references
* to be gone before returning.
*/
void
isc__netmgr_shutdown(isc_nm_t *mgr);
/*%<
* Shut down all active connections, freeing associated resources;
* prevent new connections from being established.
*/

81
lib/isc/socket_p.h Normal file
View file

@ -0,0 +1,81 @@
/*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <isc/mem.h>
#include <isc/result.h>
#include <isc/socket.h>
isc_result_t
isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp,
unsigned int maxsocks, int nthreads);
/*%<
* Create a socket manager. If "maxsocks" is non-zero, it specifies the
* maximum number of sockets that the created manager should handle.
*
* Notes:
*
*\li All memory will be allocated in memory context 'mctx'.
*
* Requires:
*
*\li 'mctx' is a valid memory context.
*
*\li 'managerp' points to a NULL isc_socketmgr_t.
*
* Ensures:
*
*\li '*managerp' is a valid isc_socketmgr_t.
*
* Returns:
*
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOMEMORY
*\li #ISC_R_UNEXPECTED
*\li #ISC_R_NOTIMPLEMENTED
*/
void
isc__socketmgr_destroy(isc_socketmgr_t **managerp);
/*%<
* Destroy a socket manager.
*
* Notes:
*
*\li This routine blocks until there are no sockets left in the manager,
* so if the caller holds any socket references using the manager, it
* must detach them before calling isc_socketmgr_destroy() or it will
* block forever.
*
* Requires:
*
*\li '*managerp' is a valid isc_socketmgr_t.
*
*\li All sockets managed by this manager are fully detached.
*
* Ensures:
*
*\li *managerp == NULL
*
*\li All resources used by the manager have been freed.
*/
#if !WIN32
#include <sys/time.h>
typedef struct isc_socketwait isc_socketwait_t;
int
isc__socketmgr_waitevents(isc_socketmgr_t *, struct timeval *,
isc_socketwait_t **);
isc_result_t
isc__socketmgr_dispatch(isc_socketmgr_t *, isc_socketwait_t *);
#endif

View file

@ -17,6 +17,7 @@
*/
#include <stdbool.h>
#include <unistd.h>
#include <isc/app.h>
#include <isc/atomic.h>
@ -44,9 +45,7 @@
#include <json_object.h>
#endif /* HAVE_JSON_C */
#ifdef OPENSSL_LEAKS
#include <openssl/err.h>
#endif /* ifdef OPENSSL_LEAKS */
#include "task_p.h"
/*
* Task manager is built around 'as little locking as possible' concept.
@ -104,6 +103,7 @@ struct isc_task {
task_state_t state;
int pause_cnt;
isc_refcount_t references;
isc_refcount_t running;
isc_eventlist_t events;
isc_eventlist_t on_shutdown;
unsigned int nevents;
@ -114,21 +114,14 @@ struct isc_task {
void *tag;
bool bound;
/* Protected by atomics */
atomic_uint_fast32_t flags;
atomic_bool shuttingdown;
atomic_bool privileged;
/* Locked by task manager lock. */
LINK(isc_task_t) link;
};
#define TASK_F_SHUTTINGDOWN 0x01
#define TASK_F_PRIVILEGED 0x02
#define TASK_SHUTTINGDOWN(t) \
((atomic_load_acquire(&(t)->flags) & TASK_F_SHUTTINGDOWN) != 0)
#define TASK_PRIVILEGED(t) \
((atomic_load_acquire(&(t)->flags) & TASK_F_PRIVILEGED) != 0)
#define TASK_FLAG_SET(t, f) atomic_fetch_or_release(&(t)->flags, (f))
#define TASK_FLAG_CLR(t, f) atomic_fetch_and_release(&(t)->flags, ~(f))
#define TASK_SHUTTINGDOWN(t) (atomic_load_acquire(&(t)->shuttingdown))
#define TASK_PRIVILEGED(t) (atomic_load_acquire(&(t)->privileged))
#define TASK_MANAGER_MAGIC ISC_MAGIC('T', 'S', 'K', 'M')
#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TASK_MANAGER_MAGIC)
@ -139,20 +132,16 @@ struct isc_taskmgr {
isc_refcount_t references;
isc_mem_t *mctx;
isc_mutex_t lock;
atomic_uint_fast32_t tasks_running;
atomic_uint_fast32_t tasks_ready;
atomic_uint_fast32_t tasks_count;
isc_nm_t *nm;
isc_nm_t *netmgr;
/* Locked by task manager lock. */
unsigned int default_quantum;
LIST(isc_task_t) tasks;
atomic_uint_fast32_t mode;
atomic_bool exclusive_req;
atomic_bool exiting;
/* Locked by halt_lock */
unsigned int halted;
/*
* Multiple threads can read/write 'excl' at the same time, so we need
* to protect the access. We can't use 'lock' since isc_task_detach()
@ -163,9 +152,6 @@ struct isc_taskmgr {
};
#define DEFAULT_DEFAULT_QUANTUM 25
#define FINISHED(m) \
(atomic_load_relaxed(&((m)->exiting)) && \
atomic_load(&(m)->tasks_count) == 0)
/*%
* The following are intended for internal use (indicated by "isc__"
@ -195,6 +181,7 @@ task_finished(isc_task_t *task) {
XTRACE("task_finished");
isc_refcount_destroy(&task->running);
isc_refcount_destroy(&task->references);
LOCK(&manager->lock);
@ -253,11 +240,13 @@ isc_task_create_bound(isc_taskmgr_t *manager, unsigned int quantum,
task->pause_cnt = 0;
isc_refcount_init(&task->references, 1);
isc_refcount_init(&task->running, 0);
INIT_LIST(task->events);
INIT_LIST(task->on_shutdown);
task->nevents = 0;
task->quantum = (quantum > 0) ? quantum : manager->default_quantum;
atomic_init(&task->flags, 0);
atomic_init(&task->shuttingdown, false);
atomic_init(&task->privileged, false);
task->now = 0;
isc_time_settoepoch(&task->tnow);
memset(task->name, 0, sizeof(task->name));
@ -313,9 +302,9 @@ task_shutdown(isc_task_t *task) {
XTRACE("task_shutdown");
if (!TASK_SHUTTINGDOWN(task)) {
if (atomic_compare_exchange_strong(&task->shuttingdown,
&(bool){ false }, true)) {
XTRACE("shutting down");
TASK_FLAG_SET(task, TASK_F_SHUTTINGDOWN);
if (task->state == task_state_idle) {
INSIST(EMPTY(task->events));
task->state = task_state_ready;
@ -352,7 +341,14 @@ task_ready(isc_task_t *task) {
REQUIRE(VALID_MANAGER(manager));
XTRACE("task_ready");
isc_nm_task_enqueue(manager->nm, task, task->threadid);
isc_refcount_increment0(&task->running);
isc_nm_task_enqueue(manager->netmgr, task, task->threadid);
}
void
isc_task_ready(isc_task_t *task) {
task_ready(task);
}
static inline bool
@ -822,8 +818,7 @@ task_run(isc_task_t *task) {
* and task lock to avoid deadlocks, just bail then.
*/
if (task->state != task_state_ready) {
UNLOCK(&task->lock);
return (ISC_R_SUCCESS);
goto done;
}
INSIST(task->state == task_state_ready);
@ -888,7 +883,6 @@ task_run(isc_task_t *task) {
* The task is done.
*/
XTRACE("done");
finished = true;
task->state = task_state_done;
} else {
if (task->state == task_state_running) {
@ -922,6 +916,13 @@ task_run(isc_task_t *task) {
break;
}
}
done:
if (isc_refcount_decrement(&task->running) == 1 &&
task->state == task_state_done)
{
finished = true;
}
UNLOCK(&task->lock);
if (finished) {
@ -939,7 +940,7 @@ isc_task_run(isc_task_t *task) {
static void
manager_free(isc_taskmgr_t *manager) {
isc_refcount_destroy(&manager->references);
isc_nm_detach(&manager->nm);
isc_nm_detach(&manager->netmgr);
isc_mutex_destroy(&manager->lock);
isc_mutex_destroy(&manager->excl_lock);
@ -967,8 +968,8 @@ isc_taskmgr_detach(isc_taskmgr_t *manager) {
}
isc_result_t
isc_taskmgr_create(isc_mem_t *mctx, unsigned int default_quantum, isc_nm_t *nm,
isc_taskmgr_t **managerp) {
isc__taskmgr_create(isc_mem_t *mctx, unsigned int default_quantum, isc_nm_t *nm,
isc_taskmgr_t **managerp) {
isc_taskmgr_t *manager;
/*
@ -990,14 +991,12 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int default_quantum, isc_nm_t *nm,
manager->default_quantum = default_quantum;
if (nm != NULL) {
isc_nm_attach(nm, &manager->nm);
isc_nm_attach(nm, &manager->netmgr);
}
INIT_LIST(manager->tasks);
atomic_init(&manager->tasks_count, 0);
atomic_init(&manager->tasks_running, 0);
atomic_init(&manager->tasks_ready, 0);
atomic_init(&manager->exiting, false);
atomic_init(&manager->mode, isc_taskmgrmode_normal);
atomic_store_relaxed(&manager->exclusive_req, false);
isc_mem_attach(mctx, &manager->mctx);
@ -1010,19 +1009,12 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int default_quantum, isc_nm_t *nm,
}
void
isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
isc_taskmgr_t *manager;
isc__taskmgr_shutdown(isc_taskmgr_t *manager) {
isc_task_t *task;
/*
* Destroy '*managerp'.
*/
REQUIRE(managerp != NULL);
manager = *managerp;
REQUIRE(VALID_MANAGER(manager));
XTHREADTRACE("isc_taskmgr_destroy");
XTHREADTRACE("isc_taskmgr_shutdown");
/*
* Only one non-worker thread may ever call this routine.
* If a worker thread wants to initiate shutdown of the
@ -1072,16 +1064,39 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
}
UNLOCK(&manager->lock);
}
isc_taskmgr_detach(manager);
void
isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
REQUIRE(managerp != NULL && VALID_MANAGER(*managerp));
isc_taskmgr_t *manager = *managerp;
*managerp = NULL;
XTHREADTRACE("isc_taskmgr_destroy");
#ifdef ISC_TASK_TRACE
int counter = 0;
while (isc_refcount_current(&manager->references) > 1 &&
counter++ < 1000) {
usleep(10 * 1000);
}
#else
while (isc_refcount_current(&manager->references) > 1) {
usleep(10 * 1000);
}
#endif
REQUIRE(isc_refcount_decrement(&manager->references) == 1);
manager_free(manager);
}
void
isc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task) {
REQUIRE(VALID_MANAGER(mgr));
REQUIRE(VALID_TASK(task));
REQUIRE(task->threadid == 0);
LOCK(&mgr->excl_lock);
if (mgr->excl != NULL) {
isc_task_detach(&mgr->excl);
@ -1130,7 +1145,7 @@ isc_task_beginexclusive(isc_task_t *task) {
return (ISC_R_LOCKBUSY);
}
isc_nm_pause(manager->nm);
isc_nm_pause(manager->netmgr);
return (ISC_R_SUCCESS);
}
@ -1143,7 +1158,7 @@ isc_task_endexclusive(isc_task_t *task) {
REQUIRE(task->state == task_state_running);
manager = task->manager;
isc_nm_resume(manager->nm);
isc_nm_resume(manager->netmgr);
REQUIRE(atomic_compare_exchange_strong(&manager->exclusive_req,
&(bool){ true }, false));
}
@ -1207,32 +1222,37 @@ isc_task_unpause(isc_task_t *task) {
}
}
void
isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode) {
atomic_store(&manager->mode, mode);
}
isc_taskmgrmode_t
isc_taskmgr_mode(isc_taskmgr_t *manager) {
return (atomic_load(&manager->mode));
}
void
isc_task_setprivilege(isc_task_t *task, bool priv) {
REQUIRE(VALID_TASK(task));
uint_fast32_t oldflags, newflags;
oldflags = atomic_load_acquire(&task->flags);
do {
if (priv) {
newflags = oldflags | TASK_F_PRIVILEGED;
} else {
newflags = oldflags & ~TASK_F_PRIVILEGED;
}
if (newflags == oldflags) {
return;
}
} while (!atomic_compare_exchange_weak_acq_rel(&task->flags, &oldflags,
newflags));
atomic_store_release(&task->privileged, priv);
}
bool
isc_task_privilege(isc_task_t *task) {
isc_task_getprivilege(isc_task_t *task) {
REQUIRE(VALID_TASK(task));
return (TASK_PRIVILEGED(task));
}
bool
isc_task_privileged(isc_task_t *task) {
REQUIRE(VALID_TASK(task));
return (isc_taskmgr_mode(task->manager) && TASK_PRIVILEGED(task));
}
bool
isc_task_exiting(isc_task_t *task) {
REQUIRE(VALID_TASK(task));
@ -1269,21 +1289,6 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, void *writer0) {
mgr->default_quantum));
TRY0(xmlTextWriterEndElement(writer)); /* default-quantum */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-count"));
TRY0(xmlTextWriterWriteFormatString(
writer, "%d", (int)atomic_load_relaxed(&mgr->tasks_count)));
TRY0(xmlTextWriterEndElement(writer)); /* tasks-count */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-running"));
TRY0(xmlTextWriterWriteFormatString(
writer, "%d", (int)atomic_load_relaxed(&mgr->tasks_running)));
TRY0(xmlTextWriterEndElement(writer)); /* tasks-running */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-ready"));
TRY0(xmlTextWriterWriteFormatString(
writer, "%d", (int)atomic_load_relaxed(&mgr->tasks_ready)));
TRY0(xmlTextWriterEndElement(writer)); /* tasks-ready */
TRY0(xmlTextWriterEndElement(writer)); /* thread-model */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks"));
@ -1373,18 +1378,6 @@ isc_taskmgr_renderjson(isc_taskmgr_t *mgr, void *tasks0) {
CHECKMEM(obj);
json_object_object_add(tasks, "default-quantum", obj);
obj = json_object_new_int(atomic_load_relaxed(&mgr->tasks_count));
CHECKMEM(obj);
json_object_object_add(tasks, "tasks-count", obj);
obj = json_object_new_int(atomic_load_relaxed(&mgr->tasks_running));
CHECKMEM(obj);
json_object_object_add(tasks, "tasks-running", obj);
obj = json_object_new_int(atomic_load_relaxed(&mgr->tasks_ready));
CHECKMEM(obj);
json_object_object_add(tasks, "tasks-ready", obj);
array = json_object_new_array();
CHECKMEM(array);

104
lib/isc/task_p.h Normal file
View file

@ -0,0 +1,104 @@
/*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <isc/mem.h>
#include <isc/result.h>
#include <isc/task.h>
isc_result_t
isc__taskmgr_create(isc_mem_t *mctx, unsigned int default_quantum, isc_nm_t *nm,
isc_taskmgr_t **managerp);
/*%<
* Create a new task manager.
*
* Notes:
*
*\li If 'default_quantum' is non-zero, then it will be used as the default
* quantum value when tasks are created. If zero, then an implementation
* defined default quantum will be used.
*
*\li If 'nm' is set then netmgr is paused when an exclusive task mode
* is requested.
*
* Requires:
*
*\li 'mctx' is a valid memory context.
*
*\li managerp != NULL && *managerp == NULL
*
* Ensures:
*
*\li On success, '*managerp' will be attached to the newly created task
* manager.
*
* Returns:
*
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOMEMORY
*\li #ISC_R_NOTHREADS No threads could be created.
*\li #ISC_R_UNEXPECTED An unexpected error occurred.
*\li #ISC_R_SHUTTINGDOWN The non-threaded, shared, task
* manager shutting down.
*/
void
isc__taskmgr_destroy(isc_taskmgr_t **managerp);
/*%<
* Destroy '*managerp'.
*
* Notes:
*
*\li Calling isc_taskmgr_destroy() will shutdown all tasks managed by
* *managerp that haven't already been shutdown. The call will block
* until all tasks have entered the done state.
*
*\li isc_taskmgr_destroy() must not be called by a task event action,
* because it would block forever waiting for the event action to
* complete. An event action that wants to cause task manager shutdown
* should request some non-event action thread of execution to do the
* shutdown, e.g. by signaling a condition variable or using
* isc_app_shutdown().
*
*\li Task manager references are not reference counted, so the caller
* must ensure that no attempt will be made to use the manager after
* isc_taskmgr_destroy() returns.
*
* Requires:
*
*\li '*managerp' is a valid task manager.
*
*\li 'isc__taskmgr_shutdown()' and isc__netmgr_shutdown() have been
* called.
*/
void
isc__taskmgr_shutdown(isc_taskmgr_t *manager);
/*%>
* Shutdown 'manager'.
*
* Notes:
*
*\li Calling isc__taskmgr_shutdown() will shut down all tasks managed by
* *managerp that haven't already been shut down.
*
* Requires:
*
*\li 'manager' is a valid task manager.
*
*\li isc_taskmgr_destroy() has not be called previously on '*managerp'.
*
* Ensures:
*
*\li All resources used by the task manager, and any tasks it managed,
* have been freed.
*/

View file

@ -10,7 +10,7 @@ LDADD += \
check_LTLIBRARIES = libisctest.la
libisctest_la_SOURCES = \
../unix/socket_p.h \
../socket_p.h \
isctest.c \
isctest.h \
uv_wrap.h

View file

@ -43,6 +43,7 @@
#include "../netmgr/netmgr-int.h"
#include "../netmgr/uv-compat.c"
#include "../netmgr/uv-compat.h"
#include "../netmgr_p.h"
#include "isctest.h"
#define MAX_NM 2
@ -319,7 +320,7 @@ nm_setup(void **state) {
nm = isc_mem_get(test_mctx, MAX_NM * sizeof(nm[0]));
for (size_t i = 0; i < MAX_NM; i++) {
nm[i] = isc_nm_start(test_mctx, nworkers);
isc__netmgr_create(test_mctx, nworkers, &nm[i]);
assert_non_null(nm[i]);
}
@ -339,7 +340,7 @@ nm_teardown(void **state) {
isc_nm_t **nm = (isc_nm_t **)*state;
for (size_t i = 0; i < MAX_NM; i++) {
isc_nm_destroy(&nm[i]);
isc__netmgr_destroy(&nm[i]);
assert_null(nm[i]);
}
isc_mem_put(test_mctx, nm, MAX_NM * sizeof(nm[0]));
@ -498,7 +499,7 @@ doh_noop(void **state) {
.length = send_msg.len },
noop_read_cb, NULL, atomic_load(&use_TLS), 30000);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
assert_int_equal(0, atomic_load(&csends));
assert_int_equal(0, atomic_load(&creads));
@ -545,7 +546,7 @@ doh_noresponse(void **state) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
}
static void
@ -666,7 +667,7 @@ doh_timeout_recovery(void **state) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
}
static void
@ -792,7 +793,7 @@ doh_recv_one(void **state) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(csends);
X(creads);
@ -913,7 +914,7 @@ doh_recv_two(void **state) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(csends);
X(creads);
@ -979,7 +980,7 @@ doh_recv_send(void **state) {
isc_thread_join(threads[i], NULL);
}
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
@ -1050,7 +1051,7 @@ doh_recv_half_send(void **state) {
isc_thread_yield();
}
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
for (size_t i = 0; i < nthreads; i++) {
isc_thread_join(threads[i], NULL);
@ -1134,7 +1135,7 @@ doh_half_recv_send(void **state) {
isc_thread_join(threads[i], NULL);
}
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(csends);
X(creads);
@ -1202,7 +1203,7 @@ doh_half_recv_half_send(void **state) {
isc_thread_yield();
}
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);

View file

@ -20,6 +20,7 @@
#include <isc/buffer.h>
#include <isc/hash.h>
#include <isc/hp.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/os.h>
#include <isc/socket.h>
@ -58,18 +59,10 @@ cleanup_managers(void) {
isc_task_shutdown(maintask);
isc_task_destroy(&maintask);
}
if (socketmgr != NULL) {
isc_socketmgr_destroy(&socketmgr);
}
if (taskmgr != NULL) {
isc_taskmgr_destroy(&taskmgr);
}
if (netmgr != NULL) {
isc_nm_destroy(&netmgr);
}
if (timermgr != NULL) {
isc_timermgr_destroy(&timermgr);
}
isc_managers_destroy(netmgr == NULL ? NULL : &netmgr,
taskmgr == NULL ? NULL : &taskmgr,
timermgr == NULL ? NULL : &timermgr,
socketmgr == NULL ? NULL : &socketmgr);
}
static isc_result_t
@ -87,14 +80,12 @@ create_managers(unsigned int workers) {
INSIST(workers != 0);
isc_hp_init(6 * workers);
isc_managers_create(test_mctx, workers, 0, 0, &netmgr, &taskmgr,
&timermgr, &socketmgr);
netmgr = isc_nm_start(test_mctx, workers);
CHECK(isc_taskmgr_create(test_mctx, 0, netmgr, &taskmgr));
CHECK(isc_task_create(taskmgr, 0, &maintask));
CHECK(isc_task_create_bound(taskmgr, 0, &maintask, 0));
isc_taskmgr_setexcltask(taskmgr, maintask);
CHECK(isc_timermgr_create(test_mctx, &timermgr));
CHECK(isc_socketmgr_create(test_mctx, &socketmgr));
return (ISC_R_SUCCESS);
cleanup:
@ -150,9 +141,6 @@ isc_test_end(void) {
if (maintask != NULL) {
isc_task_detach(&maintask);
}
if (taskmgr != NULL) {
isc_taskmgr_destroy(&taskmgr);
}
cleanup_managers();

View file

@ -37,6 +37,7 @@
#include "../netmgr/udp.c"
#include "../netmgr/uv-compat.c"
#include "../netmgr/uv-compat.h"
#include "../netmgr_p.h"
#include "isctest.h"
typedef void (*stream_connect_function)(isc_nm_t *nm);
@ -335,12 +336,12 @@ nm_setup(void **state __attribute__((unused))) {
return (-1);
}
listen_nm = isc_nm_start(test_mctx, workers);
isc__netmgr_create(test_mctx, workers, &listen_nm);
assert_non_null(listen_nm);
isc_nm_settimeouts(listen_nm, T_INIT, T_IDLE, T_KEEPALIVE,
T_ADVERTISED);
connect_nm = isc_nm_start(test_mctx, workers);
isc__netmgr_create(test_mctx, workers, &connect_nm);
assert_non_null(connect_nm);
isc_nm_settimeouts(connect_nm, T_INIT, T_IDLE, T_KEEPALIVE,
T_ADVERTISED);
@ -358,10 +359,10 @@ static int
nm_teardown(void **state __attribute__((unused))) {
UNUSED(state);
isc_nm_destroy(&connect_nm);
isc__netmgr_destroy(&connect_nm);
assert_null(connect_nm);
isc_nm_destroy(&listen_nm);
isc__netmgr_destroy(&listen_nm);
assert_null(listen_nm);
WAIT_FOR_EQ(active_cconnects, 0);
@ -677,7 +678,7 @@ mock_udpconnect_uv_udp_open(void **state __attribute__((unused))) {
isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr,
(isc_nmiface_t *)&udp_listen_addr, connect_connect_cb,
NULL, T_CONNECT, 0);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
RESET_RETURN;
}
@ -691,7 +692,7 @@ mock_udpconnect_uv_udp_bind(void **state __attribute__((unused))) {
isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr,
(isc_nmiface_t *)&udp_listen_addr, connect_connect_cb,
NULL, T_CONNECT, 0);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
RESET_RETURN;
}
@ -706,7 +707,7 @@ mock_udpconnect_uv_udp_connect(void **state __attribute__((unused))) {
isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr,
(isc_nmiface_t *)&udp_listen_addr, connect_connect_cb,
NULL, T_CONNECT, 0);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
RESET_RETURN;
}
@ -721,7 +722,7 @@ mock_udpconnect_uv_recv_buffer_size(void **state __attribute__((unused))) {
isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr,
(isc_nmiface_t *)&udp_listen_addr, connect_connect_cb,
NULL, T_CONNECT, 0);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
RESET_RETURN;
}
@ -735,7 +736,7 @@ mock_udpconnect_uv_send_buffer_size(void **state __attribute__((unused))) {
isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr,
(isc_nmiface_t *)&udp_listen_addr, connect_connect_cb,
NULL, T_CONNECT, 0);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
RESET_RETURN;
}
@ -758,7 +759,7 @@ udp_noop(void **state __attribute__((unused))) {
isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr,
(isc_nmiface_t *)&udp_listen_addr, connect_connect_cb,
NULL, T_CONNECT, 0);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
atomic_assert_int_eq(cconnects, 0);
atomic_assert_int_eq(csends, 0);
@ -787,7 +788,7 @@ udp_noresponse(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -860,7 +861,7 @@ udp_timeout_recovery(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
}
static void
@ -889,7 +890,7 @@ udp_recv_one(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -937,7 +938,7 @@ udp_recv_two(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -980,7 +981,7 @@ udp_recv_send(void **state __attribute__((unused))) {
isc_thread_join(threads[i], NULL);
}
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
@ -1020,7 +1021,7 @@ udp_recv_half_send(void **state __attribute__((unused))) {
WAIT_FOR_GE(ssends, esends / 2);
WAIT_FOR_GE(creads, esends / 2);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
DONE();
for (size_t i = 0; i < workers; i++) {
@ -1073,7 +1074,7 @@ udp_half_recv_send(void **state __attribute__((unused))) {
/* Try to send a little while longer */
isc_test_nap((esends / 2) * 10000);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
DONE();
for (size_t i = 0; i < workers; i++) {
@ -1115,7 +1116,7 @@ udp_half_recv_half_send(void **state __attribute__((unused))) {
WAIT_FOR_GE(ssends, esends / 2);
WAIT_FOR_GE(creads, esends / 2);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
@ -1218,7 +1219,7 @@ stream_noop(void **state __attribute__((unused))) {
connect_readcb = NULL;
isc_refcount_increment0(&active_cconnects);
stream_connect(connect_connect_cb, NULL, T_CONNECT, 0);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
atomic_assert_int_eq(cconnects, 0);
atomic_assert_int_eq(csends, 0);
@ -1244,7 +1245,7 @@ stream_noresponse(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -1294,7 +1295,7 @@ stream_timeout_recovery(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
}
static void
@ -1322,7 +1323,7 @@ stream_recv_one(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -1367,7 +1368,7 @@ stream_recv_two(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -1416,7 +1417,7 @@ stream_recv_send(void **state __attribute__((unused))) {
isc_thread_join(threads[i], NULL);
}
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
@ -1462,7 +1463,7 @@ stream_recv_half_send(void **state __attribute__((unused))) {
WAIT_FOR_GE(ssends, esends / 2);
WAIT_FOR_GE(creads, esends / 2);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
DONE();
for (size_t i = 0; i < workers; i++) {
@ -1521,7 +1522,7 @@ stream_half_recv_send(void **state __attribute__((unused))) {
/* Try to send a little while longer */
isc_test_nap((esends / 2) * 10000);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
DONE();
for (size_t i = 0; i < workers; i++) {
@ -1569,7 +1570,7 @@ stream_half_recv_half_send(void **state __attribute__((unused))) {
WAIT_FOR_GE(ssends, esends / 2);
WAIT_FOR_GE(creads, esends / 2);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
@ -1767,7 +1768,7 @@ tcpdns_noop(void **state __attribute__((unused))) {
isc_nm_tcpdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr,
(isc_nmiface_t *)&tcp_listen_addr,
connect_connect_cb, NULL, T_CONNECT, 0);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
atomic_assert_int_eq(cconnects, 0);
atomic_assert_int_eq(csends, 0);
@ -1801,7 +1802,7 @@ tcpdns_noresponse(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -1856,7 +1857,7 @@ tcpdns_timeout_recovery(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
}
static void
@ -1886,7 +1887,7 @@ tcpdns_recv_one(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -1936,7 +1937,7 @@ tcpdns_recv_two(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -1980,7 +1981,7 @@ tcpdns_recv_send(void **state __attribute__((unused))) {
isc_thread_join(threads[i], NULL);
}
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
@ -2021,7 +2022,7 @@ tcpdns_recv_half_send(void **state __attribute__((unused))) {
WAIT_FOR_GE(ssends, esends / 2);
WAIT_FOR_GE(creads, esends / 2);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
DONE();
for (size_t i = 0; i < workers; i++) {
@ -2075,7 +2076,7 @@ tcpdns_half_recv_send(void **state __attribute__((unused))) {
/* Try to send a little while longer */
isc_test_nap((esends / 2) * 10000);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
DONE();
for (size_t i = 0; i < workers; i++) {
@ -2118,7 +2119,7 @@ tcpdns_half_recv_half_send(void **state __attribute__((unused))) {
WAIT_FOR_GE(ssends, esends / 2);
WAIT_FOR_GE(creads, esends / 2);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
@ -2355,7 +2356,7 @@ tlsdns_noop(void **state __attribute__((unused))) {
connect_connect_cb, NULL, T_CONNECT, 0,
tcp_connect_tlsctx);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
atomic_assert_int_eq(cconnects, 0);
atomic_assert_int_eq(csends, 0);
@ -2391,7 +2392,7 @@ tlsdns_noresponse(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -2452,7 +2453,7 @@ tlsdns_timeout_recovery(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
}
static void
@ -2484,7 +2485,7 @@ tlsdns_recv_one(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -2537,7 +2538,7 @@ tlsdns_recv_two(void **state __attribute__((unused))) {
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
X(cconnects);
X(csends);
@ -2582,7 +2583,7 @@ tlsdns_recv_send(void **state __attribute__((unused))) {
isc_thread_join(threads[i], NULL);
}
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);
@ -2624,7 +2625,7 @@ tlsdns_recv_half_send(void **state __attribute__((unused))) {
WAIT_FOR_GE(ssends, esends / 2);
WAIT_FOR_GE(creads, esends / 2);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
DONE();
for (size_t i = 0; i < workers; i++) {
@ -2679,7 +2680,7 @@ tlsdns_half_recv_send(void **state __attribute__((unused))) {
/* Try to send a little while longer */
isc_test_nap((esends / 2) * 10000);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
DONE();
for (size_t i = 0; i < workers; i++) {
@ -2723,7 +2724,7 @@ tlsdns_half_recv_half_send(void **state __attribute__((unused))) {
WAIT_FOR_GE(ssends, esends / 2);
WAIT_FOR_GE(creads, esends / 2);
isc_nm_closedown(connect_nm);
isc__netmgr_shutdown(connect_nm);
isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock);
assert_null(listen_sock);

View file

@ -12,6 +12,7 @@
/*! \file */
#if HAVE_CMOCKA
#include <inttypes.h>
#include <sched.h> /* IWYU pragma: keep */
#include <setjmp.h>
#include <stdarg.h>
@ -30,7 +31,7 @@
#include <isc/socket.h>
#include <isc/task.h>
#include "../unix/socket_p.h"
#include "../socket_p.h"
#include "isctest.h"
static bool recv_dscp;
@ -79,14 +80,14 @@ _teardown(void **state) {
typedef struct {
atomic_bool done;
atomic_uintptr_t socket;
isc_result_t result;
isc_socket_t *socket;
} completion_t;
static void
completion_init(completion_t *completion) {
atomic_init(&completion->done, false);
completion->socket = NULL;
atomic_init(&completion->socket, (uintptr_t)NULL);
}
static void
@ -99,7 +100,7 @@ accept_done(isc_task_t *task, isc_event_t *event) {
completion->result = nevent->result;
atomic_store(&completion->done, true);
if (completion->result == ISC_R_SUCCESS) {
completion->socket = nevent->newsocket;
atomic_store(&completion->socket, (uintptr_t)nevent->newsocket);
}
isc_event_free(&event);
@ -136,35 +137,24 @@ event_done(isc_task_t *task, isc_event_t *event) {
isc_event_free(&event);
}
static isc_result_t
static void
waitfor(completion_t *completion) {
int i = 0;
while (!atomic_load(&completion->done) && i++ < 5000) {
isc_test_nap(1000);
isc_test_nap(10000);
}
if (atomic_load(&completion->done)) {
return (ISC_R_SUCCESS);
}
return (ISC_R_FAILURE);
assert_true(atomic_load(&completion->done));
}
static void
waitbody(void) {
isc_test_nap(1000);
}
static isc_result_t
waitfor2(completion_t *c1, completion_t *c2) {
int i = 0;
while (!(atomic_load(&c1->done) && atomic_load(&c2->done)) &&
i++ < 5000) {
waitbody();
isc_test_nap(10000);
}
if (atomic_load(&c1->done) && atomic_load(&c2->done)) {
return (ISC_R_SUCCESS);
}
return (ISC_R_FAILURE);
assert_true(atomic_load(&c1->done) && atomic_load(&c2->done));
}
/*
@ -525,7 +515,7 @@ tcp_dscp_v4_test(void **state) {
assert_int_equal(completion.result, ISC_R_SUCCESS);
assert_true(atomic_load(&completion2.done));
assert_int_equal(completion2.result, ISC_R_SUCCESS);
s3 = completion2.socket;
s3 = (isc_socket_t *)atomic_load(&completion2.socket);
isc_socket_dscp(s2, 056); /* EF */
@ -613,7 +603,7 @@ tcp_dscp_v6_test(void **state) {
assert_int_equal(completion.result, ISC_R_SUCCESS);
assert_true(atomic_load(&completion2.done));
assert_int_equal(completion2.result, ISC_R_SUCCESS);
s3 = completion2.socket;
s3 = (isc_socket_t *)atomic_load(&completion2.socket);
isc_socket_dscp(s2, 056); /* EF */

View file

@ -29,6 +29,7 @@
#include <isc/cmocka.h>
#include <isc/commandline.h>
#include <isc/condition.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/platform.h>
#include <isc/print.h>
@ -215,18 +216,19 @@ privileged_events(void **state) {
* queue without things happening while we do it.
*/
isc_nm_pause(netmgr);
isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
result = isc_task_create(taskmgr, 0, &task1);
assert_int_equal(result, ISC_R_SUCCESS);
isc_task_setname(task1, "privileged", NULL);
assert_false(isc_task_privilege(task1));
assert_false(isc_task_getprivilege(task1));
isc_task_setprivilege(task1, true);
assert_true(isc_task_privilege(task1));
assert_true(isc_task_getprivilege(task1));
result = isc_task_create(taskmgr, 0, &task2);
assert_int_equal(result, ISC_R_SUCCESS);
isc_task_setname(task2, "normal", NULL);
assert_false(isc_task_privilege(task2));
assert_false(isc_task_getprivilege(task2));
/* First event: privileged */
event = isc_event_allocate(test_mctx, task1, ISC_TASKEVENT_TEST, set,
@ -295,7 +297,7 @@ privileged_events(void **state) {
assert_int_equal(atomic_load(&counter), 6);
isc_task_setprivilege(task1, false);
assert_false(isc_task_privilege(task1));
assert_false(isc_task_getprivilege(task1));
isc_task_destroy(&task1);
assert_null(task1);
@ -329,18 +331,19 @@ privilege_drop(void **state) {
* without things happening while we do it.
*/
isc_nm_pause(netmgr);
isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
result = isc_task_create(taskmgr, 0, &task1);
assert_int_equal(result, ISC_R_SUCCESS);
isc_task_setname(task1, "privileged", NULL);
assert_false(isc_task_privilege(task1));
assert_false(isc_task_getprivilege(task1));
isc_task_setprivilege(task1, true);
assert_true(isc_task_privilege(task1));
assert_true(isc_task_getprivilege(task1));
result = isc_task_create(taskmgr, 0, &task2);
assert_int_equal(result, ISC_R_SUCCESS);
isc_task_setname(task2, "normal", NULL);
assert_false(isc_task_privilege(task2));
assert_false(isc_task_getprivilege(task2));
/* First event: privileged */
event = isc_event_allocate(test_mctx, task1, ISC_TASKEVENT_TEST,
@ -705,12 +708,16 @@ task_exclusive(void **state) {
tasks[i] = NULL;
result = isc_task_create(taskmgr, 0, &tasks[i]);
assert_int_equal(result, ISC_R_SUCCESS);
/* task chosen from the middle of the range */
if (i == 6) {
/* task chosen from the middle of the range */
result = isc_task_create_bound(taskmgr, 0, &tasks[i],
0);
assert_int_equal(result, ISC_R_SUCCESS);
isc_taskmgr_setexcltask(taskmgr, tasks[6]);
} else {
result = isc_task_create(taskmgr, 0, &tasks[i]);
assert_int_equal(result, ISC_R_SUCCESS);
}
v = isc_mem_get(test_mctx, sizeof *v);
@ -784,7 +791,6 @@ maxtask_cb(isc_task_t *task, isc_event_t *event) {
static void
manytasks(void **state) {
isc_mem_t *mctx = NULL;
isc_result_t result;
isc_event_t *event = NULL;
uintptr_t ntasks = 10000;
@ -801,9 +807,7 @@ manytasks(void **state) {
isc_mem_debugging = ISC_MEM_DEBUGRECORD;
isc_mem_create(&mctx);
netmgr = isc_nm_start(mctx, 4);
result = isc_taskmgr_create(mctx, 0, netmgr, &taskmgr);
assert_int_equal(result, ISC_R_SUCCESS);
isc_managers_create(mctx, 4, 0, 0, &netmgr, &taskmgr, NULL, NULL);
atomic_init(&done, false);
@ -818,8 +822,8 @@ manytasks(void **state) {
}
UNLOCK(&lock);
isc_taskmgr_destroy(&taskmgr);
isc_nm_destroy(&netmgr);
isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL);
isc_mem_destroy(&mctx);
isc_condition_destroy(&cv);
isc_mutex_destroy(&lock);
@ -899,7 +903,7 @@ sd_event2(isc_task_t *task, isc_event_t *event) {
}
static void
shutdown(void **state) {
task_shutdown(void **state) {
isc_result_t result;
isc_eventtype_t event_type;
isc_event_t *event = NULL;
@ -1545,7 +1549,8 @@ main(int argc, char **argv) {
cmocka_unit_test_setup_teardown(purgeevent_notpurge, _setup,
_teardown),
cmocka_unit_test_setup_teardown(purgerange, _setup, _teardown),
cmocka_unit_test_setup_teardown(shutdown, _setup4, _teardown),
cmocka_unit_test_setup_teardown(task_shutdown, _setup4,
_teardown),
cmocka_unit_test_setup_teardown(task_exclusive, _setup4,
_teardown),
};

View file

@ -164,9 +164,9 @@ set_privilege(void **state) {
assert_true(VALID_TASK(task2));
assert_true(VALID_TASK(task3));
assert_true(isc_task_privilege(task1));
assert_true(isc_task_privilege(task2));
assert_true(isc_task_privilege(task3));
assert_true(isc_task_getprivilege(task1));
assert_true(isc_task_getprivilege(task2));
assert_true(isc_task_getprivilege(task3));
isc_task_destroy(&task1);
isc_task_destroy(&task2);

View file

@ -29,9 +29,7 @@
#include <isc/timer.h>
#include <isc/util.h>
#ifdef OPENSSL_LEAKS
#include <openssl/err.h>
#endif /* ifdef OPENSSL_LEAKS */
#include "timer_p.h"
#ifdef ISC_TIMER_TRACE
#define XTRACE(s) fprintf(stderr, "%s\n", (s))
@ -630,10 +628,6 @@ static isc_threadresult_t
}
UNLOCK(&manager->lock);
#ifdef OPENSSL_LEAKS
ERR_remove_state(0);
#endif /* ifdef OPENSSL_LEAKS */
return ((isc_threadresult_t)0);
}
@ -663,7 +657,7 @@ set_index(void *what, unsigned int index) {
}
isc_result_t
isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
isc_timermgr_t *manager;
isc_result_t result;
@ -707,7 +701,7 @@ isc_timermgr_poke(isc_timermgr_t *manager) {
}
void
isc_timermgr_destroy(isc_timermgr_t **managerp) {
isc__timermgr_destroy(isc_timermgr_t **managerp) {
isc_timermgr_t *manager;
/*

65
lib/isc/timer_p.h Normal file
View file

@ -0,0 +1,65 @@
/*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <isc/mem.h>
#include <isc/result.h>
#include <isc/timer.h>
isc_result_t
isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
/*%<
* Create a timer manager.
*
* Notes:
*
*\li All memory will be allocated in memory context 'mctx'.
*
* Requires:
*
*\li 'mctx' is a valid memory context.
*
*\li 'managerp' points to a NULL isc_timermgr_t.
*
* Ensures:
*
*\li '*managerp' is a valid isc_timermgr_t.
*
* Returns:
*
*\li Success
*\li No memory
*\li Unexpected error
*/
void
isc__timermgr_destroy(isc_timermgr_t **managerp);
/*%<
* Destroy a timer manager.
*
* Notes:
*
*\li This routine blocks until there are no timers left in the manager,
* so if the caller holds any timer references using the manager, it
* must detach them before calling isc_timermgr_destroy() or it will
* block forever.
*
* Requires:
*
*\li '*managerp' is a valid isc_timermgr_t.
*
* Ensures:
*
*\li *managerp == NULL
*
*\li All resources used by the manager have been freed.
*/

View file

@ -74,6 +74,7 @@
#include <netinet/tcp.h>
#include "errno2result.h"
#include "socket_p.h"
#ifdef ENABLE_TCP_FASTOPEN
#include <netinet/tcp.h>
@ -3752,12 +3753,7 @@ cleanup_thread(isc_mem_t *mctx, isc__socketthread_t *thread) {
}
isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
return (isc_socketmgr_create2(mctx, managerp, 0, 1));
}
isc_result_t
isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp,
unsigned int maxsocks, int nthreads) {
int i;
isc_socketmgr_t *manager;
@ -3828,7 +3824,7 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
}
void
isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
isc_socketmgr_t *manager;
/*

View file

@ -1,25 +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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#ifndef ISC_SOCKET_P_H
#define ISC_SOCKET_P_H
/*! \file */
#include <sys/time.h>
typedef struct isc_socketwait isc_socketwait_t;
int
isc__socketmgr_waitevents(isc_socketmgr_t *, struct timeval *,
isc_socketwait_t **);
isc_result_t
isc__socketmgr_dispatch(isc_socketmgr_t *, isc_socketwait_t *);
#endif /* ISC_SOCKET_P_H */

View file

@ -96,14 +96,12 @@ isc_socket_send
isc_socket_sendto
isc_socket_sendto2
isc_socket_setname
isc_socketmgr_create
isc_socketmgr_create2
isc_socketmgr_destroy
isc_socketmgr_getmaxsockets
isc_socketmgr_setreserved
isc_socketmgr_setstats
isc_task_getname
isc_task_gettag
isc_task_ready
isc_task_run
isc_task_unsendrange
isc_taskmgr_attach
@ -352,6 +350,8 @@ isc_logconfig_create
isc_logconfig_destroy
isc_logconfig_use
isc_logfile_roll
isc_managers_create
isc_managers_destroy
isc_md_new
isc_md_init
isc_md_reset
@ -452,8 +452,6 @@ isc_nmhandle_peeraddr
isc_nmhandle_setdata
isc_nmhandle_settimeout
isc_nm_cancelread
isc_nm_closedown
isc_nm_destroy
isc_nm_detach
isc_nm_http_endpoint
isc_nm_httpconnect
@ -469,7 +467,6 @@ isc_nm_read
isc_nm_resumeread
isc_nm_send
isc_nm_setstats
isc_nm_start
isc_nm_stoplistening
isc_nm_tcpconnect
isc_nm_tcpdnsconnect
@ -638,9 +635,10 @@ isc_task_endexclusive
isc_task_exiting
isc_task_getcurrenttime
isc_task_getcurrenttimex
isc_task_getprivilege
isc_task_onshutdown
isc_task_pause
isc_task_privilege
isc_task_privileged
isc_task_purge
isc_task_purgeevent
isc_task_purgerange
@ -653,9 +651,8 @@ isc_task_setprivilege
isc_task_shutdown
isc_task_unpause
isc_task_unsend
isc_taskmgr_create
isc_taskmgr_destroy
isc_taskmgr_excltask
isc_taskmgr_mode
@IF NOTYET
isc_taskmgr_renderjson
@END NOTYET
@ -663,6 +660,7 @@ isc_taskmgr_renderjson
isc_taskmgr_renderxml
@END LIBXML2
isc_taskmgr_setexcltask
isc_taskmgr_setmode
isc_taskpool_create
isc_taskpool_destroy
isc_taskpool_expand
@ -706,8 +704,6 @@ isc_timer_detach
isc_timer_gettype
isc_timer_reset
isc_timer_touch
isc_timermgr_create
isc_timermgr_destroy
isc_timermgr_poke
isc_tls_get_http2_alpn
isc_tls_create

View file

@ -44,6 +44,9 @@
<ClInclude Include="..\include\isc\backtrace.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isc\barrier.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isc\base32.h">
<Filter>Library Header Files</Filter>
</ClInclude>
@ -140,6 +143,9 @@
<ClInclude Include="..\include\isc\magic.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isc\managers.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isc\mem.h">
<Filter>Library Header Files</Filter>
</ClInclude>
@ -530,6 +536,9 @@
<ClCompile Include="..\log.c">
<Filter>Library Source Files</Filter>
</ClCompile>
<ClCompile Include="..\managers.c">
<Filter>Library Source Files</Filter>
</ClCompile>
<ClCompile Include="..\mem.c">
<Filter>Library Source Files</Filter>
</ClCompile>

View file

@ -269,6 +269,7 @@ copy InstallFiles ..\Build\Release\
<ClInclude Include="..\include\isc\astack.h" />
<ClInclude Include="..\include\isc\atomic.h" />
<ClInclude Include="..\include\isc\backtrace.h" />
<ClInclude Include="..\include\isc\barrier.h" />
<ClInclude Include="..\include\isc\base32.h" />
<ClInclude Include="..\include\isc\base64.h" />
<ClInclude Include="..\include\isc\bind9.h" />
@ -302,6 +303,7 @@ copy InstallFiles ..\Build\Release\
<ClInclude Include="..\include\isc\list.h" />
<ClInclude Include="..\include\isc\log.h" />
<ClInclude Include="..\include\isc\magic.h" />
<ClInclude Include="..\include\isc\managers.h" />
<ClInclude Include="..\include\isc\md.h" />
<ClInclude Include="..\include\isc\mem.h" />
<ClInclude Include="..\include\isc\meminfo.h" />
@ -412,6 +414,7 @@ copy InstallFiles ..\Build\Release\
<ClCompile Include="..\lex.c" />
<ClCompile Include="..\lib.c" />
<ClCompile Include="..\log.c" />
<ClCompile Include="..\managers.c" />
<ClCompile Include="..\md.c" />
<ClCompile Include="..\mem.c" />
<ClCompile Include="..\mutexblock.c" />

View file

@ -82,6 +82,7 @@
#endif /* HAVE_LIBXML2 */
#include "errno2result.h"
#include "socket_p.h"
/*
* Set by the -T dscp option on the command line. If set to a value
@ -2548,12 +2549,7 @@ SocketIoThread(LPVOID ThreadContext) {
* Create a new socket manager.
*/
isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
return (isc_socketmgr_create2(mctx, managerp, 0, 1));
}
isc_result_t
isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp,
unsigned int maxsocks, int nthreads) {
isc_socketmgr_t *manager;
@ -2611,7 +2607,7 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
}
void
isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
isc_socketmgr_t *manager;
/*

View file

@ -1629,15 +1629,13 @@ ns__client_put_cb(void *client0) {
void
ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *arg) {
ns_client_t *client;
ns_clientmgr_t *mgr;
ns_interface_t *ifp;
ns_client_t *client = NULL;
isc_result_t result;
isc_result_t sigresult = ISC_R_SUCCESS;
isc_buffer_t *buffer;
isc_buffer_t *buffer = NULL;
isc_buffer_t tbuffer;
dns_rdataset_t *opt;
const dns_name_t *signame;
dns_rdataset_t *opt = NULL;
const dns_name_t *signame = NULL;
bool ra; /* Recursion available. */
isc_netaddr_t netaddr;
int match;
@ -1645,29 +1643,24 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
unsigned int flags;
bool notimp;
size_t reqsize;
dns_aclenv_t *env;
dns_aclenv_t *env = NULL;
#ifdef HAVE_DNSTAP
dns_dtmsgtype_t dtmsgtype;
#endif /* ifdef HAVE_DNSTAP */
ifp = (ns_interface_t *)arg;
if (eresult != ISC_R_SUCCESS) {
return;
}
mgr = ifp->clientmgr;
if (mgr == NULL) {
/* The interface was shut down in the meantime, just bail */
return;
}
REQUIRE(VALID_MANAGER(mgr));
client = isc_nmhandle_getdata(handle);
if (client == NULL) {
ns_interface_t *ifp = (ns_interface_t *)arg;
INSIST(VALID_MANAGER(ifp->clientmgr));
client = isc_nmhandle_getextra(handle);
result = ns__client_setup(client, mgr, true);
result = ns__client_setup(client, ifp->clientmgr, true);
if (result != ISC_R_SUCCESS) {
return;
}

View file

@ -22,6 +22,7 @@
#include <isc/buffer.h>
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/netmgr.h>
#include <isc/os.h>
@ -56,7 +57,6 @@ isc_taskmgr_t *taskmgr = NULL;
isc_task_t *maintask = NULL;
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
isc_nm_t *nm = NULL;
dns_zonemgr_t *zonemgr = NULL;
dns_dispatchmgr_t *dispatchmgr = NULL;
ns_clientmgr_t *clientmgr = NULL;
@ -198,28 +198,12 @@ cleanup_managers(void) {
if (interfacemgr != NULL) {
ns_interfacemgr_detach(&interfacemgr);
}
if (socketmgr != NULL) {
isc_socketmgr_destroy(&socketmgr);
}
ns_test_nap(500000);
if (nm != NULL) {
/*
* Force something in the workqueue as a workaround
* for libuv bug - not sending uv_close callback.
*/
isc_nm_pause(nm);
isc_nm_resume(nm);
isc_nm_detach(&nm);
}
if (taskmgr != NULL) {
isc_taskmgr_destroy(&taskmgr);
}
if (netmgr != NULL) {
isc_nm_destroy(&netmgr);
}
if (timermgr != NULL) {
isc_timermgr_destroy(&timermgr);
}
isc_managers_destroy(netmgr == NULL ? NULL : &netmgr,
taskmgr == NULL ? NULL : &taskmgr,
timermgr == NULL ? NULL : &timermgr,
socketmgr == NULL ? NULL : &socketmgr);
if (app_running) {
isc_app_finish();
}
@ -241,24 +225,18 @@ create_managers(void) {
isc_event_t *event = NULL;
ncpus = isc_os_ncpus();
netmgr = isc_nm_start(mctx, ncpus);
CHECK(isc_taskmgr_create(mctx, 0, netmgr, &taskmgr));
CHECK(isc_task_create(taskmgr, 0, &maintask));
isc_managers_create(mctx, ncpus, 0, 0, &netmgr, &taskmgr, &timermgr,
&socketmgr);
CHECK(isc_task_create_bound(taskmgr, 0, &maintask, 0));
isc_taskmgr_setexcltask(taskmgr, maintask);
CHECK(isc_task_onshutdown(maintask, shutdown_managers, NULL));
CHECK(isc_timermgr_create(mctx, &timermgr));
CHECK(isc_socketmgr_create(mctx, &socketmgr));
nm = isc_nm_start(mctx, ncpus);
CHECK(ns_server_create(mctx, matchview, &sctx));
CHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
CHECK(ns_interfacemgr_create(mctx, sctx, taskmgr, timermgr, socketmgr,
nm, dispatchmgr, maintask, ncpus, NULL,
netmgr, dispatchmgr, maintask, ncpus, NULL,
ncpus, &interfacemgr));
CHECK(ns_listenlist_default(mctx, port, -1, true, &listenon));

View file

@ -1852,6 +1852,7 @@
./lib/isc/include/isc/atomic.h C 2018,2019,2020,2021
./lib/isc/include/isc/attributes.h C 2020,2021
./lib/isc/include/isc/backtrace.h C 2009,2016,2018,2019,2020,2021
./lib/isc/include/isc/barrier.h C 2021
./lib/isc/include/isc/base32.h C 2008,2014,2016,2018,2019,2020,2021
./lib/isc/include/isc/base64.h C 1999,2000,2001,2004,2005,2006,2007,2016,2018,2019,2020,2021
./lib/isc/include/isc/bind9.h C 2009,2013,2016,2018,2019,2020,2021
@ -1887,6 +1888,7 @@
./lib/isc/include/isc/list.h C 1997,1998,1999,2000,2001,2002,2004,2006,2007,2011,2012,2013,2016,2018,2019,2020,2021
./lib/isc/include/isc/log.h C 1999,2000,2001,2002,2004,2005,2006,2007,2009,2014,2016,2017,2018,2019,2020,2021
./lib/isc/include/isc/magic.h C 1999,2000,2001,2004,2005,2006,2007,2016,2017,2018,2019,2020,2021
./lib/isc/include/isc/managers.h C 2021
./lib/isc/include/isc/md.h C 2018,2019,2020,2021
./lib/isc/include/isc/mem.h C 1997,1998,1999,2000,2001,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2015,2016,2017,2018,2019,2020,2021
./lib/isc/include/isc/meminfo.h C 2015,2016,2018,2019,2020,2021
@ -1944,6 +1946,7 @@
./lib/isc/lib.c C 1999,2000,2001,2004,2005,2007,2009,2013,2014,2015,2016,2018,2019,2020,2021
./lib/isc/lib_p.h C 2021
./lib/isc/log.c C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2009,2011,2012,2013,2014,2016,2017,2018,2019,2020,2021
./lib/isc/managers.c C 2021
./lib/isc/md.c C 2018,2019,2020,2021
./lib/isc/mem.c C 1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
./lib/isc/mem_p.h C 2018,2019,2020,2021
@ -1960,6 +1963,7 @@
./lib/isc/netmgr/uv-compat.c C 2020,2021
./lib/isc/netmgr/uv-compat.h C 2019,2020,2021
./lib/isc/netmgr/uverr2result.c C 2019,2020,2021
./lib/isc/netmgr_p.h C 2021
./lib/isc/netscope.c C 2002,2004,2005,2006,2007,2016,2018,2019,2020,2021
./lib/isc/nonce.c C 2018,2019,2020,2021
./lib/isc/openssl_shim.c C 2018,2019,2020,2021
@ -1989,10 +1993,12 @@
./lib/isc/serial.c C 1999,2000,2001,2004,2005,2007,2016,2018,2019,2020,2021
./lib/isc/siphash.c C 2019,2020,2021
./lib/isc/sockaddr.c C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2010,2011,2012,2014,2015,2016,2017,2018,2019,2020,2021
./lib/isc/socket_p.h C 2021
./lib/isc/stats.c C 2009,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
./lib/isc/string.c C 1999,2000,2001,2003,2004,2005,2006,2007,2011,2012,2014,2015,2016,2018,2019,2020,2021
./lib/isc/symtab.c C 1996,1997,1998,1999,2000,2001,2004,2005,2007,2011,2012,2013,2016,2018,2019,2020,2021
./lib/isc/task.c C 1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
./lib/isc/task_p.h C 2021
./lib/isc/taskpool.c C 1999,2000,2001,2004,2005,2007,2011,2012,2013,2016,2018,2019,2020,2021
./lib/isc/tests/aes_test.c C 2014,2016,2018,2019,2020,2021
./lib/isc/tests/buffer_test.c C 2014,2015,2016,2017,2018,2019,2020,2021
@ -2031,6 +2037,7 @@
./lib/isc/tests/timer_test.c C 2018,2019,2020,2021
./lib/isc/tests/uv_wrap.h C 2020,2021
./lib/isc/timer.c C 1998,1999,2000,2001,2002,2004,2005,2007,2008,2009,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
./lib/isc/timer_p.h C 2021
./lib/isc/tls.c C 2021
./lib/isc/tls_p.h C 2021
./lib/isc/tm.c C 2014,2016,2018,2019,2020,2021
@ -2059,7 +2066,6 @@
./lib/isc/unix/pk11_api.c C 2014,2016,2018,2019,2020,2021
./lib/isc/unix/resource.c C 2000,2001,2004,2007,2008,2009,2016,2018,2019,2020,2021
./lib/isc/unix/socket.c C 1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
./lib/isc/unix/socket_p.h C 2000,2001,2004,2005,2007,2008,2009,2016,2018,2019,2020,2021
./lib/isc/unix/stdio.c C 2000,2001,2004,2007,2011,2012,2013,2014,2016,2018,2019,2020,2021
./lib/isc/unix/stdtime.c C 1999,2000,2001,2004,2005,2007,2016,2018,2019,2020,2021
./lib/isc/unix/syslog.c C 2001,2004,2005,2007,2016,2018,2019,2020,2021