dns_rdataset_t *rdataset;
dns_namelist_t namelist;
unsigned int resopt;
+ isc_loopmgr_t *loopmgr = NULL;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
- isc_timermgr_t *timermgr = NULL;
dns_master_style_t *style = NULL;
progname = argv[0];
fatal("dst_lib_init failed: %d", result);
}
- isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, &timermgr);
+ isc_managers_create(mctx, 1, 0, &loopmgr, &netmgr, &taskmgr);
parse_args(argc, argv);
setup_logging(stderr);
/* Create client */
- result = dns_client_create(mctx, taskmgr, netmgr, timermgr, 0, &client,
+ result = dns_client_create(mctx, loopmgr, taskmgr, netmgr, 0, &client,
srcaddr4, srcaddr6);
if (result != ISC_R_SUCCESS) {
delv_log(ISC_LOG_ERROR, "dns_client_create: %s",
dns_client_detach(&client);
}
- isc_managers_destroy(&netmgr, &taskmgr, &timermgr);
+ isc_managers_destroy(&loopmgr, &netmgr, &taskmgr);
if (lctx != NULL) {
isc_log_destroy(&lctx);
#include <stdlib.h>
#include <time.h>
-#include <isc/app.h>
#include <isc/attributes.h>
#include <isc/dir.h>
+#include <isc/loop.h>
#include <isc/netaddr.h>
#include <isc/parseint.h>
#include <isc/print.h>
dig_lookup_t *default_lookup = NULL;
-static atomic_uintptr_t batchname = 0;
+static char *batchname = NULL;
static FILE *batchfp = NULL;
static char *argv0;
static int addresscount = 0;
}
return (value_from_next);
case 'f':
- atomic_store(&batchname, (uintptr_t)value);
+ batchname = value;
return (value_from_next);
case 'k':
strlcpy(keyfile, value, sizeof(keyfile));
* first entry, then trust the callback in dighost_shutdown
* to get the rest
*/
- char *filename = (char *)atomic_load(&batchname);
+ char *filename = batchname;
if ((filename != NULL) && !(is_batchfile)) {
if (strcmp(filename, "-") == 0) {
batchfp = stdin;
static void
query_finished(void) {
char batchline[MXNAME];
- int bargc;
- char *bargv[16];
-
- if (atomic_load(&batchname) == 0) {
- isc_app_shutdown();
- return;
- }
fflush(stdout);
- if (feof(batchfp)) {
- atomic_store(&batchname, 0);
- isc_app_shutdown();
- if (batchfp != stdin) {
- fclose(batchfp);
- }
- return;
- }
- if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ if (batchname != NULL && !feof(batchfp) &&
+ fgets(batchline, sizeof(batchline), batchfp) != NULL)
+ {
+ int bargc;
+ char *bargv[16];
debug("batch line %s", batchline);
bargc = split_batchline(batchline, bargv, 14, "batch argv");
bargv[0] = argv0;
parse_args(true, false, bargc, (char **)bargv);
start_lookup();
- } else {
- atomic_store(&batchname, 0);
+ return;
+ }
+
+ debug("shutdown");
+
+ /* We are done */
+ if (batchname != NULL) {
if (batchfp != stdin) {
fclose(batchfp);
}
- isc_app_shutdown();
- return;
+ batchname = NULL;
}
+ isc_loopmgr_shutdown(loopmgr);
}
static void
void
dig_setup(int argc, char **argv) {
- isc_result_t result;
-
ISC_LIST_INIT(lookup_list);
ISC_LIST_INIT(server_list);
ISC_LIST_INIT(search_list);
progname = argv[0];
preparse_args(argc, argv);
- result = isc_app_start();
- check_result(result, "isc_app_start");
-
setup_libs();
setup_system(ipv4only, ipv6only);
}
void
dig_startup(void) {
- isc_result_t result;
-
debug("dig_startup()");
- result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
- check_result(result, "isc_app_onrun");
- isc_app_run();
+ isc_loopmgr_setup(loopmgr, run_loop, NULL);
+ isc_loopmgr_run(loopmgr);
}
void
void
dig_shutdown(void) {
destroy_lookup(default_lookup);
- if (atomic_load(&batchname) != 0) {
- if (batchfp != stdin) {
- fclose(batchfp);
- }
- atomic_store(&batchname, 0);
- }
cancel_all();
destroy_libs();
- isc_app_finish();
}
/*% Main processing routine for dig */
#include <idn2.h>
#endif /* HAVE_LIBIDN2 */
-#include <isc/app.h>
#include <isc/base64.h>
#include <isc/file.h>
#include <isc/hex.h>
#include <isc/lang.h>
#include <isc/log.h>
+#include <isc/loop.h>
#include <isc/managers.h>
#include <isc/netaddr.h>
#include <isc/netdb.h>
#include <isc/sockaddr.h>
#include <isc/string.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/types.h>
#include <isc/util.h>
dig_serverlist_t server_list;
dig_searchlistlist_t search_list;
-static atomic_bool cancel_now = false;
+static bool cancel_now = false;
bool check_ra = false, have_ipv4 = false, have_ipv6 = false,
specified_source = false, free_now = false, usesearch = false,
isc_log_t *lctx = NULL;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
-isc_task_t *global_task = NULL;
+isc_loopmgr_t *loopmgr = NULL;
+isc_loop_t *mainloop = NULL;
isc_sockaddr_t localaddr;
isc_refcount_t sendcount = 0;
isc_refcount_t recvcount = 0;
bool debugtiming = false;
bool memdebugging = false;
char *progname = NULL;
-isc_mutex_t lookup_lock;
dig_lookup_t *current_lookup = NULL;
#define DIG_MAX_ADDRESSES 20
-/*%
- * Apply and clear locks at the event level in global task.
- * Can I get rid of these using shutdown events? XXX
- */
-#define LOCK_LOOKUP \
- { \
- debug("lock_lookup %s:%d", __FILE__, __LINE__); \
- isc_mutex_lock((&lookup_lock)); \
- debug("success"); \
- }
-#define UNLOCK_LOOKUP \
- { \
- debug("unlock_lookup %s:%d", __FILE__, __LINE__); \
- isc_mutex_unlock((&lookup_lock)); \
- }
-
static void
default_warnerr(const char *format, ...) {
va_list args;
return;
}
+ isc_loopmgr_blocking(loopmgr);
result = bind9_getaddresses(opt, 0, sockaddrs, DIG_MAX_ADDRESSES,
&count);
+ isc_loopmgr_nonblocking(loopmgr);
if (result != ISC_R_SUCCESS) {
fatal("couldn't get address for '%s': %s", opt,
isc_result_totext(result));
isc_mem_create(&mctx);
isc_mem_setname(mctx, "dig");
+ isc_managers_create(mctx, 1, 0, &loopmgr, &netmgr, &taskmgr);
+
isc_log_create(mctx, &lctx, &logconfig);
isc_log_setcontext(lctx);
dns_log_init(lctx);
isc_log_setdebuglevel(lctx, 0);
- isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, NULL);
-
- result = isc_task_create(taskmgr, 0, &global_task, 0);
- check_result(result, "isc_task_create");
- isc_task_setname(global_task, "dig", NULL);
+ mainloop = isc_loop_main(loopmgr);
result = dst_lib_init(mctx, NULL);
check_result(result, "dst_lib_init");
is_dst_up = true;
-
- isc_mutex_init(&lookup_lock);
}
typedef struct dig_ednsoptname {
INSIST(isc_refcount_current(&recvcount) == 0);
debug("shutting down");
dighost_shutdown();
+
+ if (current_lookup == NULL && keep != NULL) {
+ isc_nmhandle_detach(&keep);
+ }
}
}
start_lookup(void) {
debug("start_lookup()");
- if (atomic_load(&cancel_now)) {
+ if (cancel_now) {
return;
}
INSIST(!free_now);
- LOCK_LOOKUP;
-
isc_nmhandle_detach(&query->sendhandle);
lookup_attach(query->lookup, &l);
}
query_detach(&query);
lookup_detach(&l);
- UNLOCK_LOOKUP;
return;
} else if (eresult != ISC_R_SUCCESS) {
debug("send failed: %s", isc_result_totext(eresult));
}
check_if_done();
- UNLOCK_LOOKUP;
}
/*%
isc_tlsctx_t *tlsctx = NULL;
bool tls_mode = false;
isc_tlsctx_client_session_cache_t *sess_cache = NULL;
+ int local_timeout;
+
REQUIRE(DIG_VALID_QUERY(query));
debug("start_tcp(%p)", query);
launch_next_query(query);
query_detach(&query);
return;
- } else {
- int local_timeout = timeout * 1000;
- if (local_timeout == 0) {
- local_timeout = TCP_TIMEOUT * 1000;
- }
+ } else if (keep != NULL) {
+ isc_nmhandle_detach(&keep);
+ }
- if (keep != NULL) {
- isc_nmhandle_detach(&keep);
- }
+ if (timeout != 0) {
+ local_timeout = timeout * 1000;
+ } else {
+ local_timeout = TCP_TIMEOUT * 1000;
+ }
- if (!specified_source) {
- if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
- have_ipv4) {
- isc_sockaddr_any(&localaddr);
- } else {
- isc_sockaddr_any6(&localaddr);
- }
+ if (!specified_source) {
+ if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4)
+ {
+ isc_sockaddr_any(&localaddr);
+ } else {
+ isc_sockaddr_any6(&localaddr);
}
+ }
- REQUIRE(query != NULL);
+ REQUIRE(query != NULL);
- query_attach(query, &connectquery);
+ query_attach(query, &connectquery);
- if (tls_mode) {
- tlsctx = get_create_tls_context(connectquery, false,
+ if (tls_mode) {
+ tlsctx = get_create_tls_context(connectquery, false,
+ &sess_cache);
+ if (tlsctx == NULL) {
+ goto failure_tls;
+ }
+ isc_nm_tlsdnsconnect(netmgr, &localaddr, &query->sockaddr,
+ tcp_connected, connectquery, local_timeout,
+ tlsctx, sess_cache);
+#if HAVE_LIBNGHTTP2
+ } else if (query->lookup->https_mode) {
+ char uri[4096] = { 0 };
+ isc_nm_http_makeuri(!query->lookup->http_plain,
+ &query->sockaddr, query->userarg, port,
+ query->lookup->https_path, uri,
+ sizeof(uri));
+
+ if (!query->lookup->http_plain) {
+ tlsctx = get_create_tls_context(connectquery, true,
&sess_cache);
if (tlsctx == NULL) {
goto failure_tls;
}
- isc_nm_tlsdnsconnect(netmgr, &localaddr,
- &query->sockaddr, tcp_connected,
- connectquery, local_timeout,
- tlsctx, sess_cache);
-#if HAVE_LIBNGHTTP2
- } else if (query->lookup->https_mode) {
- char uri[4096] = { 0 };
- isc_nm_http_makeuri(!query->lookup->http_plain,
- &query->sockaddr, query->userarg,
- port, query->lookup->https_path,
- uri, sizeof(uri));
-
- if (!query->lookup->http_plain) {
- tlsctx = get_create_tls_context(
- connectquery, true, &sess_cache);
- if (tlsctx == NULL) {
- goto failure_tls;
- }
- }
-
- isc_nm_httpconnect(netmgr, &localaddr, &query->sockaddr,
- uri, !query->lookup->https_get,
- tcp_connected, connectquery, tlsctx,
- sess_cache, local_timeout);
-#endif
- } else {
- isc_nm_tcpdnsconnect(netmgr, &localaddr,
- &query->sockaddr, tcp_connected,
- connectquery, local_timeout);
}
- /* XXX: set DSCP */
+ isc_nm_httpconnect(netmgr, &localaddr, &query->sockaddr, uri,
+ !query->lookup->https_get, tcp_connected,
+ connectquery, tlsctx, sess_cache,
+ local_timeout);
+#endif
+ } else {
+ isc_nm_tcpdnsconnect(netmgr, &localaddr, &query->sockaddr,
+ tcp_connected, connectquery,
+ local_timeout);
}
+ /* XXX: set DSCP */
+
return;
failure_tls:
query->started = true;
- if (atomic_load(&cancel_now)) {
+ if (cancel_now) {
query_detach(&query);
return;
}
/*%
* Send a UDP packet to the remote nameserver, possible starting the
- * recv action as well. Also make sure that the timer is running and
- * is properly reset.
+ * recv action as well.
*/
static void
start_udp(dig_query_t *query) {
debug("force_next()");
- LOCK_LOOKUP;
INSIST(!free_now);
- if (atomic_load(&cancel_now)) {
- UNLOCK_LOOKUP;
+ if (cancel_now) {
return;
}
if (try_next_server(l)) {
lookup_detach(&l);
- UNLOCK_LOOKUP;
return;
}
isc_refcount_current(&recvcount));
query_detach(&query);
clear_current_lookup();
- UNLOCK_LOOKUP;
return;
}
cancel_lookup(l);
lookup_detach(&l);
clear_current_lookup();
- UNLOCK_LOOKUP;
}
/*%
query->started = true;
- if (atomic_load(&cancel_now)) {
+ if (cancel_now) {
query_detach(&query);
return;
}
debug("tcp_connected(%p, %s, %p)", handle, isc_result_totext(eresult),
query);
- LOCK_LOOKUP;
lookup_attach(query->lookup, &l);
if (eresult == ISC_R_CANCELED || eresult == ISC_R_TLSBADPEERCERT ||
query_detach(&query);
lookup_detach(&l);
clear_current_lookup();
- UNLOCK_LOOKUP;
return;
}
}
check_if_done();
- UNLOCK_LOOKUP;
return;
}
launch_next_query(query);
query_detach(&query);
lookup_detach(&l);
- UNLOCK_LOOKUP;
}
/*%
debug("recv_done(%p, %s, %p, %p)", handle, isc_result_totext(eresult),
region, arg);
- LOCK_LOOKUP;
-
isc_refcount_decrement0(&recvcount);
debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount));
query_detach(&query);
lookup_detach(&l);
clear_current_lookup();
- UNLOCK_LOOKUP;
return;
}
TIME_NOW(&query->time_recv);
}
- if ((!l->pending && !l->ns_search_only) || atomic_load(&cancel_now)) {
+ if ((!l->pending && !l->ns_search_only) || cancel_now) {
debug("no longer pending. Got %s", isc_result_totext(eresult));
goto next_lookup;
* the timeout to much longer, so brief network
* outages won't cause the XFR to abort
*/
- if (timeout != INT_MAX && query->timer != NULL) {
+ if (timeout != INT_MAX) {
unsigned int local_timeout;
if (timeout == 0) {
if (donext) {
clear_current_lookup();
}
- UNLOCK_LOOKUP;
}
/*%
get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
int count;
isc_result_t result;
- bool is_running;
- is_running = isc_app_isrunning();
- if (is_running) {
- isc_app_block();
- }
+ isc_loopmgr_blocking(loopmgr);
result = bind9_getaddresses(host, myport, sockaddr, 1, &count);
- if (is_running) {
- isc_app_unblock();
- }
+ isc_loopmgr_nonblocking(loopmgr);
if (result != ISC_R_SUCCESS) {
return (result);
}
dig_server_t *srv;
char tmp[ISC_NETADDR_FORMATSIZE];
+ isc_loopmgr_blocking(loopmgr);
result = bind9_getaddresses(host, 0, sockaddrs, DIG_MAX_ADDRESSES,
&count);
+ isc_loopmgr_nonblocking(loopmgr);
if (resultp != NULL) {
*resultp = result;
}
* Start everything in action upon task startup.
*/
void
-onrun_callback(isc_task_t *task, isc_event_t *event) {
- UNUSED(task);
+onrun_callback(void *arg) {
+ UNUSED(arg);
+
+ start_lookup();
+}
+
+void
+run_loop(void *arg) {
+ UNUSED(arg);
- isc_event_free(&event);
- LOCK_LOOKUP;
start_lookup();
- UNLOCK_LOOKUP;
}
/*%
debug("cancel_all()");
- LOCK_LOOKUP;
if (free_now) {
- UNLOCK_LOOKUP;
return;
}
- atomic_store(&cancel_now, true);
+
+ cancel_now = true;
+
while (current_lookup != NULL) {
for (q = ISC_LIST_HEAD(current_lookup->q); q != NULL; q = nq) {
nq = ISC_LIST_NEXT(q, link);
lookup_detach(&l);
l = n;
}
- UNLOCK_LOOKUP;
}
/*%
*/
void
destroy_libs(void) {
- if (keep != NULL) {
- isc_nmhandle_detach(&keep);
- }
debug("destroy_libs()");
- if (global_task != NULL) {
- debug("freeing task");
- isc_task_detach(&global_task);
- }
- isc_managers_destroy(&netmgr, &taskmgr, NULL);
-
- LOCK_LOOKUP;
isc_refcount_destroy(&recvcount);
isc_refcount_destroy(&sendcount);
is_dst_up = false;
}
- UNLOCK_LOOKUP;
- isc_mutex_destroy(&lookup_lock);
debug("Removing log context");
isc_log_destroy(&lctx);
if (memdebugging != 0) {
isc_mem_stats(mctx, stderr);
}
- if (mctx != NULL) {
- isc_mem_destroy(&mctx);
- }
+
+ isc_managers_destroy(&loopmgr, &netmgr, &taskmgr);
}
#ifdef HAVE_LIBIDN2
#include <isc/formatcheck.h>
#include <isc/lang.h>
#include <isc/list.h>
+#include <isc/loop.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/netmgr.h>
isc_time_t time_sent;
isc_time_t time_recv;
uint64_t byte_count;
- isc_timer_t *timer;
};
struct dig_server {
extern dns_tsigkey_t *tsigkey;
extern bool validated;
extern isc_taskmgr_t *taskmgr;
-extern isc_task_t *global_task;
+extern isc_loopmgr_t *loopmgr;
+extern isc_loop_t *mainloop;
extern bool free_now;
extern bool debugging, debugtiming, memdebugging;
extern bool keep_open;
start_lookup(void);
void
-onrun_callback(isc_task_t *task, isc_event_t *event);
+onrun_callback(void *arg);
+
+void
+run_loop(void *arg);
int
dhmain(int argc, char **argv);
#include <stdbool.h>
#include <stdlib.h>
-#include <isc/app.h>
#include <isc/attributes.h>
#include <isc/commandline.h>
+#include <isc/loop.h>
#include <isc/netaddr.h>
#include <isc/print.h>
#include <isc/string.h>
static void
host_shutdown(void) {
- (void)isc_app_shutdown();
+ isc_loopmgr_shutdown(loopmgr);
}
static void
int
main(int argc, char **argv) {
- isc_result_t result;
-
tries = 2;
ISC_LIST_INIT(lookup_list);
debug("main()");
progname = argv[0];
pre_parse_args(argc, argv);
- result = isc_app_start();
- check_result(result, "isc_app_start");
setup_libs();
setup_system(ipv4only, ipv6only);
parse_args(false, argc, argv);
} else if (keysecret[0] != 0) {
setup_text_key();
}
- result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
- check_result(result, "isc_app_onrun");
- isc_app_run();
+
+ isc_loopmgr_setup(loopmgr, run_loop, NULL);
+ isc_loopmgr_run(loopmgr);
+
cancel_all();
destroy_libs();
- isc_app_finish();
+
return ((seen_error == 0) ? 0 : 1);
}
#include <stdlib.h>
#include <unistd.h>
-#include <isc/app.h>
#include <isc/attributes.h>
#include <isc/buffer.h>
#include <isc/commandline.h>
+#include <isc/condition.h>
#include <isc/event.h>
+#include <isc/job.h>
+#include <isc/loop.h>
#include <isc/netaddr.h>
#include <isc/parseint.h>
#include <isc/print.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/util.h>
+#include <isc/work.h>
#include <dns/byaddr.h>
#include <dns/fixedname.h>
#include "dighost.h"
#include "readline.h"
+static char cmdlinebuf[COMMSIZE];
+static char *cmdline = NULL;
+
static bool short_form = true, tcpmode = false, tcpmode_set = false,
identify = false, stats = true, comments = true,
section_question = true, section_answer = true,
static bool in_use = false;
static char defclass[MXRD] = "IN";
static char deftype[MXRD] = "A";
-static isc_event_t *global_event = NULL;
static int query_error = 1, print_error = 0;
static char domainopt[DNS_NAME_MAXTEXT];
#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
-static void
-getinput(isc_task_t *task, isc_event_t *event);
-
static char *
rcode_totext(dns_rcode_t rcode) {
static char buf[sizeof("?65535")];
return (totext.deconsttext);
}
-static void
-query_finished(void) {
- isc_event_t *event = global_event;
-
- debug("dighost_shutdown()");
-
- if (!in_use) {
- isc_app_shutdown();
- return;
- }
-
- isc_task_send(global_task, &event);
-}
-
static void
printsoa(dns_rdata_t *rdata) {
dns_rdata_soa_t soa;
static isc_result_t
printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg,
bool headers) {
- char servtext[ISC_SOCKADDR_FORMATSIZE];
-
UNUSED(msgbuf);
/* I've we've gotten this far, we've reached a server. */
debug("printmessage()");
if (!default_lookups || query->lookup->rdtype == dns_rdatatype_a) {
+ char servtext[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_format(&query->sockaddr, servtext,
sizeof(servtext));
printf("Server:\t\t%s\n", query->userarg);
} else if ((strcasecmp(ptr, "server") == 0) ||
(strcasecmp(ptr, "lserver") == 0))
{
- isc_app_block();
set_nameserver(arg);
check_ra = false;
- isc_app_unblock();
show_settings(true, true);
} else if (strcasecmp(ptr, "exit") == 0) {
in_use = false;
}
static void
-get_next_command(void) {
- char cmdlinebuf[COMMSIZE];
- char *cmdline, *ptr = NULL;
+readline_next_command(void *arg) {
+ char *ptr = NULL;
- isc_app_block();
- if (interactive) {
- cmdline = ptr = readline("> ");
- if (ptr != NULL && *ptr != 0) {
- add_history(ptr);
- }
- } else {
- cmdline = fgets(cmdlinebuf, COMMSIZE, stdin);
- }
- isc_app_unblock();
- if (cmdline == NULL) {
- in_use = false;
- } else {
- do_next_command(cmdline);
+ UNUSED(arg);
+
+ isc_loopmgr_blocking(loopmgr);
+ ptr = readline("> ");
+ isc_loopmgr_nonblocking(loopmgr);
+ if (ptr == NULL) {
+ return;
}
- if (ptr != NULL) {
- free(ptr);
+
+ if (*ptr != 0) {
+ add_history(ptr);
+ strlcpy(cmdlinebuf, ptr, COMMSIZE);
+ cmdline = cmdlinebuf;
}
+ free(ptr);
+}
+
+static void
+fgets_next_command(void *arg) {
+ UNUSED(arg);
+
+ cmdline = fgets(cmdlinebuf, COMMSIZE, stdin);
}
noreturn static void
}
static void
-getinput(isc_task_t *task, isc_event_t *event) {
- UNUSED(task);
- if (global_event == NULL) {
- global_event = event;
- }
- while (in_use) {
- get_next_command();
+start_next_command(void);
+
+static void
+process_next_command(void *arg __attribute__((__unused__))) {
+ if (cmdline == NULL) {
+ in_use = false;
+ } else {
+ do_next_command(cmdline);
if (ISC_LIST_HEAD(lookup_list) != NULL) {
- start_lookup();
+ isc_job_run(loopmgr, run_loop, NULL);
return;
}
}
- isc_app_shutdown();
+
+ start_next_command();
+}
+
+static void
+start_next_command(void) {
+ isc_loop_t *loop = isc_loop_main(loopmgr);
+ if (!in_use) {
+ isc_loopmgr_shutdown(loopmgr);
+ return;
+ }
+
+ cmdline = NULL;
+
+ isc_loopmgr_pause(loopmgr);
+ if (interactive) {
+ isc_work_enqueue(loop, readline_next_command,
+ process_next_command, loop);
+ } else {
+ isc_work_enqueue(loop, fgets_next_command, process_next_command,
+ loop);
+ }
+ isc_loopmgr_resume(loopmgr);
+}
+
+static void
+read_loop(void *arg) {
+ UNUSED(arg);
+
+ start_next_command();
}
int
main(int argc, char **argv) {
- isc_result_t result;
-
interactive = isatty(0);
ISC_LIST_INIT(lookup_list);
dighost_printmessage = printmessage;
dighost_received = received;
dighost_trying = trying;
- dighost_shutdown = query_finished;
-
- result = isc_app_start();
- check_result(result, "isc_app_start");
+ dighost_shutdown = start_next_command;
setup_libs();
progname = argv[0];
set_search_domain(domainopt);
}
if (in_use) {
- result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ isc_loopmgr_setup(loopmgr, run_loop, NULL);
} else {
- result = isc_app_onrun(mctx, global_task, getinput, NULL);
+ isc_loopmgr_setup(loopmgr, read_loop, NULL);
}
- check_result(result, "isc_app_onrun");
in_use = !in_use;
- (void)isc_app_run();
+ isc_loopmgr_run(loopmgr);
puts("");
debug("done, and starting to shut down");
- if (global_event != NULL) {
- isc_event_free(&global_event);
- }
cancel_all();
destroy_libs();
- isc_app_finish();
return (query_error | print_error);
}
static unsigned int nverified = 0, nverifyfailed = 0;
static const char *directory = NULL, *dsdir = NULL;
static isc_mutex_t namelock, statslock;
+static isc_loopmgr_t *loopmgr = NULL;
static isc_nm_t *netmgr = NULL;
static isc_taskmgr_t *taskmgr = NULL;
static dns_db_t *gdb; /* The database */
print_time(outfp);
print_version(outfp);
- isc_managers_create(mctx, ntasks, 0, &netmgr, &taskmgr, NULL);
+ isc_managers_create(mctx, ntasks, 0, &loopmgr, &netmgr, &taskmgr);
main_task = NULL;
result = isc_task_create(taskmgr, 0, &main_task, 0);
for (i = 0; i < (int)ntasks; i++) {
isc_task_detach(&tasks[i]);
}
- isc_managers_destroy(&netmgr, &taskmgr, NULL);
+ isc_managers_destroy(&loopmgr, &netmgr, &taskmgr);
isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
postsign();
TIME_NOW(&sign_finish);
#include <stdbool.h>
#include <isc/log.h>
+#include <isc/loop.h>
#include <isc/net.h>
#include <isc/netmgr.h>
#include <isc/rwlock.h>
EXTERN unsigned int named_g_cpus INIT(0);
EXTERN unsigned int named_g_udpdisp INIT(0);
EXTERN isc_taskmgr_t *named_g_taskmgr INIT(NULL);
+EXTERN isc_loop_t *named_g_mainloop INIT(NULL);
+EXTERN isc_loopmgr_t *named_g_loopmgr INIT(NULL);
EXTERN dns_dispatchmgr_t *named_g_dispatchmgr INIT(NULL);
EXTERN unsigned int named_g_cpus_detected INIT(1);
* for really short timers, another for client timers, and one
* for zone timers.
*/
-EXTERN isc_timermgr_t *named_g_timermgr 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);
-EXTERN const char *named_g_product INIT(PACKAGE_NAME);
-EXTERN const char *named_g_description INIT(PACKAGE_DESCRIPTION);
-EXTERN const char *named_g_srcid INIT(PACKAGE_SRCID);
-EXTERN const char *named_g_configargs INIT(PACKAGE_CONFIGARGS);
-EXTERN const char *named_g_builder INIT(PACKAGE_BUILDER);
-EXTERN in_port_t named_g_port INIT(0);
-EXTERN in_port_t named_g_tlsport INIT(0);
-EXTERN in_port_t named_g_httpsport INIT(0);
-EXTERN in_port_t named_g_httpport INIT(0);
-EXTERN isc_dscp_t named_g_dscp INIT(-1);
+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);
+EXTERN const char *named_g_product INIT(PACKAGE_NAME);
+EXTERN const char *named_g_description INIT(PACKAGE_DESCRIPTION);
+EXTERN const char *named_g_srcid INIT(PACKAGE_SRCID);
+EXTERN const char *named_g_configargs INIT(PACKAGE_CONFIGARGS);
+EXTERN const char *named_g_builder INIT(PACKAGE_BUILDER);
+EXTERN in_port_t named_g_port INIT(0);
+EXTERN in_port_t named_g_tlsport INIT(0);
+EXTERN in_port_t named_g_httpsport INIT(0);
+EXTERN in_port_t named_g_httpport INIT(0);
+EXTERN isc_dscp_t named_g_dscp INIT(-1);
EXTERN in_port_t named_g_http_listener_clients INIT(0);
EXTERN in_port_t named_g_http_streams_per_conn INIT(0);
void
named_main_setmemstats(const char *);
+
+void
+named_main_shutdown(void *arg, int signum);
named_g_udpdisp == 1 ? "" : "s");
result = isc_managers_create(named_g_mctx, named_g_cpus,
- 0 /* quantum */, &named_g_netmgr,
- &named_g_taskmgr, &named_g_timermgr);
+ 0 /* quantum */, &named_g_loopmgr,
+ &named_g_netmgr, &named_g_taskmgr);
if (result != ISC_R_SUCCESS) {
return (result);
}
static void
destroy_managers(void) {
- isc_managers_destroy(&named_g_netmgr, &named_g_taskmgr,
- &named_g_timermgr);
+ isc_managers_destroy(&named_g_loopmgr, &named_g_netmgr,
+ &named_g_taskmgr);
}
static void
#include <isc/hmac.h>
#include <isc/httpd.h>
#include <isc/lex.h>
+#include <isc/loop.h>
#include <isc/meminfo.h>
#include <isc/netmgr.h>
#include <isc/nonce.h>
return (ISC_R_UNEXPECTED);
}
- result = dns_view_initntatable(view, named_g_taskmgr, named_g_timermgr);
+ result = dns_view_initntatable(view, named_g_taskmgr, named_g_loopmgr);
if (result != ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
#endif /* ifndef USE_DNSRPS */
result = dns_rpz_new_zones(&view->rpzs, rps_cstr, rps_cstr_size,
- view->mctx, named_g_taskmgr,
- named_g_timermgr);
+ view->mctx, named_g_loopmgr,
+ named_g_taskmgr);
if (result != ISC_R_SUCCESS) {
return (result);
}
}
CHECK(dns_catz_new_zones(&view->catzs, &ns_catz_zonemodmethods,
- view->mctx, named_g_taskmgr,
- named_g_timermgr));
+ view->mctx, named_g_taskmgr, named_g_loopmgr));
if (pview != NULL) {
old = pview->catzs;
isc_mem_create(&hmctx);
isc_mem_setname(hmctx, "cache_heap");
CHECK(dns_cache_create(cmctx, hmctx, named_g_taskmgr,
- named_g_timermgr, view->rdclass,
- cachename, "rbt", 0, NULL,
- &cache));
+ view->rdclass, cachename, "rbt",
+ 0, NULL, &cache));
isc_mem_detach(&cmctx);
isc_mem_detach(&hmctx);
}
ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH);
CHECK(dns_view_createresolver(
- view, named_g_taskmgr, ndisp, named_g_netmgr, named_g_timermgr,
+ view, named_g_loopmgr, named_g_taskmgr, ndisp, named_g_netmgr,
resopts, named_g_dispatchmgr, dispatch4, dispatch6));
if (resstats == NULL) {
CHECK(dns_dyndb_createctx(mctx, hashinit, named_g_lctx,
view, named_g_server->zonemgr,
named_g_server->task,
- named_g_timermgr, &dctx));
+ named_g_loopmgr, &dctx));
}
CHECK(configure_dyndb(dyndb, mctx, dctx));
*/
static void
-interface_timer_tick(isc_task_t *task, isc_event_t *event) {
- named_server_t *server = (named_server_t *)event->ev_arg;
- INSIST(task == server->task);
- UNUSED(task);
+interface_timer_tick(void *arg) {
+ named_server_t *server = (named_server_t *)arg;
- isc_event_free(&event);
ns_interfacemgr_scan(server->interfacemgr, false, false);
}
static void
-heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
- named_server_t *server = (named_server_t *)event->ev_arg;
- dns_view_t *view;
+heartbeat_timer_tick(void *arg) {
+ named_server_t *server = (named_server_t *)arg;
+ dns_view_t *view = NULL;
- UNUSED(task);
- isc_event_free(&event);
view = ISC_LIST_HEAD(server->viewlist);
while (view != NULL) {
dns_view_dialup(view);
void *arg) {
struct dotat_arg *dotat_arg = arg;
isc_result_t result;
- dns_view_t *view;
- isc_task_t *task;
- ns_tat_t *tat;
- isc_event_t *event;
+ dns_view_t *view = NULL;
+ isc_task_t *task = NULL;
+ ns_tat_t *tat = NULL;
+ isc_event_t *event = NULL;
REQUIRE(keytable != NULL);
REQUIRE(keynode != NULL);
task = dotat_arg->task;
tat = isc_mem_get(dotat_arg->view->mctx, sizeof(*tat));
+ *tat = (ns_tat_t){ 0 };
- tat->fetch = NULL;
- tat->mctx = NULL;
- tat->task = NULL;
- tat->view = NULL;
dns_rdataset_init(&tat->rdataset);
dns_rdataset_init(&tat->sigrdataset);
dns_name_copy(keyname, dns_fixedname_initname(&tat->keyname));
}
static void
-tat_timer_tick(isc_task_t *task, isc_event_t *event) {
+tat_timer_tick(void *arg) {
isc_result_t result;
- named_server_t *server = (named_server_t *)event->ev_arg;
- struct dotat_arg arg;
- dns_view_t *view;
+ named_server_t *server = (named_server_t *)arg;
+ struct dotat_arg dotat_arg = { 0 };
+ dns_view_t *view = NULL;
dns_keytable_t *secroots = NULL;
- isc_event_free(&event);
-
for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
view = ISC_LIST_NEXT(view, link))
{
continue;
}
- arg.view = view;
- arg.task = task;
- (void)dns_keytable_forall(secroots, dotat, &arg);
+ dotat_arg.view = view;
+ dotat_arg.task = server->task;
+ (void)dns_keytable_forall(secroots, dotat, &dotat_arg);
dns_keytable_detach(&secroots);
}
}
static void
-pps_timer_tick(isc_task_t *task, isc_event_t *event) {
+pps_timer_tick(void *arg) {
static unsigned int oldrequests = 0;
unsigned int requests = atomic_load_relaxed(&ns_client_requests);
- UNUSED(task);
- isc_event_free(&event);
+ UNUSED(arg);
/*
* Don't worry about wrapping as the overflow result will be right.
result = named_config_get(maps, "interface-interval", &obj);
INSIST(result == ISC_R_SUCCESS);
interface_interval = cfg_obj_asduration(obj);
-
if (server->interface_timer != NULL) {
if (interface_interval == 0) {
- CHECK(isc_timer_reset(server->interface_timer,
- isc_timertype_inactive, NULL,
- true));
+ isc_timer_stop(server->interface_timer);
} else if (server->interface_interval != interface_interval) {
isc_interval_set(&interval, interface_interval, 0);
- CHECK(isc_timer_reset(server->interface_timer,
- isc_timertype_ticker, &interval,
- false));
+ isc_timer_start(server->interface_timer,
+ isc_timertype_ticker, &interval);
}
}
server->interface_interval = interface_interval;
INSIST(result == ISC_R_SUCCESS);
heartbeat_interval = cfg_obj_asuint32(obj) * 60;
if (heartbeat_interval == 0) {
- CHECK(isc_timer_reset(server->heartbeat_timer,
- isc_timertype_inactive, NULL, true));
+ isc_timer_stop(server->heartbeat_timer);
} else if (server->heartbeat_interval != heartbeat_interval) {
isc_interval_set(&interval, heartbeat_interval, 0);
- CHECK(isc_timer_reset(server->heartbeat_timer,
- isc_timertype_ticker, &interval, false));
+ isc_timer_start(server->heartbeat_timer, isc_timertype_ticker,
+ &interval);
}
server->heartbeat_interval = heartbeat_interval;
isc_interval_set(&interval, 1200, 0);
- CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker,
- &interval, false));
+ isc_timer_start(server->pps_timer, isc_timertype_ticker, &interval);
isc_interval_set(&interval, named_g_tat_interval, 0);
- CHECK(isc_timer_reset(server->tat_timer, isc_timertype_ticker,
- &interval, false));
+ isc_timer_start(server->tat_timer, isc_timertype_ticker, &interval);
/*
* Write the PID file.
geoip = NULL;
#endif /* if defined(HAVE_GEOIP2) */
- CHECKFATAL(ns_interfacemgr_create(named_g_mctx, server->sctx,
- named_g_taskmgr, named_g_timermgr,
- named_g_netmgr, named_g_dispatchmgr,
- server->task, geoip, true,
- &server->interfacemgr),
+ CHECKFATAL(ns_interfacemgr_create(
+ named_g_mctx, server->sctx, named_g_taskmgr,
+ named_g_loopmgr, named_g_netmgr, named_g_dispatchmgr,
+ server->task, geoip, true, &server->interfacemgr),
"creating interface manager");
/*
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
"Disabling periodic interface re-scans timer");
} else {
- isc_timer_create(named_g_timermgr, server->task,
- interface_timer_tick, server,
+ isc_timer_create(named_g_mainloop, interface_timer_tick, server,
&server->interface_timer);
}
- isc_timer_create(named_g_timermgr, server->task, heartbeat_timer_tick,
- server, &server->heartbeat_timer);
+ isc_timer_create(named_g_mainloop, heartbeat_timer_tick, server,
+ &server->heartbeat_timer);
- isc_timer_create(named_g_timermgr, server->task, tat_timer_tick, server,
+ isc_timer_create(named_g_mainloop, tat_timer_tick, server,
&server->tat_timer);
- isc_timer_create(named_g_timermgr, server->task, pps_timer_tick, server,
+ isc_timer_create(named_g_mainloop, pps_timer_tick, server,
&server->pps_timer);
CHECKFATAL(
server->sctx->fuzznotify = named_fuzz_notify;
#endif /* ifdef ENABLE_AFL */
+ named_g_mainloop = isc_loop_main(named_g_loopmgr);
+
CHECKFATAL(
isc_app_onrun(named_g_mctx, server->task, run_server, server),
"isc_app_onrun");
server->interface_interval = 0;
server->heartbeat_interval = 0;
- CHECKFATAL(dns_zonemgr_create(named_g_mctx, named_g_taskmgr,
- named_g_timermgr, named_g_netmgr,
+ CHECKFATAL(dns_zonemgr_create(named_g_mctx, named_g_loopmgr,
+ named_g_taskmgr, named_g_netmgr,
&server->zonemgr),
"dns_zonemgr_create");
static bool tried_other_gsstsig = false;
static bool local_only = false;
static isc_nm_t *netmgr = NULL;
+static isc_loopmgr_t *loopmgr = NULL;
static isc_taskmgr_t *taskmgr = NULL;
static isc_task_t *global_task = NULL;
static isc_event_t *global_event = NULL;
irs_resconf_destroy(&resconf);
- result = isc_managers_create(gmctx, 1, 0, &netmgr, &taskmgr, NULL);
+ result = isc_managers_create(gmctx, 1, 0, &loopmgr, &netmgr, &taskmgr);
check_result(result, "isc_managers_create");
result = dns_dispatchmgr_create(gmctx, netmgr, &dispatchmgr);
UNLOCK(&answer_lock);
ddebug("Shutting down managers");
- isc_managers_destroy(&netmgr, &taskmgr, NULL);
+ isc_managers_destroy(&loopmgr, &netmgr, &taskmgr);
#if HAVE_GSSAPI
if (tsigkey != NULL) {
#include <isc/attributes.h>
#include <isc/buffer.h>
#include <isc/commandline.h>
+#include <isc/event.h>
#include <isc/file.h>
#include <isc/log.h>
#include <isc/managers.h>
bool verbose;
static isc_nm_t *netmgr = NULL;
+static isc_loopmgr_t *loopmgr = NULL;
static isc_taskmgr_t *taskmgr = NULL;
static isc_task_t *rndc_task = NULL;
serial = isc_random32();
isc_mem_create(&rndc_mctx);
- isc_managers_create(rndc_mctx, 1, 0, &netmgr, &taskmgr, NULL);
+ isc_managers_create(rndc_mctx, 1, 0, &loopmgr, &netmgr, &taskmgr);
DO("create task", isc_task_create(taskmgr, 0, &rndc_task, 0));
isc_log_create(rndc_mctx, &log, &logconfig);
isc_log_setcontext(log);
}
isc_task_detach(&rndc_task);
- isc_managers_destroy(&netmgr, &taskmgr, NULL);
+ isc_managers_destroy(&loopmgr, &netmgr, &taskmgr);
/*
* Note: when TCP connections are shut down, there will be a final
static isc_mem_t *mctx = NULL;
static isc_nm_t *netmgr = NULL;
+static isc_loopmgr_t *loopmgr = NULL;
static protocol_t protocol;
static const char *address;
isc_mem_create(&mctx);
- isc_managers_create(mctx, workers, 0, &netmgr, NULL, NULL);
+ isc_managers_create(mctx, workers, 0, &loopmgr, &netmgr, NULL);
}
static void
close(out);
}
- isc_managers_destroy(&netmgr, NULL, NULL);
+ isc_managers_destroy(&loopmgr, &netmgr, NULL);
isc_mem_destroy(&mctx);
if (tls_ctx) {
isc_tlsctx_free(&tls_ctx);
static isc_mem_t *mctx = NULL;
static isc_nm_t *netmgr = NULL;
+static isc_loopmgr_t *loopmgr = NULL;
static protocol_t protocol;
static in_port_t port;
isc_mem_create(&mctx);
- isc_managers_create(mctx, workers, 0, &netmgr, NULL, NULL);
+ isc_managers_create(mctx, workers, 0, &loopmgr, &netmgr, NULL);
}
static void
teardown(void) {
- isc_managers_destroy(&netmgr, NULL, NULL);
+ isc_managers_destroy(&loopmgr, &netmgr, NULL);
isc_mem_destroy(&mctx);
if (tls_ctx) {
isc_tlsctx_free(&tls_ctx);
isc_sockaddr_t bind_any;
isc_log_t *lctx = NULL;
isc_logconfig_t *lcfg = NULL;
+ isc_loopmgr_t *loopmgr = NULL;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_task_t *task = NULL;
fatal("can't choose between IPv4 and IPv6");
}
- isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, NULL);
+ isc_managers_create(mctx, 1, 0, &loopmgr, &netmgr, &taskmgr);
RUNCHECK(isc_task_create(taskmgr, 0, &task, 0));
RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
isc_task_detach(&task);
- isc_managers_destroy(&netmgr, &taskmgr, NULL);
+ isc_managers_destroy(&loopmgr, &netmgr, &taskmgr);
dst_lib_destroy();
#include <inttypes.h>
#include <stdbool.h>
+#include <isc/event.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/refcount.h>
static isc_result_t
cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, cache_cleaner_t *cleaner);
+ cache_cleaner_t *cleaner);
static void
incremental_cleaning_action(isc_task_t *task, isc_event_t *event);
isc_result_t
dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
- const char *cachename, const char *db_type,
- unsigned int db_argc, char **db_argv, dns_cache_t **cachep) {
+ dns_rdataclass_t rdclass, const char *cachename,
+ const char *db_type, unsigned int db_argc, char **db_argv,
+ dns_cache_t **cachep) {
isc_result_t result;
dns_cache_t *cache;
int i, extra = 0;
* need the control of the generic cleaner.
*/
if (strcmp(db_type, "rbt") == 0) {
- result = cache_cleaner_init(cache, NULL, NULL, &cache->cleaner);
+ result = cache_cleaner_init(cache, NULL, &cache->cleaner);
} else {
- result = cache_cleaner_init(cache, taskmgr, timermgr,
- &cache->cleaner);
+ result = cache_cleaner_init(cache, taskmgr, &cache->cleaner);
}
if (result != ISC_R_SUCCESS) {
goto cleanup_db;
static isc_result_t
cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, cache_cleaner_t *cleaner) {
+ cache_cleaner_t *cleaner) {
isc_result_t result;
isc_mutex_init(&cleaner->lock);
goto cleanup;
}
- if (taskmgr != NULL && timermgr != NULL) {
+ if (taskmgr != NULL) {
result = isc_task_create(taskmgr, 1, &cleaner->task, 0);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
#include <stdbool.h>
#include <isc/hex.h>
+#include <isc/loop.h>
#include <isc/md.h>
#include <isc/mem.h>
#include <isc/parseint.h>
dns_dbversion_t *dbversion;
isc_timer_t *updatetimer;
- isc_event_t updateevent;
bool active;
bool db_registered;
isc_mutex_t lock;
dns_catz_zonemodmethods_t *zmm;
isc_taskmgr_t *taskmgr;
- isc_timermgr_t *timermgr;
+ isc_loopmgr_t *loopmgr;
dns_view_t *view;
isc_task_t *updater;
};
isc_result_t
dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr) {
+ isc_loopmgr_t *loopmgr) {
dns_catz_zones_t *new_zones;
isc_result_t result;
isc_mem_attach(mctx, &new_zones->mctx);
new_zones->zmm = zmm;
- new_zones->timermgr = timermgr;
+ new_zones->loopmgr = loopmgr;
new_zones->taskmgr = taskmgr;
result = isc_task_create(taskmgr, 0, &new_zones->updater, 0);
isc_ht_init(&new_zone->coos, catzs->mctx, 4, ISC_HT_CASE_INSENSITIVE);
new_zone->updatetimer = NULL;
- isc_timer_create(catzs->timermgr, catzs->updater,
+ isc_timer_create(isc_loop_main(catzs->loopmgr),
dns_catz_update_taskaction, new_zone,
&new_zone->updatetimer);
}
void
-dns_catz_update_taskaction(isc_task_t *task, isc_event_t *event) {
+dns_catz_update_taskaction(void *arg) {
isc_result_t result;
- dns_catz_zone_t *zone;
- (void)task;
+ dns_catz_zone_t *zone = arg;
- REQUIRE(event != NULL);
- zone = event->ev_arg;
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
LOCK(&zone->catzs->lock);
zone->updatepending = false;
dns_catz_update_from_db(zone->db, zone->catzs);
- result = isc_timer_reset(zone->updatetimer, isc_timertype_inactive,
- NULL, true);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- isc_event_free(&event);
+ isc_timer_stop(zone->updatetimer);
result = isc_time_now(&zone->lastupdated);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
UNLOCK(&zone->catzs->lock);
}
if (!zone->updatepending) {
+ isc_interval_t interval;
zone->updatepending = true;
isc_time_now(&now);
tdiff = isc_time_microdiff(&now, &zone->lastupdated) / 1000000;
if (tdiff < zone->defoptions.min_update_interval) {
- isc_interval_t interval;
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
"catz: new zone version came too soon, "
zone->defoptions.min_update_interval -
(unsigned int)tdiff,
0);
- dns_db_currentversion(db, &zone->dbversion);
- result = isc_timer_reset(zone->updatetimer,
- isc_timertype_once, &interval,
- true);
- if (result != ISC_R_SUCCESS) {
- goto cleanup;
- }
} else {
- isc_event_t *event;
-
- dns_db_currentversion(db, &zone->dbversion);
- ISC_EVENT_INIT(&zone->updateevent,
- sizeof(zone->updateevent), 0,
- DNS_EVENT_CATZUPDATED,
- dns_catz_update_taskaction, zone, zone,
- NULL, NULL);
- event = &zone->updateevent;
- isc_task_send(catzs->updater, &event);
+ isc_interval_set(&interval, 0, 0);
}
+ dns_db_currentversion(db, &zone->dbversion);
+ isc_timer_start(zone->updatetimer, isc_timertype_once,
+ &interval);
} else {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
#include <isc/safe.h>
#include <isc/sockaddr.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/adb.h>
isc_taskmgr_t *taskmgr;
isc_task_t *task;
isc_nm_t *nm;
- isc_timermgr_t *timermgr;
+ isc_loopmgr_t *loopmgr;
dns_dispatchmgr_t *dispatchmgr;
dns_dispatch_t *dispatchv4;
dns_dispatch_t *dispatchv6;
static isc_result_t
createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_taskmgr_t *taskmgr,
- isc_nm_t *nm, isc_timermgr_t *timermgr,
- dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4,
- dns_dispatch_t *dispatchv6, dns_view_t **viewp) {
+ isc_nm_t *nm, isc_loopmgr_t *loopmgr, dns_dispatchmgr_t *dispatchmgr,
+ dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
+ dns_view_t **viewp) {
isc_result_t result;
dns_view_t *view = NULL;
return (result);
}
- result = dns_view_createresolver(view, taskmgr, 1, nm, timermgr, 0,
+ result = dns_view_createresolver(view, loopmgr, taskmgr, 1, nm, 0,
dispatchmgr, dispatchv4, dispatchv6);
if (result != ISC_R_SUCCESS) {
dns_view_detach(&view);
}
isc_result_t
-dns_client_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_nm_t *nm,
- isc_timermgr_t *timermgr, unsigned int options,
+dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr, isc_nm_t *nm, unsigned int options,
dns_client_t **clientp, const isc_sockaddr_t *localaddr4,
const isc_sockaddr_t *localaddr6) {
isc_result_t result;
REQUIRE(mctx != NULL);
REQUIRE(taskmgr != NULL);
- REQUIRE(timermgr != NULL);
+ REQUIRE(loopmgr != NULL);
REQUIRE(nm != NULL);
REQUIRE(clientp != NULL && *clientp == NULL);
client = isc_mem_get(mctx, sizeof(*client));
*client = (dns_client_t){
.taskmgr = taskmgr,
- .timermgr = timermgr,
+ .loopmgr = loopmgr,
.nm = nm,
};
isc_refcount_init(&client->references, 1);
/* Create the default view for class IN */
- result = createview(mctx, dns_rdataclass_in, taskmgr, nm, timermgr,
+ result = createview(mctx, dns_rdataclass_in, taskmgr, nm, loopmgr,
client->dispatchmgr, dispatchv4, dispatchv6, &view);
if (result != ISC_R_SUCCESS) {
goto cleanup_references;
isc_result_t
dns_dyndb_createctx(isc_mem_t *mctx, const void *hashinit, isc_log_t *lctx,
dns_view_t *view, dns_zonemgr_t *zmgr, isc_task_t *task,
- isc_timermgr_t *tmgr, dns_dyndbctx_t **dctxp) {
+ isc_loopmgr_t *loopmgr, dns_dyndbctx_t **dctxp) {
dns_dyndbctx_t *dctx;
REQUIRE(dctxp != NULL && *dctxp == NULL);
if (task != NULL) {
isc_task_attach(task, &dctx->task);
}
- dctx->timermgr = tmgr;
+ dctx->loopmgr = loopmgr;
dctx->hashinit = hashinit;
dctx->lctx = lctx;
dctx->refvar = &isc_bind9;
if (dctx->task != NULL) {
isc_task_detach(&dctx->task);
}
- dctx->timermgr = NULL;
+ dctx->loopmgr = NULL;
dctx->lctx = NULL;
isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx));
***/
isc_result_t
dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
- const char *cachename, const char *db_type,
- unsigned int db_argc, char **db_argv, dns_cache_t **cachep);
+ dns_rdataclass_t rdclass, const char *cachename,
+ const char *db_type, unsigned int db_argc, char **db_argv,
+ dns_cache_t **cachep);
/*%<
* Create a new DNS cache.
*
*
*\li 'cmctx' (and 'hmctx' if applicable) is a valid memory context.
*
- *\li 'taskmgr' is a valid task manager and 'timermgr' is a valid timer
- * manager, or both are NULL. If NULL, no periodic cleaning of the
- * cache will take place.
+ *\li 'taskmgr' is a valid task manager or are NULL. If NULL, no periodic
+ * cleaning of the cache will take place.
*
*\li 'cachename' is a valid string. This must not be NULL.
*
isc_result_t
dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr);
+ isc_loopmgr_t *loopmgr);
/*%<
* Allocate a new catz_zones object, a collection storing all catalog zones
* for a view.
*/
void
-dns_catz_update_taskaction(isc_task_t *task, isc_event_t *event);
+dns_catz_update_taskaction(void *arg);
/*%<
* Task that launches dns_catz_update_from_db.
*
} dns_clientresevent_t; /* too long? */
isc_result_t
-dns_client_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_nm_t *nm,
- isc_timermgr_t *timermgr, unsigned int options,
+dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr, isc_nm_t *nm, unsigned int options,
dns_client_t **clientp, const isc_sockaddr_t *localaddr4,
const isc_sockaddr_t *localaddr6);
/*%<
*
*\li 'nm' is a valid network manager.
*
- *\li 'timermgr' is a valid timer manager.
+ *\li 'loopmgr' is a valid loop manager.
*
*\li clientp != NULL && *clientp == NULL.
*
* function should detach from them.
*/
struct dns_dyndbctx {
- unsigned int magic;
- const void *hashinit;
- isc_mem_t *mctx;
- isc_log_t *lctx;
- dns_view_t *view;
- dns_zonemgr_t *zmgr;
- isc_task_t *task;
- isc_timermgr_t *timermgr;
- const bool *refvar;
+ unsigned int magic;
+ const void *hashinit;
+ isc_mem_t *mctx;
+ isc_log_t *lctx;
+ dns_view_t *view;
+ dns_zonemgr_t *zmgr;
+ isc_task_t *task;
+ isc_loopmgr_t *loopmgr;
+ const bool *refvar;
};
#define DNS_DYNDBCTX_MAGIC ISC_MAGIC('D', 'd', 'b', 'c')
isc_result_t
dns_dyndb_createctx(isc_mem_t *mctx, const void *hashinit, isc_log_t *lctx,
dns_view_t *view, dns_zonemgr_t *zmgr, isc_task_t *task,
- isc_timermgr_t *tmgr, dns_dyndbctx_t **dctxp);
+ isc_loopmgr_t *loopmgr, dns_dyndbctx_t **dctxp);
/*%
* Create a dyndb initialization context structure, with
* pointers to structures in the server that the dyndb module will
struct dns_ntatable {
/* Unlocked. */
- unsigned int magic;
- dns_view_t *view;
- isc_rwlock_t rwlock;
- isc_taskmgr_t *taskmgr;
- isc_timermgr_t *timermgr;
- isc_task_t *task;
+ unsigned int magic;
+ dns_view_t *view;
+ isc_rwlock_t rwlock;
+ isc_taskmgr_t *taskmgr;
+ isc_loopmgr_t *loopmgr;
+ isc_task_t *task;
/* Protected by atomics */
isc_refcount_t references;
/* Locked by rwlock. */
isc_result_t
dns_ntatable_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, dns_ntatable_t **ntatablep);
+ isc_loopmgr_t *loopmgr, dns_ntatable_t **ntatablep);
/*%<
* Create an NTA table in view 'view'.
*
#define DNS_MAX_LABELS 127
isc_result_t
-dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
- unsigned int ndisp, isc_nm_t *nm, isc_timermgr_t *timermgr,
+dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr, unsigned int ndisp, isc_nm_t *nm,
unsigned int options, dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_resolver_t **resp);
*
*\li 'nm' is a valid network manager.
*
- *\li 'timermgr' is a valid timer manager.
- *
*\li 'dispatchv4' is a dispatch with an IPv4 UDP socket, or is NULL.
* If not NULL, 'ndisp' clones of it will be created by the resolver.
*
* on */
bool addsoa; /* add soa to the additional section */
isc_timer_t *updatetimer;
- isc_event_t updateevent;
};
/*
*/
dns_rpz_triggers_t total_triggers;
- isc_mem_t *mctx;
- isc_taskmgr_t *taskmgr;
- isc_timermgr_t *timermgr;
- isc_task_t *updater;
- isc_refcount_t refs;
- isc_refcount_t irefs;
+ isc_mem_t *mctx;
+ isc_loopmgr_t *loopmgr;
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *updater;
+ isc_refcount_t refs;
+ isc_refcount_t irefs;
/*
* One lock for short term read-only search that guarantees the
* consistency of the pointers.
isc_result_t
dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, char *rps_cstr, size_t rps_cstr_size,
- isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr);
+ isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr);
isc_result_t
dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp);
*/
isc_result_t
-dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr,
- unsigned int ndisp, isc_nm_t *nm,
- isc_timermgr_t *timermgr, unsigned int options,
+dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr, unsigned int ndisp,
+ isc_nm_t *netmgr, unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6);
/*%<
*\li 'view' does not have a resolver already.
*
*\li The requirements of dns_resolver_create() apply to 'taskmgr',
- * 'ntasks', 'nm', 'timermgr', 'options', 'dispatchv4', and
- * 'dispatchv6'.
+ * 'ndisp', 'netmgr', 'options', 'dispatchv4', and 'dispatchv6'.
*
* Returns:
*
isc_result_t
dns_view_initntatable(dns_view_t *view, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr);
+ isc_loopmgr_t *loopmgr);
/*%<
* Initialize the negative trust anchor table for the view.
*
*\li 'fd' to be a stream open for writing.
*/
-void
-dns_zone_maintenance(dns_zone_t *zone);
-/*%<
- * Perform regular maintenance on the zone. This is called as a
- * result of a zone being managed.
- *
- * Require
- *\li 'zone' to be a valid zone.
- */
-
void
dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *primaries,
dns_name_t **keynames, dns_name_t **tlsnames,
*/
isc_result_t
-dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, isc_nm_t *netmgr,
+dns_zonemgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr, isc_nm_t *netmgr,
dns_zonemgr_t **zmgrp);
/*%<
* Create a zone manager.
* Requires:
*\li 'mctx' to be a valid memory context.
*\li 'taskmgr' to be a valid task manager.
- *\li 'timermgr' to be a valid timer manager.
*\li 'zmgrp' to point to a NULL pointer.
*/
#include <stdbool.h>
#include <isc/buffer.h>
+#include <isc/event.h>
#include <isc/log.h>
+#include <isc/loop.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
isc_refcount_destroy(&nta->refcount);
nta->magic = 0;
if (nta->timer != NULL) {
- (void)isc_timer_reset(
- nta->timer, isc_timertype_inactive, NULL, true);
+ (void)isc_timer_stop(nta->timer);
isc_timer_destroy(&nta->timer);
}
if (dns_rdataset_isassociated(&nta->rdataset)) {
isc_result_t
dns_ntatable_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, dns_ntatable_t **ntatablep) {
+ isc_loopmgr_t *loopmgr, dns_ntatable_t **ntatablep) {
dns_ntatable_t *ntatable;
isc_result_t result;
isc_rwlock_init(&ntatable->rwlock, 0, 0);
ntatable->shuttingdown = false;
- ntatable->timermgr = timermgr;
+ ntatable->loopmgr = loopmgr;
ntatable->taskmgr = taskmgr;
ntatable->view = view;
if (ntatable->task != NULL) {
isc_task_detach(&ntatable->task);
}
- ntatable->timermgr = NULL;
+ ntatable->loopmgr = NULL;
ntatable->taskmgr = NULL;
ntatable->magic = 0;
isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable));
case DNS_R_NXDOMAIN:
case DNS_R_NCACHENXRRSET:
case DNS_R_NXRRSET:
+ RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
if (nta->expiry > now) {
nta->expiry = now;
}
+ RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
break;
default:
break;
* If we're expiring before the next recheck, we might
* as well stop the timer now.
*/
+ RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
if (nta->timer != NULL && nta->expiry - now < view->nta_recheck) {
- (void)isc_timer_reset(nta->timer, isc_timertype_inactive, NULL,
- true);
+ (void)isc_timer_stop(nta->timer);
}
+ RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
+
nta_detach(view->mctx, &nta);
dns_view_weakdetach(&view);
}
static void
-checkbogus(isc_task_t *task, isc_event_t *event) {
- dns_nta_t *nta = event->ev_arg;
+checkbogus(void *arg) {
+ dns_nta_t *nta = arg;
dns_ntatable_t *ntatable = nta->ntatable;
dns_view_t *view = NULL;
isc_result_t result;
dns_rdataset_disassociate(&nta->sigrdataset);
}
- isc_event_free(&event);
-
nta_ref(nta);
dns_view_weakattach(ntatable->view, &view);
result = dns_resolver_createfetch(
view->resolver, nta->name, dns_rdatatype_nsec, NULL, NULL, NULL,
- NULL, 0, DNS_FETCHOPT_NONTA, 0, NULL, task, fetch_done, nta,
- &nta->rdataset, &nta->sigrdataset, &nta->fetch);
+ NULL, 0, DNS_FETCHOPT_NONTA, 0, NULL, ntatable->task,
+ fetch_done, nta, &nta->rdataset, &nta->sigrdataset,
+ &nta->fetch);
if (result != ISC_R_SUCCESS) {
nta_detach(view->mctx, &nta);
dns_view_weakdetach(&view);
}
}
-static isc_result_t
+static void
settimer(dns_ntatable_t *ntatable, dns_nta_t *nta, uint32_t lifetime) {
- isc_result_t result;
isc_interval_t interval;
- dns_view_t *view;
+ dns_view_t *view = NULL;
+ isc_loop_t *loop = NULL;
REQUIRE(VALID_NTATABLE(ntatable));
REQUIRE(VALID_NTA(nta));
- if (ntatable->timermgr == NULL) {
- return (ISC_R_SUCCESS);
+ if (ntatable->loopmgr == NULL) {
+ return;
}
view = ntatable->view;
if (view->nta_recheck == 0 || lifetime <= view->nta_recheck) {
- return (ISC_R_SUCCESS);
+ return;
}
- isc_timer_create(ntatable->timermgr, ntatable->task, checkbogus, nta,
- &nta->timer);
+ loop = isc_loop_main(ntatable->loopmgr);
+
+ isc_timer_create(loop, checkbogus, nta, &nta->timer);
isc_interval_set(&interval, view->nta_recheck, 0);
- result = isc_timer_reset(nta->timer, isc_timertype_ticker, &interval,
- false);
- if (result != ISC_R_SUCCESS) {
- isc_timer_destroy(&nta->timer);
- }
- return (result);
+ isc_timer_start(nta->timer, isc_timertype_ticker, &interval);
}
static isc_result_t
result = dns_rbt_addnode(ntatable->table, name, &node);
if (result == ISC_R_SUCCESS) {
if (!force) {
- (void)settimer(ntatable, nta, lifetime);
+ settimer(ntatable, nta, lifetime);
}
node->data = nta;
nta = NULL;
dns_nta_t *n = node->data;
if (n == NULL) {
if (!force) {
- (void)settimer(ntatable, nta, lifetime);
+ settimer(ntatable, nta, lifetime);
}
node->data = nta;
nta = NULL;
"deleting expired NTA at %s", nb);
if (nta->timer != NULL) {
- (void)isc_timer_reset(
- nta->timer, isc_timertype_inactive, NULL, true);
+ (void)isc_timer_stop(nta->timer);
isc_timer_destroy(&nta->timer);
}
if (node->data != NULL) {
dns_nta_t *nta = (dns_nta_t *)node->data;
if (nta->timer != NULL) {
- (void)isc_timer_reset(nta->timer,
- isc_timertype_inactive,
- NULL, true);
+ (void)isc_timer_stop(nta->timer);
}
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
#include <isc/counter.h>
#include <isc/hash.h>
#include <isc/log.h>
+#include <isc/loop.h>
#include <isc/print.h>
#include <isc/random.h>
#include <isc/refcount.h>
#include <isc/stats.h>
#include <isc/string.h>
#include <isc/task.h>
+#include <isc/tid.h>
#include <isc/timer.h>
#include <isc/util.h>
dns_name_t *domain;
dns_rdataset_t nameservers;
atomic_uint_fast32_t attributes;
+ isc_loop_t *loop;
isc_timer_t *timer;
isc_time_t expires;
isc_time_t expires_try_stale;
isc_mutex_t lock;
isc_mutex_t primelock;
dns_rdataclass_t rdclass;
+ isc_loopmgr_t *loopmgr;
isc_nm_t *nm;
- isc_timermgr_t *timermgr;
isc_taskmgr_t *taskmgr;
dns_view_t *view;
bool frozen;
* trigger if, for example, some ADB or validator dependency
* loop occurs and causes a fetch to hang.
*/
-static isc_result_t
+static void
fctx_starttimer(fetchctx_t *fctx) {
isc_interval_t interval;
isc_time_t now;
isc_time_subtract(&expires, &now, &interval);
}
- return (isc_timer_reset(fctx->timer, isc_timertype_once, &interval,
- true));
+ isc_timer_start(fctx->timer, isc_timertype_once, &interval);
}
static void
fctx_stoptimer(fetchctx_t *fctx) {
- isc_result_t result;
-
/*
* We don't return a result if resetting the timer to inactive fails
* since there's nothing to be done about it. Resetting to inactive
* should never fail anyway, since the code as currently written
* cannot fail in that case.
*/
- result = isc_timer_reset(fctx->timer, isc_timertype_inactive, NULL,
- true);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_timer_reset(): %s",
- isc_result_totext(result));
- }
+ isc_timer_stop(fctx->timer);
}
static void
logit = true;
}
isc_interval_set(&i, 20 * 60, 0);
- result = isc_timer_reset(fctx->res->spillattimer,
- isc_timertype_ticker, &i,
- true);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_timer_start(fctx->res->spillattimer,
+ isc_timertype_ticker, &i);
}
UNLOCK(&fctx->res->lock);
if (logit) {
fctx_detach(&fctx);
}
+static void
+fctx_expired(void *arg) {
+ fetchctx_t *fctx = (fetchctx_t *)arg;
+
+ REQUIRE(VALID_FCTX(fctx));
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
+ "shut down hung fetch while resolving %p(%s)", fctx,
+ fctx->info);
+ fctx_shutdown(fctx);
+}
+
static void
fctx_start(isc_task_t *task, isc_event_t *event) {
fetchctx_t *fctx = event->ev_arg;
- isc_result_t result;
REQUIRE(VALID_FCTX(fctx));
LOCK(&fctx->bucket->lock);
+ /*
+ * Create an inactive timer to enforce maximum query
+ * lifetime. It will be made active when the fetch is
+ * started.
+ */
+ isc_timer_create(fctx->loop, fctx_expired, fctx, &fctx->timer);
+
INSIST(fctx->state == fetchstate_init);
if (atomic_load_acquire(&fctx->want_shutdown)) {
/*
* should be enough of a gap to avoid the timer firing
* while a response is being processed normally.)
*/
- result = fctx_starttimer(fctx);
- if (result != ISC_R_SUCCESS) {
- fctx_done_detach(&fctx, result);
- } else {
- fctx_try(fctx, false, false);
- }
+ fctx_starttimer(fctx);
+ fctx_try(fctx, false, false);
}
/*
where, namebuf, domainbuf, fctx->ns_ttl_ok, fctx->ns_ttl);
}
-static void
-fctx_expired(isc_task_t *task, isc_event_t *event) {
- fetchctx_t *fctx = event->ev_arg;
-
- REQUIRE(VALID_FCTX(fctx));
-
- UNUSED(task);
-
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
- DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
- "shut down hung fetch while resolving '%s'", fctx->info);
- LOCK(&fctx->bucket->lock);
- fctx_shutdown(fctx);
- UNLOCK(&fctx->bucket->lock);
- isc_event_free(&event);
-}
-
static isc_result_t
fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
const dns_name_t *domain, dns_rdataset_t *nameservers,
isc_interval_t interval;
unsigned int findoptions = 0;
char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 1];
- int tid = isc_nm_tid();
+ int tid = isc_tid();
uint_fast32_t nfctx;
size_t p;
- if (tid == ISC_NETMGR_TID_UNKNOWN) {
- tid = 0;
- }
-
/*
* Caller must be holding the lock for 'bucket'
*/
.fwdpolicy = dns_fwdpolicy_none,
.result = ISC_R_FAILURE,
.exitline = -1, /* sentinel */
+ .loop = isc_loop_get(res->loopmgr, tid),
};
dns_resolver_attach(res, &fctx->res);
goto cleanup_qmessage;
}
- /*
- * Create an inactive timer to enforce maximum query
- * lifetime. It will be made active when the fetch is
- * started.
- */
- isc_timer_create(res->timermgr, fctx->restask, fctx_expired, fctx,
- &fctx->timer);
-
/*
* Default retry interval initialization. We set the interval
* now mostly so it won't be uninitialized. It will be set to
}
static void
-spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
- dns_resolver_t *res = event->ev_arg;
- isc_result_t result;
+spillattimer_countdown(void *arg) {
+ dns_resolver_t *res = (dns_resolver_t *)arg;
unsigned int count;
bool logit = false;
REQUIRE(VALID_RESOLVER(res));
- UNUSED(task);
-
LOCK(&res->lock);
INSIST(!atomic_load_acquire(&res->exiting));
if (res->spillat > res->spillatmin) {
logit = true;
}
if (res->spillat <= res->spillatmin) {
- result = isc_timer_reset(res->spillattimer,
- isc_timertype_inactive, NULL, true);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_timer_stop(res->spillattimer);
}
count = res->spillat;
UNLOCK(&res->lock);
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
"clients-per-query decreased to %u", count);
}
-
- isc_event_free(&event);
}
isc_result_t
-dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
- unsigned int ndisp, isc_nm_t *nm, isc_timermgr_t *timermgr,
+dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr, unsigned int ndisp, isc_nm_t *nm,
unsigned int options, dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_resolver_t **resp) {
isc_result_t result = ISC_R_SUCCESS;
char name[sizeof("res4294967295")];
dns_resolver_t *res = NULL;
- isc_task_t *task = NULL;
+ isc_loop_t *loop = NULL;
/*
* Create a resolver.
REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
RTRACE("create");
+
res = isc_mem_get(view->mctx, sizeof(*res));
- *res = (dns_resolver_t){ .rdclass = view->rdclass,
- .nm = nm,
- .timermgr = timermgr,
- .taskmgr = taskmgr,
- .dispatchmgr = dispatchmgr,
- .options = options,
- .ntasks = isc_nm_getnworkers(nm),
- .udpsize = DEFAULT_EDNS_BUFSIZE,
- .spillatmin = 10,
- .spillat = 10,
- .spillatmax = 100,
- .retryinterval = 10000,
- .nonbackofftries = 3,
- .query_timeout = DEFAULT_QUERY_TIMEOUT,
- .maxdepth = DEFAULT_RECURSION_DEPTH,
- .maxqueries = DEFAULT_MAX_QUERIES,
- .querydscp4 = -1,
- .querydscp6 = -1 };
+ *res = (dns_resolver_t){
+ .loopmgr = loopmgr,
+ .rdclass = view->rdclass,
+ .nm = nm,
+ .taskmgr = taskmgr,
+ .dispatchmgr = dispatchmgr,
+ .options = options,
+ .udpsize = DEFAULT_EDNS_BUFSIZE,
+ .spillatmin = 10,
+ .spillat = 10,
+ .spillatmax = 100,
+ .retryinterval = 10000,
+ .nonbackofftries = 3,
+ .query_timeout = DEFAULT_QUERY_TIMEOUT,
+ .maxdepth = DEFAULT_RECURSION_DEPTH,
+ .maxqueries = DEFAULT_MAX_QUERIES,
+ .ntasks = isc_loopmgr_nloops(loopmgr),
+ .querydscp4 = -1,
+ .querydscp6 = -1,
+ };
dns_view_weakattach(view, &res->view);
isc_mem_attach(view->mctx, &res->mctx);
isc_mutex_init(&res->lock);
isc_mutex_init(&res->primelock);
- result = isc_task_create(taskmgr, 0, &task, 0);
- if (result != ISC_R_SUCCESS) {
- goto cleanup_primelock;
- }
- isc_task_setname(task, "resolver_task", NULL);
+ loop = isc_loop_main(res->loopmgr);
- isc_timer_create(timermgr, task, spillattimer_countdown, res,
- &res->spillattimer);
- isc_task_detach(&task);
+ isc_timer_create(loop, spillattimer_countdown, res, &res->spillattimer);
res->magic = RES_MAGIC;
return (ISC_R_SUCCESS);
-cleanup_primelock:
- isc_mutex_destroy(&res->primelock);
- isc_mutex_destroy(&res->lock);
-
- if (res->dispatches6 != NULL) {
- dns_dispatchset_destroy(&res->dispatches6);
- }
- if (res->dispatches4 != NULL) {
- dns_dispatchset_destroy(&res->dispatches4);
- }
-
- isc_rwlock_destroy(&res->zonehash_lock);
- isc_ht_destroy(&res->zonebuckets);
-
- isc_rwlock_destroy(&res->hash_lock);
- isc_ht_destroy(&res->buckets);
-
cleanup_tasks:
for (size_t i = 0; i < res->ntasks; i++) {
if (res->tasks[i] != NULL) {
isc_ht_iter_destroy(&it);
RWUNLOCK(&res->hash_lock, isc_rwlocktype_read);
- result = isc_timer_reset(res->spillattimer,
- isc_timertype_inactive, NULL, true);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_timer_stop(res->spillattimer);
}
}
#include <stdlib.h>
#include <isc/buffer.h>
+#include <isc/loop.h>
#include <isc/mem.h>
#include <isc/net.h>
#include <isc/netaddr.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/util.h>
+#include <isc/work.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
update_from_db(dns_rpz_zone_t *rpz);
static void
-dns_rpz_update_taskaction(isc_task_t *task, isc_event_t *event);
+dns_rpz_update_taskaction(void *);
/*
* Use a private definition of IPv6 addresses because s6_addr32 is not
*/
isc_result_t
dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, char *rps_cstr, size_t rps_cstr_size,
- isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr) {
+ isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr) {
dns_rpz_zones_t *rpzs = NULL;
isc_result_t result = ISC_R_SUCCESS;
*rpzs = (dns_rpz_zones_t){
.rps_cstr = rps_cstr,
.rps_cstr_size = rps_cstr_size,
- .timermgr = timermgr,
+ .loopmgr = loopmgr,
.taskmgr = taskmgr,
};
.addsoa = true,
};
- isc_timer_create(rpzs->timermgr, rpzs->updater,
+ isc_timer_create(isc_loop_main(rpzs->loopmgr),
dns_rpz_update_taskaction, rpz, &rpz->updatetimer);
isc_refcount_init(&rpz->refs, 1);
rpz_attach_rpzs(rpzs, &rpz->rpzs);
- ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0, 0, NULL,
- NULL, NULL, NULL, NULL);
-
rpz->num = rpzs->p.num_zones++;
rpzs->zones[rpz->num] = rpz;
if (!rpz->updatepending && !rpz->updaterunning) {
uint64_t tdiff;
+ isc_interval_t interval;
rpz->updatepending = true;
tdiff = isc_time_microdiff(&now, &rpz->lastupdated) / 1000000;
if (tdiff < rpz->min_update_interval) {
uint64_t defer = rpz->min_update_interval - tdiff;
- isc_interval_t interval;
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
"rpz: %s: new zone version came "
"%" PRIu64 " seconds",
dname, defer);
isc_interval_set(&interval, (unsigned int)defer, 0);
- dns_db_currentversion(rpz->db, &rpz->dbversion);
- result = isc_timer_reset(rpz->updatetimer,
- isc_timertype_once, &interval,
- true);
} else {
- isc_event_t *event = NULL;
-
- dns_db_currentversion(rpz->db, &rpz->dbversion);
- INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
- ISC_EVENT_INIT(
- &rpz->updateevent, sizeof(rpz->updateevent), 0,
- DNS_EVENT_RPZUPDATED, dns_rpz_update_taskaction,
- rpz, rpz, NULL, NULL);
- event = &rpz->updateevent;
- isc_task_send(rpz->rpzs->updater, &event);
+ isc_interval_set(&interval, 0, 0);
}
+ dns_db_currentversion(rpz->db, &rpz->dbversion);
+ isc_timer_start(rpz->updatetimer, isc_timertype_once,
+ &interval);
} else {
rpz->updatepending = true;
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
}
static void
-dns_rpz_update_taskaction(isc_task_t *task, isc_event_t *event) {
+dns_rpz_update_taskaction(void *arg) {
isc_result_t result;
- dns_rpz_zone_t *rpz = NULL;
+ dns_rpz_zone_t *rpz = (dns_rpz_zone_t *)arg;
- REQUIRE(event != NULL);
- REQUIRE(event->ev_arg != NULL);
-
- UNUSED(task);
- rpz = (dns_rpz_zone_t *)event->ev_arg;
- isc_event_free(&event);
LOCK(&rpz->rpzs->maint_lock);
rpz->updatepending = false;
rpz->updaterunning = true;
update_from_db(rpz);
- result = isc_timer_reset(rpz->updatetimer, isc_timertype_inactive, NULL,
- true);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_timer_stop(rpz->updatetimer);
result = isc_time_now(&rpz->lastupdated);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
UNLOCK(&rpz->rpzs->maint_lock);
}
static void
-update_rpz_done_cb(void *data, isc_result_t result) {
+update_rpz_done_cb(void *data) {
dns_rpz_zone_t *rpz = (dns_rpz_zone_t *)data;
char dname[DNS_NAME_FORMATSIZE];
-
- if (result == ISC_R_SUCCESS && rpz->updateresult != ISC_R_SUCCESS) {
- result = rpz->updateresult;
- }
+ isc_interval_t interval;
LOCK(&rpz->rpzs->maint_lock);
rpz->updaterunning = false;
/* If there's an update pending, schedule it */
if (rpz->min_update_interval > 0) {
uint64_t defer = rpz->min_update_interval;
- isc_interval_t interval;
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
"%" PRIu64 " seconds",
dname, defer);
isc_interval_set(&interval, (unsigned int)defer, 0);
- isc_timer_reset(rpz->updatetimer, isc_timertype_once, &interval,
- true);
} else {
- isc_event_t *event = NULL;
- INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
- ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0,
- DNS_EVENT_RPZUPDATED, dns_rpz_update_taskaction,
- rpz, rpz, NULL, NULL);
- event = &rpz->updateevent;
- isc_task_send(rpz->rpzs->updater, &event);
+ isc_interval_set(&interval, 0, 0);
}
+ isc_timer_start(rpz->updatetimer, isc_timertype_once, &interval);
+
done:
dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
dns_db_detach(&rpz->updb);
UNLOCK(&rpz->rpzs->maint_lock);
- rpz_detach(&rpz);
-
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
ISC_LOG_INFO, "rpz: %s: reload done: %s", dname,
- isc_result_totext(result));
+ isc_result_totext(rpz->updateresult));
+
+ rpz_detach(&rpz);
}
static isc_result_t
char domain[DNS_NAME_FORMATSIZE];
dns_rpz_zone_t *rpz_zone = NULL;
- REQUIRE(isc_nm_tid() >= 0);
REQUIRE(rpz != NULL);
REQUIRE(DNS_DB_VALID(rpz->db));
REQUIRE(rpz->updb == NULL);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
ISC_LOG_INFO, "rpz: %s: reload start", domain);
- isc_nm_work_offload(isc_task_getnetmgr(rpz->rpzs->updater),
- update_rpz_cb, update_rpz_done_cb, rpz_zone);
+ isc_work_enqueue(isc_loop_current(rpz->rpzs->loopmgr), update_rpz_cb,
+ update_rpz_done_cb, rpz_zone);
}
/*
isc_refcount_destroy(&sdb->references);
- if (imp->methods->destroy != NULL) {
+ if (imp != NULL && imp->methods->destroy != NULL) {
MAYBE_LOCK(sdb);
imp->methods->destroy(sdb->zone, imp->driverdata, &sdb->dbdata);
MAYBE_UNLOCK(sdb);
}
isc_result_t
-dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr,
- unsigned int ndisp, isc_nm_t *nm,
- isc_timermgr_t *timermgr, unsigned int options,
+dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr, unsigned int ndisp,
+ isc_nm_t *netmgr, unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6) {
}
isc_task_setname(view->task, "view", view);
- result = dns_resolver_create(view, taskmgr, ndisp, nm, timermgr,
+ result = dns_resolver_create(view, loopmgr, taskmgr, ndisp, netmgr,
options, dispatchmgr, dispatchv4,
dispatchv6, &view->resolver);
if (result != ISC_R_SUCCESS) {
isc_result_t
dns_view_initntatable(dns_view_t *view, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr) {
+ isc_loopmgr_t *loopmgr) {
REQUIRE(DNS_VIEW_VALID(view));
if (view->ntatable_priv != NULL) {
dns_ntatable_detach(&view->ntatable_priv);
}
- return (dns_ntatable_create(view, taskmgr, timermgr,
+ return (dns_ntatable_create(view, taskmgr, loopmgr,
&view->ntatable_priv));
}
#include <inttypes.h>
#include <stdbool.h>
+#include <isc/async.h>
#include <isc/atomic.h>
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/hex.h>
+#include <isc/loop.h>
#include <isc/md.h>
#include <isc/mutex.h>
#include <isc/print.h>
/* Locked */
dns_zonemgr_t *zmgr;
ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
+ isc_loop_t *loop;
isc_timer_t *timer;
isc_refcount_t irefs;
dns_name_t origin;
uint32_t maxxfrout;
uint32_t idlein;
uint32_t idleout;
- isc_event_t ctlevent;
dns_ssutable_t *ssutable;
uint32_t sigvalidityinterval;
uint32_t keyvalidityinterval;
unsigned int magic;
isc_mem_t *mctx;
isc_refcount_t refs;
+ isc_loopmgr_t *loopmgr;
isc_taskmgr_t *taskmgr;
- isc_timermgr_t *timermgr;
isc_nm_t *netmgr;
uint32_t workers;
- isc_task_t *task;
isc_task_t **zonetasks;
isc_task_t **loadtasks;
isc_mem_t **mctxpool;
#define SEND_BUFFER_SIZE 2048
static void
-zone_timer_start(dns_zone_t *zone, isc_time_t *next, isc_time_t *now);
-static void
-zone_timer_stop(dns_zone_t *zone);
+zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now);
static void
zone_settimer(dns_zone_t *, isc_time_t *);
static void
zone_needdump(dns_zone_t *zone, unsigned int delay);
static void
-zone_shutdown(isc_task_t *, isc_event_t *);
+zone_shutdown(void *arg);
static void
zone_loaddone(void *arg, isc_result_t result);
static isc_result_t
/* Must be after magic is set. */
dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
- ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0,
- DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone, NULL,
- NULL);
*zonep = zone;
return (ISC_R_SUCCESS);
(asl->loaded)(asl->loaded_arg, zone, task);
}
- /* Reduce the quantum */
- isc_task_setquantum(zone->loadtask, 1);
-
isc_mem_put(zone->mctx, asl, sizeof(*asl));
dns_zone_idetach(&zone);
}
* up synchronously in the context of
* its task.
*/
- isc_event_t *ev = &zone->ctlevent;
- isc_task_send(zone->task, &ev);
+
+ isc_async_run(zone->loop, zone_shutdown, zone);
} else {
/*
* This zone is not being managed; it has
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
}
-/*
- * Coordinates the starting of routine jobs.
- */
-void
-dns_zone_maintenance(dns_zone_t *zone) {
- isc_time_t now;
-
- REQUIRE(DNS_ZONE_VALID(zone));
- ENTER;
-
- LOCK_ZONE(zone);
- TIME_NOW(&now);
- zone_settimer(zone, &now);
- UNLOCK_ZONE(zone);
-}
-
static bool
was_dumping(dns_zone_t *zone) {
REQUIRE(LOCKED_ZONE(zone));
}
break;
case dns_zone_primary:
+ if (zone->rss_event != NULL) {
+ isc_time_settoepoch(&zone->refreshkeytime);
+ break;
+ }
if (!isc_time_isepoch(&zone->refreshkeytime) &&
- isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
- zone->rss_event == NULL)
+ isc_time_compare(&now, &zone->refreshkeytime) >= 0)
{
zone_rekey(zone);
}
* Do we need to sign/resign some RRsets?
*/
if (zone->rss_event != NULL) {
+ isc_time_settoepoch(&zone->signingtime);
+ isc_time_settoepoch(&zone->resigntime);
+ isc_time_settoepoch(&zone->nsec3chaintime);
+ isc_time_settoepoch(&zone->keywarntime);
break;
}
if (!isc_time_isepoch(&zone->signingtime) &&
* to shut down, it is not a shutdown event in the sense of the task library.
*/
static void
-zone_shutdown(isc_task_t *task, isc_event_t *event) {
- dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
+zone_shutdown(void *arg) {
+ dns_zone_t *zone = (dns_zone_t *)arg;
bool free_needed, linked = false;
dns_zone_t *raw = NULL, *secure = NULL;
- UNUSED(task);
REQUIRE(DNS_ZONE_VALID(zone));
- INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
INSIST(isc_refcount_current(&zone->erefs) == 0);
zone_debuglog(zone, __func__, 3, "shutting down");
}
static void
-zone_timer(isc_task_t *task, isc_event_t *event) {
- dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
+zone_timer(void *arg) {
+ dns_zone_t *zone = (dns_zone_t *)arg;
- UNUSED(task);
REQUIRE(DNS_ZONE_VALID(zone));
- ENTER;
-
zone_maintenance(zone);
-
- isc_event_free(&event);
}
static void
-zone_timer_start(dns_zone_t *zone, isc_time_t *next, isc_time_t *now) {
+zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now) {
isc_interval_t interval;
- isc_result_t result;
if (isc_time_compare(next, now) <= 0) {
isc_interval_set(&interval, 0, 1);
isc_time_subtract(next, now, &interval);
}
- result = isc_timer_reset(zone->timer, isc_timertype_once, &interval,
- true);
- if (result != ISC_R_SUCCESS) {
- dns_zone_log(zone, ISC_LOG_ERROR,
- "could not reset zone timer: %s",
- isc_result_totext(result));
- }
-}
-
-static void
-zone_timer_stop(dns_zone_t *zone) {
- isc_result_t result = isc_timer_reset(
- zone->timer, isc_timertype_inactive, NULL, true);
- if (result != ISC_R_SUCCESS) {
- dns_zone_log(zone, ISC_LOG_ERROR,
- "could not deactivate zone timer: %s",
- isc_result_totext(result));
- }
+ isc_timer_start(zone->timer, isc_timertype_once, &interval);
}
static void
if (isc_time_isepoch(&next)) {
zone_debuglog(zone, __func__, 10, "settimer inactive");
- zone_timer_stop(zone);
} else {
- zone_timer_start(zone, &next, now);
+ zone_timer_set(zone, &next, now);
}
}
}
isc_result_t
-dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, isc_nm_t *netmgr,
+dns_zonemgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
+ isc_taskmgr_t *taskmgr, isc_nm_t *netmgr,
dns_zonemgr_t **zmgrp) {
dns_zonemgr_t *zmgr;
isc_result_t result;
+ isc_loop_t *mainloop = isc_loop_main(loopmgr);
REQUIRE(mctx != NULL);
+ REQUIRE(loopmgr != NULL);
REQUIRE(taskmgr != NULL);
- REQUIRE(timermgr != NULL);
REQUIRE(netmgr != NULL);
+ REQUIRE(zmgrp != NULL && *zmgrp == NULL);
zmgr = isc_mem_get(mctx, sizeof(*zmgr));
*zmgr = (dns_zonemgr_t){
+ .loopmgr = loopmgr,
.taskmgr = taskmgr,
- .timermgr = timermgr,
.netmgr = netmgr,
- .workers = isc_nm_getnworkers(netmgr),
+ .workers = isc_loopmgr_nloops(loopmgr),
.transfersin = 10,
.transfersperns = 2,
};
/* Unreachable lock. */
isc_rwlock_init(&zmgr->urlock, 0, 0);
- /* Create a single task for queueing of SOA queries. */
- result = isc_task_create(taskmgr, 1, &zmgr->task, 0);
+ result = isc_ratelimiter_create(mainloop, &zmgr->checkdsrl);
+ INSIST(result == ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS) {
goto free_urlock;
}
- isc_task_setname(zmgr->task, "zmgr", zmgr);
- result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
- &zmgr->checkdsrl);
- if (result != ISC_R_SUCCESS) {
- goto free_task;
- }
-
- result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
- &zmgr->notifyrl);
+ result = isc_ratelimiter_create(mainloop, &zmgr->notifyrl);
+ INSIST(result == ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS) {
goto free_checkdsrl;
}
- result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
- &zmgr->refreshrl);
+ result = isc_ratelimiter_create(mainloop, &zmgr->refreshrl);
+ INSIST(result == ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS) {
goto free_notifyrl;
}
- result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
- &zmgr->startupnotifyrl);
+ result = isc_ratelimiter_create(mainloop, &zmgr->startupnotifyrl);
+ INSIST(result == ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS) {
goto free_refreshrl;
}
- result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
- &zmgr->startuprefreshrl);
+ result = isc_ratelimiter_create(mainloop, &zmgr->startuprefreshrl);
+ INSIST(result == ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS) {
goto free_startupnotifyrl;
}
for (size_t i = 0; i < zmgr->workers; i++) {
result = isc_task_create(zmgr->taskmgr, 2, &zmgr->zonetasks[i],
i);
+ INSIST(result == ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS) {
+ INSIST(result == ISC_R_SUCCESS);
goto free_zonetasks;
}
isc_task_setname(zmgr->zonetasks[i], "zonemgr-zonetasks", NULL);
for (size_t i = 0; i < zmgr->workers; i++) {
result = isc_task_create(zmgr->taskmgr, UINT_MAX,
&zmgr->loadtasks[i], i);
+ INSIST(result == ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS) {
goto free_loadtasks;
}
isc_mem_put(zmgr->mctx, zmgr->zonetasks,
zmgr->workers * sizeof(zmgr->zonetasks[0]));
- isc_ratelimiter_detach(&zmgr->startuprefreshrl);
+ isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
+ isc_ratelimiter_destroy(&zmgr->startuprefreshrl);
free_startupnotifyrl:
- isc_ratelimiter_detach(&zmgr->startupnotifyrl);
+ isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
+ isc_ratelimiter_destroy(&zmgr->startupnotifyrl);
free_refreshrl:
- isc_ratelimiter_detach(&zmgr->refreshrl);
+ isc_ratelimiter_shutdown(zmgr->refreshrl);
+ isc_ratelimiter_destroy(&zmgr->refreshrl);
free_notifyrl:
- isc_ratelimiter_detach(&zmgr->notifyrl);
+ isc_ratelimiter_shutdown(zmgr->notifyrl);
+ isc_ratelimiter_destroy(&zmgr->notifyrl);
free_checkdsrl:
- isc_ratelimiter_detach(&zmgr->checkdsrl);
-free_task:
- isc_task_detach(&zmgr->task);
+ isc_ratelimiter_shutdown(zmgr->checkdsrl);
+ isc_ratelimiter_destroy(&zmgr->checkdsrl);
free_urlock:
isc_rwlock_destroy(&zmgr->urlock);
isc_rwlock_destroy(&zmgr->rwlock);
isc_task_setname(zone->task, "zone", zone);
isc_task_setname(zone->loadtask, "loadzone", zone);
- isc_timer_create(zmgr->timermgr, zone->task, zone_timer, zone,
- &zone->timer);
+ zone->loop = isc_loop_get(zmgr->loopmgr, zone->tid);
+
+ isc_timer_create(zone->loop, zone_timer, zone, &zone->timer);
/*
* The timer "holds" a iref.
isc_result_t
dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
- dns_zone_t *p;
-
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
- for (p = ISC_LIST_HEAD(zmgr->zones); p != NULL;
- p = ISC_LIST_NEXT(p, link)) {
- dns_zone_maintenance(p);
+ for (dns_zone_t *zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
+ zone = ISC_LIST_NEXT(zone, link))
+ {
+ isc_time_t now;
+
+ LOCK_ZONE(zone);
+ TIME_NOW(&now);
+ zone_settimer(zone, &now);
+ UNLOCK_ZONE(zone);
}
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
- if (zmgr->task != NULL) {
- isc_task_detach(&zmgr->task);
- }
-
for (size_t i = 0; i < zmgr->workers; i++) {
isc_mem_detach(&zmgr->mctxpool[i]);
}
for (size_t i = 0; i < zmgr->workers; i++) {
- if (zmgr->loadtasks[i] != NULL) {
- isc_task_detach(&zmgr->loadtasks[i]);
- }
+ isc_task_detach(&zmgr->loadtasks[i]);
}
for (size_t i = 0; i < zmgr->workers; i++) {
- if (zmgr->zonetasks[i] != NULL) {
- isc_task_detach(&zmgr->zonetasks[i]);
- }
+ isc_task_detach(&zmgr->zonetasks[i]);
}
RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
static void
zonemgr_free(dns_zonemgr_t *zmgr) {
- isc_mem_t *mctx;
-
- INSIST(ISC_LIST_EMPTY(zmgr->zones));
+ REQUIRE(ISC_LIST_EMPTY(zmgr->zones));
zmgr->magic = 0;
isc_refcount_destroy(&zmgr->refs);
isc_mutex_destroy(&zmgr->iolock);
- isc_ratelimiter_detach(&zmgr->checkdsrl);
- isc_ratelimiter_detach(&zmgr->notifyrl);
- isc_ratelimiter_detach(&zmgr->refreshrl);
- isc_ratelimiter_detach(&zmgr->startupnotifyrl);
- isc_ratelimiter_detach(&zmgr->startuprefreshrl);
+ isc_ratelimiter_destroy(&zmgr->checkdsrl);
+ isc_ratelimiter_destroy(&zmgr->notifyrl);
+ isc_ratelimiter_destroy(&zmgr->refreshrl);
+ isc_ratelimiter_destroy(&zmgr->startupnotifyrl);
+ isc_ratelimiter_destroy(&zmgr->startuprefreshrl);
isc_mem_put(zmgr->mctx, zmgr->mctxpool,
zmgr->workers * sizeof(zmgr->mctxpool[0]));
zonemgr_keymgmt_destroy(zmgr);
- mctx = zmgr->mctx;
if (zmgr->tlsctx_cache != NULL) {
isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
}
- isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
- isc_mem_detach(&mctx);
+ isc_mem_putanddetach(&zmgr->mctx, zmgr, sizeof(*zmgr));
}
void
isc_interval_t interval;
uint32_t s, ns;
uint32_t pertic;
- isc_result_t result;
if (value == 0) {
value = 1;
isc_interval_set(&interval, s, ns);
- result = isc_ratelimiter_setinterval(rl, &interval);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_ratelimiter_setinterval(rl, &interval);
isc_ratelimiter_setpertic(rl, pertic);
*rate = value;
LOCK_ZONE(zone);
LOCK_ZONE(raw);
- isc_timer_create(zmgr->timermgr, zone->task, zone_timer, raw,
- &raw->timer);
+ raw->loop = zone->loop;
+ isc_timer_create(raw->loop, zone_timer, raw, &raw->timer);
/*
* The timer "holds" a iref.
isc_refcount_increment(&raw->erefs);
zone->raw = raw;
- /* dns_zone_iattach(zone, &raw->secure); */
+ /* dns_zone_iattach(zone, &raw->secure); */
zone_iattach(zone, &raw->secure);
isc_task_attach(zone->task, &raw->task);
mutexblock.c \
net.c \
netaddr.c \
- netmgr_p.h \
netscope.c \
nonce.c \
openssl_shim.c \
symtab.c \
syslog.c \
task.c \
- task_p.h \
thread.c \
tid.c \
time.c \
timer.c \
- timer_p.h \
tls.c \
tls_p.h \
tm.c \
isc_result_t
isc_managers_create(isc_mem_t *mctx, size_t workers, size_t quantum,
- isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp,
- isc_timermgr_t **timermgrp);
+ isc_loopmgr_t **loopmgrp, isc_nm_t **netmgrp,
+ isc_taskmgr_t **taskmgrp);
void
-isc_managers_destroy(isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp,
- isc_timermgr_t **timermgrp);
+isc_managers_destroy(isc_loopmgr_t **loopmgr, isc_nm_t **netmgrp,
+ isc_taskmgr_t **taskmgrp);
#include <stdbool.h>
#include <isc/lang.h>
+#include <isc/loop.h>
#include <isc/time.h>
#include <isc/types.h>
*****/
isc_result_t
-isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
- isc_task_t *task, isc_ratelimiter_t **ratelimiterp);
+isc_ratelimiter_create(isc_loop_t *loop, isc_ratelimiter_t **ratelimiterp);
/*%<
* Create a rate limiter. The execution interval is initially undefined.
*/
-isc_result_t
+void
isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval);
/*!<
* Set the minimum interval between event executions.
*
* Ensures:
*\li All events that have not yet been
- * dispatched to the task are dispatched immediately with
+ * dispatched to the task are dispatched immediately with
* the #ISC_EVENTATTR_CANCELED bit set in ev_attributes.
*
*\li Further attempts to enqueue events will fail with
- * #ISC_R_SHUTTINGDOWN.
+ * #ISC_R_SHUTTINGDOWN.
*
*\li The rate limiter is no longer attached to its task.
*/
void
-isc_ratelimiter_attach(isc_ratelimiter_t *source, isc_ratelimiter_t **target);
-/*%<
- * Attach to a rate limiter.
- */
-
-void
-isc_ratelimiter_detach(isc_ratelimiter_t **ratelimiterp);
-/*%<
- * Detach from a rate limiter.
- */
-
-isc_result_t
-isc_ratelimiter_stall(isc_ratelimiter_t *rl);
-/*%<
- * Stall event processing.
- */
-
-isc_result_t
-isc_ratelimiter_release(isc_ratelimiter_t *rl);
+isc_ratelimiter_destroy(isc_ratelimiter_t **ratelimiterp);
/*%<
- * Release a stalled rate limiter.
+ * Destroy the rate limiter.
*/
ISC_LANG_ENDDECLS
/*! \file isc/timer.h
* \brief Provides timers which are event sources in the task system.
*
- * Three types of timers are supported:
+ * Two types of timers are supported:
*
*\li 'ticker' timers generate a periodic tick event.
*
*\li 'once' timers generate an timeout event if the time reaches
* the set interval.
*
- *\li 'inactive' timers generate no events.
- *
- * Timers can change type. It is typical to create a timer as
- * an 'inactive' timer and then change it into a 'ticker' or
- * 'once' timer.
- *
*\li MP:
* The module ensures appropriate synchronization of data structures it
* creates and manipulates.
#include <stdbool.h>
-#include <isc/event.h>
-#include <isc/eventclass.h>
+#include <isc/job.h>
#include <isc/lang.h>
#include <isc/time.h>
#include <isc/types.h>
isc_timertype_undefined = -1, /*%< Undefined */
isc_timertype_ticker = 0, /*%< Ticker */
isc_timertype_once = 1, /*%< Once */
- isc_timertype_inactive = 3 /*%< Inactive */
} isc_timertype_t;
-typedef struct isc_timerevent isc_timerevent_t;
-
-struct isc_timerevent {
- struct isc_event common;
- isc_time_t due;
- ISC_LINK(isc_timerevent_t) ev_timerlink;
-};
-
-#define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 0)
-#define ISC_TIMEREVENT_ONCE (ISC_EVENTCLASS_TIMER + 1)
-
/***
*** Timer and Timer Manager Functions
***
***/
void
-isc_timer_create(isc_timermgr_t *manager, isc_task_t *task,
- isc_taskaction_t action, void *arg, isc_timer_t **timerp);
+isc_timer_create(isc_loop_t *loop, isc_job_cb cb, void *cbarg,
+ isc_timer_t **timerp);
/*%<
- * Create a new 'type' timer managed by 'manager'. The timers parameters
- * are specified by 'expires' and 'interval'. Events will be posted to
- * 'task' and when dispatched 'action' will be called with 'arg' as the
- * arg value. The new timer is returned in 'timerp'.
+ * Create a new 'type' timer managed by 'loop'. The timers parameters are
+ * specified by 'expires' and 'interval'. Events will be posted on the isc
+ * event loop and when dispatched 'cb' will be called with 'cbarg' as the arg
+ * value. The new timer is returned in 'timerp'.
*
* Requires:
*
- *\li 'manager' is a valid manager
- *
- *\li 'task' is a valid task
- *
- *\li 'action' is a valid action
- *
- *\li 'expires' points to a valid time, or is NULL.
- *
- *\li 'interval' points to a valid interval, or is NULL.
- *
- *\li type == isc_timertype_inactive ||
- * ('expires' and 'interval' are not both 0)
- *
+ *\li 'loop' is a valid manager
+ *\li 'cb' is a valid job
*\li 'timerp' is a valid pointer, and *timerp == NULL
*
* Ensures:
*
*\li '*timerp' is attached to the newly created timer
+ */
+
+void
+isc_timer_stop(isc_timer_t *timer);
+/*%<
+ * Stop the timer.
*
- *\li The timer is attached to the task
- *
- *\li An idle timeout will not be generated until at least Now + the
- * timer's interval if 'timer' is a once timer with a non-zero
- * interval.
- *
- * Returns:
+ * Requires:
*
- *\li Success
- *\li No memory
- *\li Unexpected error
+ *\li 'timer' is a valid timer
*/
-isc_result_t
-isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
- const isc_interval_t *interval, bool purge);
+void
+isc_timer_start(isc_timer_t *timer, isc_timertype_t type,
+ const isc_interval_t *interval);
/*%<
- * Change the timer's type, and interval values to the given
- * values. If 'purge' is TRUE, any pending events from this timer
- * are purged from its task's event queue.
+ * Start the timer.
*
* Notes:
*
* 'interval' seconds.
*
*\li For once timers, 'interval' specifies how long the timer
- * can be idle before it generates an idle timeout. If 0, then no
- * idle timeout will be generated.
+ * can be idle before it generates an idle timeout. If 0, then
+ * the timer will be run immediately.
*
*\li If 'interval' is NULL, the zero interval will be used.
*
* Requires:
*
*\li 'timer' is a valid timer
- *
+ *\li 'type' is either 'isc_timertype_ticker' or 'isc_timertype_once'
*\li 'interval' points to a valid interval, or is NULL.
*
- *
* Ensures:
*
*\li An idle timeout will not be generated until at least Now + the
* timer's interval if 'timer' is a once timer with a non-zero
* interval.
- *
- * Returns:
- *
- *\li Success
- *\li No memory
- *\li Unexpected error
*/
void
isc_timer_destroy(isc_timer_t **timerp);
/*%<
- * Destroy *timerp.
+ * Destroy the timer *timerp.
*
* Requires:
*
* Ensures:
*
*\li *timerp is NULL.
- *
- *\code
- * The timer will be shutdown
- *
- * The timer will detach from its task
- *
- * All resources used by the timer have been freed
- *
- * Any events already posted by the timer will be purged.
- * Therefore, if isc_timer_destroy() is called in the context
- * of the timer's task, it is guaranteed that no more
- * timer event callbacks will run after the call.
- *
- * If this function is called from the timer event callback
- * the event itself must be destroyed before the timer
- * itself.
- *\endcode
- */
-
-isc_timertype_t
-isc_timer_gettype(isc_timer_t *timer);
-/*%<
- * Return the timer type.
- *
- * Requires:
- *
- *\li 'timer' to be a valid timer.
*/
ISC_LANG_ENDDECLS
* information regarding copyright ownership.
*/
+#include <isc/loop.h>
#include <isc/managers.h>
#include <isc/util.h>
#include "netmgr_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,
- isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp,
- isc_timermgr_t **timermgrp) {
+ isc_loopmgr_t **loopmgrp, isc_nm_t **netmgrp,
+ isc_taskmgr_t **taskmgrp) {
isc_result_t result;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
- isc_timermgr_t *timermgr = NULL;
REQUIRE(netmgrp != NULL && *netmgrp == NULL);
isc__netmgr_create(mctx, workers, &netmgr);
*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;
- }
+ isc_loopmgr_create(mctx, workers, loopmgrp);
return (ISC_R_SUCCESS);
fail:
- isc_managers_destroy(netmgrp, taskmgrp, timermgrp);
+ isc_managers_destroy(loopmgrp, netmgrp, taskmgrp);
return (result);
}
void
-isc_managers_destroy(isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp,
- isc_timermgr_t **timermgrp) {
+isc_managers_destroy(isc_loopmgr_t **loopmgrp, isc_nm_t **netmgrp,
+ isc_taskmgr_t **taskmgrp) {
/*
* If we have a taskmgr to clean up, then we must also have a netmgr.
*/
isc__netmgr_destroy(netmgrp);
}
- /*
- * 5. Clean up the remaining managers.
- */
- if (timermgrp != NULL) {
- INSIST(*timermgrp != NULL);
- isc__timermgr_destroy(timermgrp);
- }
+ isc_loopmgr_destroy(loopmgrp);
}
#include <inttypes.h>
#include <stdbool.h>
+#include <isc/async.h>
+#include <isc/event.h>
+#include <isc/loop.h>
#include <isc/mem.h>
#include <isc/ratelimiter.h>
#include <isc/refcount.h>
#include <isc/util.h>
typedef enum {
- isc_ratelimiter_stalled = 0,
- isc_ratelimiter_ratelimited = 1,
- isc_ratelimiter_idle = 2,
- isc_ratelimiter_shuttingdown = 3
+ isc_ratelimiter_ratelimited = 0,
+ isc_ratelimiter_idle = 1,
+ isc_ratelimiter_shuttingdown = 2
} isc_ratelimiter_state_t;
struct isc_ratelimiter {
isc_mem_t *mctx;
isc_mutex_t lock;
- isc_refcount_t references;
- isc_task_t *task;
+ isc_loopmgr_t *loopmgr;
isc_timer_t *timer;
isc_interval_t interval;
uint32_t pertic;
bool pushpop;
isc_ratelimiter_state_t state;
- isc_event_t shutdownevent;
ISC_LIST(isc_event_t) pending;
};
-#define ISC_RATELIMITEREVENT_SHUTDOWN (ISC_EVENTCLASS_RATELIMITER + 1)
-
-static void
-ratelimiter_tick(isc_task_t *task, isc_event_t *event);
-
static void
-ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event);
+ratelimiter_tick(void *arg);
isc_result_t
-isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
- isc_task_t *task, isc_ratelimiter_t **ratelimiterp) {
- isc_ratelimiter_t *rl;
+isc_ratelimiter_create(isc_loop_t *loop, isc_ratelimiter_t **ratelimiterp) {
+ isc_ratelimiter_t *rl = NULL;
+ isc_mem_t *mctx = isc_loop_getmctx(loop);
+
INSIST(ratelimiterp != NULL && *ratelimiterp == NULL);
rl = isc_mem_get(mctx, sizeof(*rl));
*rl = (isc_ratelimiter_t){
- .mctx = mctx,
- .task = task,
.pertic = 1,
.state = isc_ratelimiter_idle,
};
- isc_refcount_init(&rl->references, 1);
+ isc_mem_attach(mctx, &rl->mctx);
isc_interval_set(&rl->interval, 0, 0);
ISC_LIST_INIT(rl->pending);
isc_mutex_init(&rl->lock);
- isc_timer_create(timermgr, rl->task, ratelimiter_tick, rl, &rl->timer);
-
- /*
- * Increment the reference count to indicate that we may
- * (soon) have events outstanding.
- */
- isc_refcount_increment(&rl->references);
-
- ISC_EVENT_INIT(&rl->shutdownevent, sizeof(isc_event_t), 0,
- ISC_RATELIMITEREVENT_SHUTDOWN,
- ratelimiter_shutdowncomplete, rl, rl, NULL, NULL);
+ isc_timer_create(loop, ratelimiter_tick, rl, &rl->timer);
*ratelimiterp = rl;
return (ISC_R_SUCCESS);
}
-isc_result_t
+void
isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval) {
- isc_result_t result = ISC_R_SUCCESS;
-
REQUIRE(rl != NULL);
REQUIRE(interval != NULL);
* If the timer is currently running, change its rate.
*/
if (rl->state == isc_ratelimiter_ratelimited) {
- result = isc_timer_reset(rl->timer, isc_timertype_ticker,
- &rl->interval, false);
+ isc_timer_start(rl->timer, isc_timertype_ticker, &rl->interval);
}
UNLOCK(&rl->lock);
- return (result);
}
void
isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, uint32_t pertic) {
REQUIRE(rl != NULL);
+ REQUIRE(pertic > 0);
- if (pertic == 0) {
- pertic = 1;
- }
+ LOCK(&rl->lock);
rl->pertic = pertic;
+ UNLOCK(&rl->lock);
}
void
isc_ratelimiter_setpushpop(isc_ratelimiter_t *rl, bool pushpop) {
REQUIRE(rl != NULL);
+ LOCK(&rl->lock);
rl->pushpop = pushpop;
+ UNLOCK(&rl->lock);
}
isc_result_t
isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
isc_event_t **eventp) {
isc_result_t result = ISC_R_SUCCESS;
- isc_event_t *ev;
+ isc_event_t *event;
REQUIRE(rl != NULL);
REQUIRE(task != NULL);
REQUIRE(eventp != NULL && *eventp != NULL);
- ev = *eventp;
- REQUIRE(ev->ev_sender == NULL);
+ event = *eventp;
+ REQUIRE(event->ev_sender == NULL);
LOCK(&rl->lock);
- if (rl->state == isc_ratelimiter_ratelimited ||
- rl->state == isc_ratelimiter_stalled)
- {
- ev->ev_sender = task;
+ switch (rl->state) {
+ case isc_ratelimiter_shuttingdown:
+ result = ISC_R_SHUTTINGDOWN;
+ break;
+ case isc_ratelimiter_ratelimited:
+ event->ev_sender = task;
*eventp = NULL;
if (rl->pushpop) {
- ISC_LIST_PREPEND(rl->pending, ev, ev_ratelink);
+ ISC_LIST_PREPEND(rl->pending, event, ev_ratelink);
} else {
- ISC_LIST_APPEND(rl->pending, ev, ev_ratelink);
- }
- } else if (rl->state == isc_ratelimiter_idle) {
- result = isc_timer_reset(rl->timer, isc_timertype_ticker,
- &rl->interval, false);
- if (result == ISC_R_SUCCESS) {
- ev->ev_sender = task;
- rl->state = isc_ratelimiter_ratelimited;
+ ISC_LIST_APPEND(rl->pending, event, ev_ratelink);
}
- } else {
- INSIST(rl->state == isc_ratelimiter_shuttingdown);
- result = ISC_R_SHUTTINGDOWN;
+ break;
+ case isc_ratelimiter_idle:
+ isc_timer_start(rl->timer, isc_timertype_ticker, &rl->interval);
+ event->ev_sender = task;
+ rl->state = isc_ratelimiter_ratelimited;
+ break;
+ default:
+ UNREACHABLE();
}
UNLOCK(&rl->lock);
if (*eventp != NULL && result == ISC_R_SUCCESS) {
} else {
result = ISC_R_NOTFOUND;
}
+
+ if (ISC_LIST_EMPTY(rl->pending)) {
+ /* No work left to do. Stop the timer. */
+ isc_timer_stop(rl->timer);
+ rl->state = isc_ratelimiter_idle;
+ }
UNLOCK(&rl->lock);
+
return (result);
}
static void
-ratelimiter_tick(isc_task_t *task, isc_event_t *event) {
- isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
- isc_event_t *p;
+ratelimiter_tick(void *arg) {
+ isc_ratelimiter_t *rl = (isc_ratelimiter_t *)arg;
+ isc_event_t *event;
uint32_t pertic;
- UNUSED(task);
-
- isc_event_free(&event);
-
pertic = rl->pertic;
while (pertic != 0) {
pertic--;
LOCK(&rl->lock);
- p = ISC_LIST_HEAD(rl->pending);
- if (p != NULL) {
+ event = ISC_LIST_HEAD(rl->pending);
+ if (event != NULL) {
/*
* There is work to do. Let's do it after unlocking.
*/
- ISC_LIST_UNLINK(rl->pending, p, ev_ratelink);
+ ISC_LIST_UNLINK(rl->pending, event, ev_ratelink);
} else {
- /*
- * No work left to do. Stop the timer so that we don't
- * waste resources by having it fire periodically.
- */
- isc_result_t result = isc_timer_reset(
- rl->timer, isc_timertype_inactive, NULL, false);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ /* No work left to do. Stop the timer. */
+ isc_timer_stop(rl->timer);
rl->state = isc_ratelimiter_idle;
pertic = 0; /* Force the loop to exit. */
}
UNLOCK(&rl->lock);
- if (p != NULL) {
- isc_task_t *evtask = p->ev_sender;
- isc_task_send(evtask, &p);
+ if (event != NULL) {
+ isc_task_send(event->ev_sender, &event);
}
- INSIST(p == NULL);
+ INSIST(event == NULL);
}
}
void
isc_ratelimiter_shutdown(isc_ratelimiter_t *rl) {
- isc_event_t *ev;
- isc_task_t *task;
- isc_result_t result;
+ isc_event_t *event;
REQUIRE(rl != NULL);
LOCK(&rl->lock);
rl->state = isc_ratelimiter_shuttingdown;
- (void)isc_timer_reset(rl->timer, isc_timertype_inactive, NULL, false);
- while ((ev = ISC_LIST_HEAD(rl->pending)) != NULL) {
- task = ev->ev_sender;
- ISC_LIST_UNLINK(rl->pending, ev, ev_ratelink);
- ev->ev_attributes |= ISC_EVENTATTR_CANCELED;
- isc_task_send(task, &ev);
- }
- task = NULL;
- isc_task_attach(rl->task, &task);
-
- result = isc_timer_reset(rl->timer, isc_timertype_inactive, NULL,
- false);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_timer_stop(rl->timer);
isc_timer_destroy(&rl->timer);
- /*
- * Send an event to our task. The delivery of this event
- * indicates that no more timer events will be delivered.
- */
- ev = &rl->shutdownevent;
- isc_task_send(rl->task, &ev);
-
- UNLOCK(&rl->lock);
-}
-
-static void
-ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event) {
- isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
-
- UNUSED(task);
-
- isc_ratelimiter_detach(&rl);
- isc_task_detach(&task);
-}
-
-static void
-ratelimiter_free(isc_ratelimiter_t *rl) {
- isc_refcount_destroy(&rl->references);
- isc_mutex_destroy(&rl->lock);
- isc_mem_put(rl->mctx, rl, sizeof(*rl));
-}
+ while ((event = ISC_LIST_HEAD(rl->pending)) != NULL) {
+ ISC_LIST_UNLINK(rl->pending, event, ev_ratelink);
+ UNLOCK(&rl->lock);
-void
-isc_ratelimiter_attach(isc_ratelimiter_t *source, isc_ratelimiter_t **target) {
- REQUIRE(source != NULL);
- REQUIRE(target != NULL && *target == NULL);
+ event->ev_attributes |= ISC_EVENTATTR_CANCELED;
+ isc_task_send(event->ev_sender, &event);
- isc_refcount_increment(&source->references);
+ LOCK(&rl->lock);
+ }
- *target = source;
+ UNLOCK(&rl->lock);
}
void
-isc_ratelimiter_detach(isc_ratelimiter_t **rlp) {
+isc_ratelimiter_destroy(isc_ratelimiter_t **rlp) {
isc_ratelimiter_t *rl;
REQUIRE(rlp != NULL && *rlp != NULL);
rl = *rlp;
*rlp = NULL;
- if (isc_refcount_decrement(&rl->references) == 1) {
- ratelimiter_free(rl);
- }
-}
-
-isc_result_t
-isc_ratelimiter_stall(isc_ratelimiter_t *rl) {
- isc_result_t result = ISC_R_SUCCESS;
-
- REQUIRE(rl != NULL);
-
LOCK(&rl->lock);
- switch (rl->state) {
- case isc_ratelimiter_shuttingdown:
- result = ISC_R_SHUTTINGDOWN;
- break;
- case isc_ratelimiter_ratelimited:
- result = isc_timer_reset(rl->timer, isc_timertype_inactive,
- NULL, false);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- FALLTHROUGH;
- case isc_ratelimiter_idle:
- case isc_ratelimiter_stalled:
- rl->state = isc_ratelimiter_stalled;
- break;
- }
+ REQUIRE(rl->state == isc_ratelimiter_shuttingdown);
UNLOCK(&rl->lock);
- return (result);
-}
-
-isc_result_t
-isc_ratelimiter_release(isc_ratelimiter_t *rl) {
- isc_result_t result = ISC_R_SUCCESS;
- REQUIRE(rl != NULL);
-
- LOCK(&rl->lock);
- switch (rl->state) {
- case isc_ratelimiter_shuttingdown:
- result = ISC_R_SHUTTINGDOWN;
- break;
- case isc_ratelimiter_stalled:
- if (!ISC_LIST_EMPTY(rl->pending)) {
- result = isc_timer_reset(rl->timer,
- isc_timertype_ticker,
- &rl->interval, false);
- if (result == ISC_R_SUCCESS) {
- rl->state = isc_ratelimiter_ratelimited;
- }
- } else {
- rl->state = isc_ratelimiter_idle;
- }
- break;
- case isc_ratelimiter_ratelimited:
- case isc_ratelimiter_idle:
- break;
- }
- UNLOCK(&rl->lock);
- return (result);
+ isc_mutex_destroy(&rl->lock);
+ isc_mem_putanddetach(&rl->mctx, rl, sizeof(*rl));
}
#include <stdbool.h>
-#include <isc/app.h>
+#include <isc/async.h>
#include <isc/condition.h>
#include <isc/heap.h>
+#include <isc/job.h>
#include <isc/log.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/time.h>
#include <isc/timer.h>
#include <isc/util.h>
+#include <isc/uv.h>
-#include "timer_p.h"
-
-#ifdef ISC_TIMER_TRACE
-#define XTRACE(s) fprintf(stderr, "%s\n", (s))
-#define XTRACEID(s, t) fprintf(stderr, "%s %p\n", (s), (t))
-#define XTRACETIME(s, d) \
- fprintf(stderr, "%s %u.%09u\n", (s), (d).seconds, (d).nanoseconds)
-#define XTRACETIME2(s, d, n) \
- fprintf(stderr, "%s %u.%09u %u.%09u\n", (s), (d).seconds, \
- (d).nanoseconds, (n).seconds, (n).nanoseconds)
-#define XTRACETIMER(s, t, d) \
- fprintf(stderr, "%s %p %u.%09u\n", (s), (t), (d).seconds, \
- (d).nanoseconds)
-#else /* ifdef ISC_TIMER_TRACE */
-#define XTRACE(s)
-#define XTRACEID(s, t)
-#define XTRACETIME(s, d)
-#define XTRACETIME2(s, d, n)
-#define XTRACETIMER(s, t, d)
-#endif /* ISC_TIMER_TRACE */
+#include "loop_p.h"
#define TIMER_MAGIC ISC_MAGIC('T', 'I', 'M', 'R')
#define VALID_TIMER(t) ISC_MAGIC_VALID(t, TIMER_MAGIC)
struct isc_timer {
- /*! Not locked. */
unsigned int magic;
- isc_timermgr_t *manager;
- isc_mutex_t lock;
- /*! Locked by timer lock. */
- isc_time_t idle;
- ISC_LIST(isc_timerevent_t) active;
- /*! Locked by manager lock. */
- isc_timertype_t type;
- isc_interval_t interval;
- isc_task_t *task;
- isc_taskaction_t action;
- void *arg;
- unsigned int index;
- isc_time_t due;
- LINK(isc_timer_t) link;
-};
-
-#define TIMER_MANAGER_MAGIC ISC_MAGIC('T', 'I', 'M', 'M')
-#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TIMER_MANAGER_MAGIC)
-
-struct isc_timermgr {
- /* Not locked. */
- unsigned int magic;
- isc_mem_t *mctx;
- isc_mutex_t lock;
- /* Locked by manager lock. */
- bool done;
- LIST(isc_timer_t) timers;
- unsigned int nscheduled;
- isc_time_t due;
- isc_condition_t wakeup;
- isc_thread_t thread;
- isc_heap_t *heap;
-};
-
-static isc_result_t
-schedule(isc_timer_t *timer, isc_time_t *now, bool signal_ok) {
- isc_timermgr_t *manager;
- isc_time_t due;
- isc_result_t result = ISC_R_SUCCESS;
-
- /*!
- * Note: the caller must ensure locking.
- */
-
- manager = timer->manager;
-
- /*
- * Compute the new due time.
- */
- switch (timer->type) {
- case isc_timertype_ticker:
- result = isc_time_add(now, &timer->interval, &due);
- if (result != ISC_R_SUCCESS) {
- return (result);
- }
- break;
- case isc_timertype_once:
- due = timer->idle;
- break;
- default:
- UNREACHABLE();
- }
+ isc_refcount_t references;
+ isc_loop_t *loop;
+ uv_timer_t timer;
+ isc_job_cb cb;
+ void *cbarg;
/*
- * Schedule the timer.
+ * We are locking the values here for now, but this needs to go away
+ * when the timers are pinned to the respective loops.
*/
-
- if (timer->index > 0) {
- /*
- * Already scheduled.
- */
- int cmp = isc_time_compare(&due, &timer->due);
- timer->due = due;
- switch (cmp) {
- case -1:
- isc_heap_increased(manager->heap, timer->index);
- break;
- case 1:
- isc_heap_decreased(manager->heap, timer->index);
- break;
- case 0:
- /* Nothing to do. */
- break;
- }
- } else {
- timer->due = due;
- isc_heap_insert(manager->heap, timer);
- manager->nscheduled++;
- }
-
- XTRACETIMER("schedule", timer, due);
-
- /*
- * If this timer is at the head of the queue, we need to ensure
- * that we won't miss it if it has a more recent due time than
- * the current "next" timer. We do this either by waking up the
- * run thread, or explicitly setting the value in the manager.
- */
-
- if (timer->index == 1 && signal_ok) {
- XTRACE("signal (schedule)");
- SIGNAL(&manager->wakeup);
- }
-
- return (result);
-}
-
-static void
-deschedule(isc_timer_t *timer) {
- isc_timermgr_t *manager;
-
- /*
- * The caller must ensure locking.
- */
-
- manager = timer->manager;
- if (timer->index > 0) {
- bool need_wakeup = false;
- if (timer->index == 1) {
- need_wakeup = true;
- }
- isc_heap_delete(manager->heap, timer->index);
- timer->index = 0;
- INSIST(manager->nscheduled > 0);
- manager->nscheduled--;
- if (need_wakeup) {
- XTRACE("signal (deschedule)");
- SIGNAL(&manager->wakeup);
- }
- }
-}
-
-static void
-timerevent_unlink(isc_timer_t *timer, isc_timerevent_t *event) {
- REQUIRE(ISC_LINK_LINKED(event, ev_timerlink));
- ISC_LIST_UNLINK(timer->active, event, ev_timerlink);
-}
+ isc_mutex_t lock;
+ uint64_t timeout;
+ uint64_t repeat;
+};
static void
-timerevent_destroy(isc_event_t *event0) {
- isc_timer_t *timer = event0->ev_destroy_arg;
- isc_timerevent_t *event = (isc_timerevent_t *)event0;
-
- LOCK(&timer->lock);
- if (ISC_LINK_LINKED(event, ev_timerlink)) {
- /* The event was unlinked via timer_purge() */
- timerevent_unlink(timer, event);
- }
- UNLOCK(&timer->lock);
+isc__timer_detach(isc_timer_t **timerp);
- isc_mem_put(timer->manager->mctx, event, event0->ev_size);
-}
+void
+isc_timer_create(isc_loop_t *loop, isc_job_cb cb, void *cbarg,
+ isc_timer_t **timerp) {
+ int r;
+ isc_timer_t *timer = NULL;
+ isc_loopmgr_t *loopmgr = NULL;
-static void
-timer_purge(isc_timer_t *timer) {
- isc_timerevent_t *event = NULL;
-
- while ((event = ISC_LIST_HEAD(timer->active)) != NULL) {
- timerevent_unlink(timer, event);
- UNLOCK(&timer->lock);
- (void)isc_task_purgeevent(timer->task, (isc_event_t *)event);
- LOCK(&timer->lock);
- }
-}
+ REQUIRE(cb != NULL);
+ REQUIRE(timerp != NULL && *timerp == NULL);
-void
-isc_timer_create(isc_timermgr_t *manager, isc_task_t *task,
- isc_taskaction_t action, void *arg, isc_timer_t **timerp) {
- REQUIRE(VALID_MANAGER(manager));
- REQUIRE(task != NULL);
- REQUIRE(action != NULL);
+ REQUIRE(VALID_LOOP(loop));
- isc_timer_t *timer;
- isc_time_t now;
+ loopmgr = loop->loopmgr;
- REQUIRE(timerp != NULL && *timerp == NULL);
+ REQUIRE(VALID_LOOPMGR(loopmgr));
- /*
- * Get current time.
- */
- TIME_NOW(&now);
+ REQUIRE(loop == isc_loop_current(loopmgr) ||
+ !atomic_load(&loopmgr->running) ||
+ atomic_load(&loopmgr->paused) > 0);
- timer = isc_mem_get(manager->mctx, sizeof(*timer));
+ timer = isc_mem_get(loop->mctx, sizeof(*timer));
*timer = (isc_timer_t){
- .manager = manager,
- .type = isc_timertype_inactive,
- .interval = *isc_interval_zero,
- .action = action,
- .arg = arg,
+ .cb = cb,
+ .cbarg = cbarg,
};
- isc_time_settoepoch(&timer->idle);
+ isc_loop_attach(loop, &timer->loop);
- isc_task_attach(task, &timer->task);
+ isc_refcount_init(&timer->references, 1);
isc_mutex_init(&timer->lock);
- ISC_LINK_INIT(timer, link);
-
- ISC_LIST_INIT(timer->active);
timer->magic = TIMER_MAGIC;
- /*
- * Note we don't have to lock the timer like we normally would because
- * there are no external references to it yet.
- */
+ r = uv_timer_init(&timer->loop->loop, &timer->timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data(&timer->timer, timer);
*timerp = timer;
-
- LOCK(&manager->lock);
- APPEND(manager->timers, timer, link);
- UNLOCK(&manager->lock);
}
-isc_result_t
-isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
- const isc_interval_t *interval, bool purge) {
- isc_time_t now;
- isc_timermgr_t *manager;
- isc_result_t result;
-
- /*
- * Change the timer's type, expires, and interval values to the given
- * values. If 'purge' is true, any pending events from this timer
- * are purged from its task's event queue.
- */
+static void
+isc__timer_stop(void *arg) {
+ isc_timer_t *timer = (isc_timer_t *)arg;
+ uv_timer_stop(&timer->timer);
+ isc__timer_detach(&timer);
+}
+void
+isc_timer_stop(isc_timer_t *timer) {
REQUIRE(VALID_TIMER(timer));
- manager = timer->manager;
- REQUIRE(VALID_MANAGER(manager));
- if (interval == NULL) {
- interval = isc_interval_zero;
- }
- REQUIRE(type == isc_timertype_inactive ||
- !isc_interval_iszero(interval));
-
- /*
- * Get current time.
- */
- if (type != isc_timertype_inactive) {
- TIME_NOW(&now);
- } else {
- /*
- * We don't have to do this, but it keeps the compiler from
- * complaining about "now" possibly being used without being
- * set, even though it will never actually happen.
- */
- isc_time_settoepoch(&now);
- }
-
- LOCK(&manager->lock);
- LOCK(&timer->lock);
-
- if (purge) {
- timer_purge(timer);
- }
- timer->type = type;
- timer->interval = *interval;
- if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
- result = isc_time_add(&now, interval, &timer->idle);
+ isc_refcount_increment(&timer->references);
+ if (timer->loop == isc_loop_current(timer->loop->loopmgr)) {
+ isc__timer_stop(timer);
} else {
- isc_time_settoepoch(&timer->idle);
- result = ISC_R_SUCCESS;
+ isc_async_run(timer->loop, isc__timer_stop, timer);
}
+}
- if (result == ISC_R_SUCCESS) {
- if (type == isc_timertype_inactive) {
- deschedule(timer);
- result = ISC_R_SUCCESS;
- } else {
- result = schedule(timer, &now, true);
- }
- }
+static void
+timer_cb(uv_timer_t *handle) {
+ isc_timer_t *timer = uv_handle_get_data(handle);
- UNLOCK(&timer->lock);
- UNLOCK(&manager->lock);
+ REQUIRE(VALID_TIMER(timer));
- return (result);
+ timer->cb(timer->cbarg);
}
-isc_timertype_t
-isc_timer_gettype(isc_timer_t *timer) {
- isc_timertype_t t;
-
- REQUIRE(VALID_TIMER(timer));
+static void
+isc__timer_start(void *arg) {
+ isc_timer_t *timer = (isc_timer_t *)arg;
LOCK(&timer->lock);
- t = timer->type;
+ int r = uv_timer_start(&timer->timer, timer_cb, timer->timeout,
+ timer->repeat);
+ UV_RUNTIME_CHECK(uv_timer_start, r);
UNLOCK(&timer->lock);
- return (t);
+ isc__timer_detach(&timer);
}
void
-isc_timer_destroy(isc_timer_t **timerp) {
- isc_timer_t *timer = NULL;
- isc_timermgr_t *manager = NULL;
+isc_timer_start(isc_timer_t *timer, isc_timertype_t type,
+ const isc_interval_t *interval) {
+ isc_loopmgr_t *loopmgr = NULL;
+ isc_loop_t *loop = NULL;
- REQUIRE(timerp != NULL && VALID_TIMER(*timerp));
+ REQUIRE(VALID_TIMER(timer));
+ REQUIRE(type == isc_timertype_ticker || type == isc_timertype_once);
- timer = *timerp;
- *timerp = NULL;
+ loop = timer->loop;
- manager = timer->manager;
+ REQUIRE(VALID_LOOP(loop));
- LOCK(&manager->lock);
+ loopmgr = loop->loopmgr;
+
+ REQUIRE(VALID_LOOPMGR(loopmgr));
LOCK(&timer->lock);
- timer_purge(timer);
- deschedule(timer);
+ switch (type) {
+ case isc_timertype_once:
+ timer->timeout = isc_interval_ms(interval);
+ timer->repeat = 0;
+ break;
+ case isc_timertype_ticker:
+ timer->timeout = timer->repeat = isc_interval_ms(interval);
+ break;
+ default:
+ UNREACHABLE();
+ }
UNLOCK(&timer->lock);
- UNLINK(manager->timers, timer, link);
-
- UNLOCK(&manager->lock);
-
- isc_task_detach(&timer->task);
- isc_mutex_destroy(&timer->lock);
- timer->magic = 0;
- isc_mem_put(manager->mctx, timer, sizeof(*timer));
+ isc_refcount_increment(&timer->references);
+ if (timer->loop == isc_loop_current(timer->loop->loopmgr)) {
+ isc__timer_start(timer);
+ } else {
+ isc_async_run(timer->loop, isc__timer_start, timer);
+ }
}
static void
-post_event(isc_timermgr_t *manager, isc_timer_t *timer, isc_eventtype_t type) {
- isc_timerevent_t *event;
- XTRACEID("posting", timer);
+timer_destroy(uv_handle_t *handle) {
+ isc_timer_t *timer = uv_handle_get_data(handle);
+ isc_loop_t *loop;
- event = (isc_timerevent_t *)isc_event_allocate(
- manager->mctx, timer, type, timer->action, timer->arg,
- sizeof(*event));
+ REQUIRE(VALID_TIMER(timer));
- ISC_LINK_INIT(event, ev_timerlink);
- ((isc_event_t *)event)->ev_destroy = timerevent_destroy;
- ((isc_event_t *)event)->ev_destroy_arg = timer;
+ loop = timer->loop;
- event->due = timer->due;
+ isc_refcount_destroy(&timer->references);
+ isc_mutex_destroy(&timer->lock);
- LOCK(&timer->lock);
- ISC_LIST_APPEND(timer->active, event, ev_timerlink);
- UNLOCK(&timer->lock);
+ isc_mem_put(loop->mctx, timer, sizeof(*timer));
- isc_task_send(timer->task, ISC_EVENT_PTR(&event));
+ isc_loop_detach(&loop);
}
static void
-dispatch(isc_timermgr_t *manager, isc_time_t *now) {
- bool need_schedule;
- isc_eventtype_t type = 0;
- isc_timer_t *timer;
- isc_result_t result;
-
- /*!
- * The caller must be holding the manager lock.
- */
-
- while (manager->nscheduled > 0) {
- timer = isc_heap_element(manager->heap, 1);
- INSIST(timer != NULL && timer->type != isc_timertype_inactive);
-
- if (isc_time_compare(now, &timer->due) < 0) {
- manager->due = timer->due;
- break;
- }
+isc__timer_destroy(void *arg) {
+ isc_timer_t *timer = (isc_timer_t *)arg;
- switch (timer->type) {
- case isc_timertype_ticker:
- type = ISC_TIMEREVENT_TICK;
- post_event(manager, timer, type);
- need_schedule = true;
- break;
- case isc_timertype_once:
- type = ISC_TIMEREVENT_ONCE;
- post_event(manager, timer, type);
- need_schedule = false;
- break;
- default:
- UNREACHABLE();
- }
-
- timer->index = 0;
- isc_heap_delete(manager->heap, 1);
- manager->nscheduled--;
-
- if (need_schedule) {
- result = schedule(timer, now, false);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: %u",
- "couldn't schedule "
- "timer",
- result);
- }
- }
- }
+ uv_timer_stop(&timer->timer);
+ uv_close(&timer->timer, timer_destroy);
}
-static isc_threadresult_t
-run(void *uap) {
- isc_timermgr_t *manager = uap;
- isc_time_t now;
- isc_result_t result;
-
- LOCK(&manager->lock);
- while (!manager->done) {
- TIME_NOW(&now);
+static void
+isc__timer_detach(isc_timer_t **timerp) {
+ isc_timer_t *timer = NULL;
- XTRACETIME("running", now);
+ REQUIRE(timerp != NULL && VALID_TIMER(*timerp));
- dispatch(manager, &now);
+ timer = *timerp;
+ *timerp = NULL;
- if (manager->nscheduled > 0) {
- XTRACETIME2("waituntil", manager->due, now);
- result = WAITUNTIL(&manager->wakeup, &manager->lock,
- &manager->due);
- INSIST(result == ISC_R_SUCCESS ||
- result == ISC_R_TIMEDOUT);
+ if (isc_refcount_decrement(&timer->references) == 1) {
+ if (timer->loop == isc_loop_current(timer->loop->loopmgr)) {
+ isc__timer_destroy(timer);
} else {
- XTRACETIME("wait", now);
- WAIT(&manager->wakeup, &manager->lock);
+ isc_async_run(timer->loop, isc__timer_destroy, timer);
}
- XTRACE("wakeup");
- }
- UNLOCK(&manager->lock);
-
- return ((isc_threadresult_t)0);
-}
-
-static bool
-sooner(void *v1, void *v2) {
- isc_timer_t *t1, *t2;
-
- t1 = v1;
- t2 = v2;
- REQUIRE(VALID_TIMER(t1));
- REQUIRE(VALID_TIMER(t2));
-
- if (isc_time_compare(&t1->due, &t2->due) < 0) {
- return (true);
}
- return (false);
-}
-
-static void
-set_index(void *what, unsigned int index) {
- isc_timer_t *timer;
-
- REQUIRE(VALID_TIMER(what));
- timer = what;
-
- timer->index = index;
-}
-
-isc_result_t
-isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
- isc_timermgr_t *manager;
-
- /*
- * Create a timer manager.
- */
-
- REQUIRE(managerp != NULL && *managerp == NULL);
-
- manager = isc_mem_get(mctx, sizeof(*manager));
-
- manager->magic = TIMER_MANAGER_MAGIC;
- manager->mctx = NULL;
- manager->done = false;
- INIT_LIST(manager->timers);
- manager->nscheduled = 0;
- isc_time_settoepoch(&manager->due);
- manager->heap = NULL;
- isc_heap_create(mctx, sooner, set_index, 0, &manager->heap);
- isc_mutex_init(&manager->lock);
- isc_mem_attach(mctx, &manager->mctx);
- isc_condition_init(&manager->wakeup);
- isc_thread_create(run, manager, &manager->thread);
- isc_thread_setname(manager->thread, "isc-timer");
-
- *managerp = manager;
-
- return (ISC_R_SUCCESS);
}
void
-isc__timermgr_destroy(isc_timermgr_t **managerp) {
- isc_timermgr_t *manager;
-
- /*
- * Destroy a timer manager.
- */
-
- REQUIRE(managerp != NULL);
- manager = *managerp;
- REQUIRE(VALID_MANAGER(manager));
-
- LOCK(&manager->lock);
-
- REQUIRE(EMPTY(manager->timers));
- manager->done = true;
-
- XTRACE("signal (destroy)");
- SIGNAL(&manager->wakeup);
-
- UNLOCK(&manager->lock);
-
- /*
- * Wait for thread to exit.
- */
- isc_thread_join(manager->thread, NULL);
-
- /*
- * Clean up.
- */
- isc_condition_destroy(&manager->wakeup);
- isc_mutex_destroy(&manager->lock);
- isc_heap_destroy(&manager->heap);
- manager->magic = 0;
- isc_mem_putanddetach(&manager->mctx, manager, sizeof(*manager));
-
- *managerp = NULL;
+isc_timer_destroy(isc_timer_t **timerp) {
+ isc__timer_detach(timerp);
}
+++ /dev/null
-/*
- * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
- *
- * SPDX-License-Identifier: MPL-2.0
- *
- * 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.
- */
#include <isc/string.h>
#include <isc/task.h>
#include <isc/thread.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/adb.h>
isc_result_t
ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid,
+ isc_loopmgr_t *loopmgr, dns_aclenv_t *aclenv, int tid,
ns_clientmgr_t **managerp) {
ns_clientmgr_t *manager = NULL;
isc_mem_t *mctx = NULL;
isc_mutex_init(&manager->reclock);
manager->taskmgr = taskmgr;
- manager->timermgr = timermgr;
+ manager->loopmgr = loopmgr;
manager->tid = tid;
dns_aclenv_attach(aclenv, &manager->aclenv);
/* Unlocked. */
unsigned int magic;
- isc_mem_t *mctx;
- ns_server_t *sctx;
- isc_taskmgr_t *taskmgr;
- isc_timermgr_t *timermgr;
- isc_refcount_t references;
- int tid;
+ isc_mem_t *mctx;
+ ns_server_t *sctx;
+ isc_taskmgr_t *taskmgr;
+ isc_loopmgr_t *loopmgr;
+ isc_refcount_t references;
+ int tid;
/* Attached by clients, needed for e.g. recursion */
isc_task_t *task;
isc_result_t
ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid,
+ isc_loopmgr_t *loopmgr, dns_aclenv_t *aclenv, int tid,
ns_clientmgr_t **managerp);
/*%<
* Create a client manager.
isc_result_t
ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
- isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
+ isc_taskmgr_t *taskmgr, isc_loopmgr_t *loopmgr,
isc_nm_t *nm, dns_dispatchmgr_t *dispatchmgr,
isc_task_t *task, dns_geoip_databases_t *geoip,
bool scan, ns_interfacemgr_t **mgrp);
unsigned int magic; /*%< Magic number */
isc_refcount_t references;
isc_mutex_t lock;
- isc_mem_t *mctx; /*%< Memory context */
- ns_server_t *sctx; /*%< Server context */
- isc_taskmgr_t *taskmgr; /*%< Task manager */
- isc_task_t *task; /*%< Task */
- isc_timermgr_t *timermgr; /*%< Timer manager */
- isc_nm_t *nm; /*%< Net manager */
- uint32_t ncpus; /*%< Number of workers */
+ isc_mem_t *mctx; /*%< Memory context */
+ ns_server_t *sctx; /*%< Server context */
+ isc_taskmgr_t *taskmgr; /*%< Task manager */
+ isc_task_t *task; /*%< Task */
+ isc_loopmgr_t *loopmgr; /*%< Loop manager */
+ isc_nm_t *nm; /*%< Net manager */
+ uint32_t ncpus; /*%< Number of workers */
dns_dispatchmgr_t *dispatchmgr;
unsigned int generation; /*%< Current generation no */
ns_listenlist_t *listenon4;
isc_result_t
ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
- isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
+ isc_taskmgr_t *taskmgr, isc_loopmgr_t *loopmgr,
isc_nm_t *nm, dns_dispatchmgr_t *dispatchmgr,
isc_task_t *task, dns_geoip_databases_t *geoip,
bool scan, ns_interfacemgr_t **mgrp) {
mgr = isc_mem_get(mctx, sizeof(*mgr));
*mgr = (ns_interfacemgr_t){
.taskmgr = taskmgr,
- .timermgr = timermgr,
+ .loopmgr = loopmgr,
.nm = nm,
.dispatchmgr = dispatchmgr,
.generation = 1,
mgr->ncpus * sizeof(mgr->clientmgrs[0]));
for (size_t i = 0; i < mgr->ncpus; i++) {
result = ns_clientmgr_create(mgr->sctx, mgr->taskmgr,
- mgr->timermgr, mgr->aclenv, (int)i,
+ mgr->loopmgr, mgr->aclenv, (int)i,
&mgr->clientmgrs[i]);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
#include <isc/atomic.h>
#include <isc/commandline.h>
#include <isc/condition.h>
+#include <isc/job.h>
+#include <isc/loop.h>
#include <isc/mem.h>
+#include <isc/os.h>
#include <isc/print.h>
-#include <isc/task.h>
#include <isc/time.h>
#include <isc/timer.h>
#include <isc/util.h>
#define FUDGE_NANOSECONDS 500000000 /* in absence of clock_getres() */
static isc_timer_t *timer = NULL;
-static isc_condition_t cv;
-static isc_mutex_t mx;
static isc_time_t endtime;
static isc_mutex_t lasttime_mx;
static isc_time_t lasttime;
static atomic_uint_fast32_t errcnt;
static int nevents;
-static int
-_setup(void **state) {
- atomic_init(&errcnt, ISC_R_SUCCESS);
+typedef struct setup_test_arg {
+ isc_timertype_t timertype;
+ isc_interval_t *interval;
+ isc_job_cb action;
+} setup_test_arg_t;
- setup_managers(state);
-
- return (0);
-}
-
-static int
-_teardown(void **state) {
- teardown_managers(state);
+static void
+setup_test_run(void *data) {
+ isc_timertype_t timertype = ((setup_test_arg_t *)data)->timertype;
+ isc_interval_t *interval = ((setup_test_arg_t *)data)->interval;
+ isc_job_cb action = ((setup_test_arg_t *)data)->action;
+ isc_result_t result;
- return (0);
-}
+ isc_mutex_lock(&lasttime_mx);
+ result = isc_time_now(&lasttime);
+ UNLOCK(&lasttime_mx);
+ assert_int_equal(result, ISC_R_SUCCESS);
-static void
-test_shutdown(void) {
- /*
- * Signal shutdown processing complete.
- */
- LOCK(&mx);
- SIGNAL(&cv);
- UNLOCK(&mx);
+ isc_timer_create(mainloop, action, (void *)timertype, &timer);
+ isc_timer_start(timer, timertype, interval);
}
static void
setup_test(isc_timertype_t timertype, isc_interval_t *interval,
- void (*action)(isc_task_t *, isc_event_t *)) {
- isc_result_t result;
- isc_task_t *task = NULL;
+ isc_job_cb action) {
+ setup_test_arg_t arg = { .timertype = timertype,
+ .interval = interval,
+ .action = action };
+
isc_time_settoepoch(&endtime);
atomic_init(&eventcnt, 0);
- isc_mutex_init(&mx);
isc_mutex_init(&lasttime_mx);
- isc_condition_init(&cv);
-
atomic_store(&errcnt, ISC_R_SUCCESS);
- LOCK(&mx);
-
- result = isc_task_create(taskmgr, 0, &task, 0);
- assert_int_equal(result, ISC_R_SUCCESS);
-
- LOCK(&lasttime_mx);
- result = isc_time_now(&lasttime);
- UNLOCK(&lasttime_mx);
- assert_int_equal(result, ISC_R_SUCCESS);
-
- isc_timer_create(timermgr, task, action, (void *)timertype, &timer);
- result = isc_timer_reset(timer, timertype, interval, false);
- assert_int_equal(result, ISC_R_SUCCESS);
-
- /*
- * Wait for shutdown processing to complete.
- */
- while (atomic_load(&eventcnt) != nevents) {
- WAIT(&cv, &mx);
- assert_int_equal(result, ISC_R_SUCCESS);
- }
-
- UNLOCK(&mx);
+ isc_loop_setup(mainloop, setup_test_run, &arg);
+ isc_loopmgr_run(loopmgr);
assert_int_equal(atomic_load(&errcnt), ISC_R_SUCCESS);
- isc_task_detach(&task);
- isc_mutex_destroy(&mx);
isc_mutex_destroy(&lasttime_mx);
- isc_condition_destroy(&cv);
}
static void
#define subthread_assert_true(expected) \
subthread_assert_true(expected, __FILE__, __LINE__)
-static void
-subthread_assert_int_equal(int observed, int expected, const char *file,
- unsigned int line) {
- if (observed != expected) {
- printf("# %s:%u subthread_assert_int_equal(%d != %d)\n", file,
- line, observed, expected);
- set_global_error(ISC_R_UNEXPECTED);
- }
-}
-#define subthread_assert_int_equal(observed, expected) \
- subthread_assert_int_equal(observed, expected, __FILE__, __LINE__)
-
static void
subthread_assert_result_equal(isc_result_t result, isc_result_t expected,
const char *file, unsigned int line) {
subthread_assert_result_equal(observed, expected, __FILE__, __LINE__)
static void
-ticktock(isc_task_t *task, isc_event_t *event) {
+ticktock(void *arg) {
isc_result_t result;
isc_time_t now;
isc_time_t base;
isc_time_t ulim;
isc_time_t llim;
isc_interval_t interval;
- isc_eventtype_t expected_event_type;
-
- UNUSED(task);
-
int tick = atomic_fetch_add(&eventcnt, 1);
+ UNUSED(arg);
+
if (verbose) {
print_message("# tick %d\n", tick);
}
- expected_event_type = ISC_TIMEREVENT_ONCE;
- if ((uintptr_t)event->ev_arg == isc_timertype_ticker) {
- expected_event_type = ISC_TIMEREVENT_TICK;
- }
-
- if (event->ev_type != expected_event_type) {
- print_error("# expected event type %u, got %u\n",
- expected_event_type, event->ev_type);
- }
-
result = isc_time_now(&now);
subthread_assert_result_equal(result, ISC_R_SUCCESS);
isc_mutex_unlock(&lasttime_mx);
subthread_assert_result_equal(result, ISC_R_SUCCESS);
- isc_event_free(&event);
-
if (atomic_load(&eventcnt) == nevents) {
result = isc_time_now(&endtime);
subthread_assert_result_equal(result, ISC_R_SUCCESS);
isc_timer_destroy(&timer);
- test_shutdown();
+ isc_loopmgr_shutdown(loopmgr);
}
}
}
static void
-test_idle(isc_task_t *task, isc_event_t *event) {
+test_idle(void *arg) {
isc_result_t result;
isc_time_t now;
isc_time_t base;
isc_time_t ulim;
isc_time_t llim;
isc_interval_t interval;
-
- UNUSED(task);
-
int tick = atomic_fetch_add(&eventcnt, 1);
+ UNUSED(arg);
+
if (verbose) {
print_message("# tick %d\n", tick);
}
isc_time_add(&now, &interval, &lasttime);
isc_mutex_unlock(&lasttime_mx);
- subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_ONCE);
-
- isc_event_free(&event);
-
isc_timer_destroy(&timer);
- test_shutdown();
+ isc_loopmgr_shutdown(loopmgr);
}
/* timer type once idles out */
/* timer reset */
static void
-test_reset(isc_task_t *task, isc_event_t *event) {
+test_reset(void *arg) {
isc_result_t result;
isc_time_t now;
isc_time_t base;
isc_time_t ulim;
isc_time_t llim;
isc_interval_t interval;
-
- UNUSED(task);
-
int tick = atomic_fetch_add(&eventcnt, 1);
+ UNUSED(arg);
+
if (verbose) {
print_message("# tick %d\n", tick);
}
isc_time_add(&now, &interval, &lasttime);
isc_mutex_unlock(&lasttime_mx);
- int _eventcnt = atomic_load(&eventcnt);
-
- if (_eventcnt < 3) {
- subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_TICK);
- if (_eventcnt == 2) {
+ if (tick < 2) {
+ if (tick == 1) {
isc_interval_set(&interval, seconds, nanoseconds);
- result = isc_timer_reset(timer, isc_timertype_once,
- &interval, false);
- subthread_assert_result_equal(result, ISC_R_SUCCESS);
+ isc_timer_start(timer, isc_timertype_once, &interval);
}
-
- isc_event_free(&event);
} else {
- subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_ONCE);
-
- isc_event_free(&event);
isc_timer_destroy(&timer);
- test_shutdown();
+ isc_loopmgr_shutdown(loopmgr);
}
}
}
static atomic_bool startflag;
-static atomic_bool shutdownflag;
static isc_timer_t *tickertimer = NULL;
static isc_timer_t *oncetimer = NULL;
-static isc_task_t *task1 = NULL;
-static isc_task_t *task2 = NULL;
-
-/*
- * task1 blocks on mx while events accumulate
- * in its queue, until signaled by task2.
- */
static void
-tick_event(isc_task_t *task, isc_event_t *event) {
- isc_result_t result;
- isc_time_t expires;
- isc_interval_t interval;
+tick_event(void *arg) {
+ int tick;
- UNUSED(task);
+ UNUSED(arg);
if (!atomic_load(&startflag)) {
if (verbose) {
print_message("# tick_event %d\n", -1);
}
- isc_event_free(&event);
return;
}
- int tick = atomic_fetch_add(&eventcnt, 1);
+ tick = atomic_fetch_add(&eventcnt, 1);
if (verbose) {
print_message("# tick_event %d\n", tick);
}
/*
- * On the first tick, purge all remaining tick events
- * and then shut down the task.
+ * On the first tick, purge all remaining tick events.
*/
if (tick == 0) {
- isc_time_settoepoch(&expires);
- isc_interval_set(&interval, seconds, 0);
- result = isc_timer_reset(tickertimer, isc_timertype_ticker,
- &interval, true);
- subthread_assert_result_equal(result, ISC_R_SUCCESS);
-
- atomic_store(&shutdownflag, 1);
+ isc_timer_destroy(&tickertimer);
}
-
- isc_event_free(&event);
}
static void
-once_event(isc_task_t *task, isc_event_t *event) {
- UNUSED(task);
+once_event(void *arg) {
+ UNUSED(arg);
if (verbose) {
print_message("# once_event\n");
*/
atomic_store(&startflag, true);
- isc_event_free(&event);
+ isc_loopmgr_shutdown(loopmgr);
+ isc_timer_destroy(&oncetimer);
+}
+
+ISC_LOOP_SETUP_IMPL(purge) {
+ atomic_init(&eventcnt, 0);
+ atomic_store(&errcnt, ISC_R_SUCCESS);
+}
+
+ISC_LOOP_TEARDOWN_IMPL(purge) {
+ assert_int_equal(atomic_load(&errcnt), ISC_R_SUCCESS);
+ assert_int_equal(atomic_load(&eventcnt), 1);
}
/* timer events purged */
-ISC_RUN_TEST_IMPL(purge) {
- isc_result_t result;
+ISC_LOOP_TEST_SETUP_TEARDOWN_IMPL(purge) {
isc_interval_t interval;
- UNUSED(state);
+ UNUSED(arg);
+
+ if (verbose) {
+ print_message("# purge_run\n");
+ }
atomic_init(&startflag, 0);
- atomic_init(&shutdownflag, 0);
- atomic_init(&eventcnt, 0);
seconds = 1;
nanoseconds = 0;
- result = isc_task_create(taskmgr, 0, &task1, 0);
- assert_int_equal(result, ISC_R_SUCCESS);
-
- result = isc_task_create(taskmgr, 0, &task2, 0);
- assert_int_equal(result, ISC_R_SUCCESS);
-
isc_interval_set(&interval, seconds, 0);
tickertimer = NULL;
- isc_timer_create(timermgr, task1, tick_event, NULL, &tickertimer);
- result = isc_timer_reset(tickertimer, isc_timertype_ticker, &interval,
- false);
- assert_int_equal(result, ISC_R_SUCCESS);
+ isc_timer_create(mainloop, tick_event, NULL, &tickertimer);
+ isc_timer_start(tickertimer, isc_timertype_ticker, &interval);
oncetimer = NULL;
isc_interval_set(&interval, (seconds * 2) + 1, 0);
- isc_timer_create(timermgr, task2, once_event, NULL, &oncetimer);
- result = isc_timer_reset(oncetimer, isc_timertype_once, &interval,
- false);
- assert_int_equal(result, ISC_R_SUCCESS);
-
- /*
- * Wait for shutdown processing to complete.
- */
- while (!atomic_load(&shutdownflag)) {
- uv_sleep(1);
- }
-
- assert_int_equal(atomic_load(&errcnt), ISC_R_SUCCESS);
-
- assert_int_equal(atomic_load(&eventcnt), 1);
-
- isc_timer_destroy(&tickertimer);
- isc_timer_destroy(&oncetimer);
- isc_task_detach(&task1);
- isc_task_detach(&task2);
+ isc_timer_create(mainloop, once_event, NULL, &oncetimer);
+ isc_timer_start(oncetimer, isc_timertype_once, &interval);
}
ISC_TEST_LIST_START
-ISC_TEST_ENTRY_CUSTOM(once_idle, _setup, _teardown)
-ISC_TEST_ENTRY_CUSTOM(reset, _setup, _teardown)
-ISC_TEST_ENTRY_CUSTOM(purge, _setup, _teardown)
+ISC_TEST_ENTRY_CUSTOM(ticker, setup_loopmgr, teardown_loopmgr)
+ISC_TEST_ENTRY_CUSTOM(once_idle, setup_loopmgr, teardown_loopmgr)
+ISC_TEST_ENTRY_CUSTOM(reset, setup_loopmgr, teardown_loopmgr)
+ISC_TEST_ENTRY_CUSTOM(purge, setup_loopmgr, teardown_loopmgr)
ISC_TEST_LIST_END