mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch '3202-cleanup-isc_timer-API' into 'main'
Refactor and simplify isc_timer API See merge request isc-projects/bind9!5966
This commit is contained in:
commit
13b20ef411
20 changed files with 263 additions and 618 deletions
4
CHANGES
4
CHANGES
|
|
@ -1,3 +1,7 @@
|
|||
5829. [func] Refactor and simplify isc_timer API in preparation
|
||||
for further refactoring on top of network manager
|
||||
loops. [GL #3202]
|
||||
|
||||
5828. [bug] Replace single TCP write timer with per-TCP write
|
||||
timers. [GL #3200]
|
||||
|
||||
|
|
|
|||
|
|
@ -278,9 +278,6 @@ named_control_docommand(isccc_sexpr_t *message, bool readonly,
|
|||
command_compare(command, NAMED_COMMAND_UNFREEZE))
|
||||
{
|
||||
result = named_server_freeze(named_g_server, false, lex, text);
|
||||
} else if (command_compare(command, NAMED_COMMAND_TIMERPOKE)) {
|
||||
isc_timermgr_poke(named_g_timermgr);
|
||||
result = ISC_R_SUCCESS;
|
||||
} else if (command_compare(command, NAMED_COMMAND_TRACE)) {
|
||||
result = named_server_setdebuglevel(named_g_server, lex);
|
||||
} else if (command_compare(command, NAMED_COMMAND_TSIGDELETE)) {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
#define NAMED_COMMAND_FREEZE "freeze"
|
||||
#define NAMED_COMMAND_UNFREEZE "unfreeze"
|
||||
#define NAMED_COMMAND_THAW "thaw"
|
||||
#define NAMED_COMMAND_TIMERPOKE "timerpoke"
|
||||
#define NAMED_COMMAND_RECURSING "recursing"
|
||||
#define NAMED_COMMAND_NULL "null"
|
||||
#define NAMED_COMMAND_NOTIFY "notify"
|
||||
|
|
|
|||
|
|
@ -9059,13 +9059,11 @@ load_configuration(const char *filename, named_server_t *server,
|
|||
interface_interval = cfg_obj_asduration(obj);
|
||||
if (interface_interval == 0) {
|
||||
CHECK(isc_timer_reset(server->interface_timer,
|
||||
isc_timertype_inactive, NULL, NULL,
|
||||
true));
|
||||
isc_timertype_inactive, NULL, true));
|
||||
} else if (server->interface_interval != interface_interval) {
|
||||
isc_interval_set(&interval, interface_interval, 0);
|
||||
CHECK(isc_timer_reset(server->interface_timer,
|
||||
isc_timertype_ticker, NULL, &interval,
|
||||
false));
|
||||
isc_timertype_ticker, &interval, false));
|
||||
}
|
||||
server->interface_interval = interface_interval;
|
||||
|
||||
|
|
@ -9086,22 +9084,20 @@ load_configuration(const char *filename, named_server_t *server,
|
|||
heartbeat_interval = cfg_obj_asuint32(obj) * 60;
|
||||
if (heartbeat_interval == 0) {
|
||||
CHECK(isc_timer_reset(server->heartbeat_timer,
|
||||
isc_timertype_inactive, NULL, NULL,
|
||||
true));
|
||||
isc_timertype_inactive, NULL, true));
|
||||
} else if (server->heartbeat_interval != heartbeat_interval) {
|
||||
isc_interval_set(&interval, heartbeat_interval, 0);
|
||||
CHECK(isc_timer_reset(server->heartbeat_timer,
|
||||
isc_timertype_ticker, NULL, &interval,
|
||||
false));
|
||||
isc_timertype_ticker, &interval, false));
|
||||
}
|
||||
server->heartbeat_interval = heartbeat_interval;
|
||||
|
||||
isc_interval_set(&interval, 1200, 0);
|
||||
CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL,
|
||||
CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker,
|
||||
&interval, false));
|
||||
|
||||
isc_interval_set(&interval, named_g_tat_interval, 0);
|
||||
CHECK(isc_timer_reset(server->tat_timer, isc_timertype_ticker, NULL,
|
||||
CHECK(isc_timer_reset(server->tat_timer, isc_timertype_ticker,
|
||||
&interval, false));
|
||||
|
||||
/*
|
||||
|
|
@ -9942,27 +9938,17 @@ run_server(isc_task_t *task, isc_event_t *event) {
|
|||
true, &server->interfacemgr),
|
||||
"creating interface manager");
|
||||
|
||||
CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
|
||||
NULL, NULL, server->task,
|
||||
interface_timer_tick, server,
|
||||
&server->interface_timer),
|
||||
"creating interface timer");
|
||||
isc_timer_create(named_g_timermgr, server->task, interface_timer_tick,
|
||||
server, &server->interface_timer);
|
||||
|
||||
CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
|
||||
NULL, NULL, server->task,
|
||||
heartbeat_timer_tick, server,
|
||||
&server->heartbeat_timer),
|
||||
"creating heartbeat timer");
|
||||
isc_timer_create(named_g_timermgr, server->task, heartbeat_timer_tick,
|
||||
server, &server->heartbeat_timer);
|
||||
|
||||
CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
|
||||
NULL, NULL, server->task, tat_timer_tick,
|
||||
server, &server->tat_timer),
|
||||
"creating trust anchor telemetry timer");
|
||||
isc_timer_create(named_g_timermgr, server->task, tat_timer_tick, server,
|
||||
&server->tat_timer);
|
||||
|
||||
CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
|
||||
NULL, NULL, server->task, pps_timer_tick,
|
||||
server, &server->pps_timer),
|
||||
"creating pps timer");
|
||||
isc_timer_create(named_g_timermgr, server->task, pps_timer_tick, server,
|
||||
&server->pps_timer);
|
||||
|
||||
CHECKFATAL(
|
||||
cfg_parser_create(named_g_mctx, named_g_lctx, &named_g_parser),
|
||||
|
|
|
|||
6
cocci/isc_timer_reset.spatch
Normal file
6
cocci/isc_timer_reset.spatch
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
@@
|
||||
expression E1, E2, E3, E4;
|
||||
@@
|
||||
|
||||
- isc_timer_reset(E1, E2, NULL, E3, E4)
|
||||
+ isc_timer_reset(E1, E2, E3, E4)
|
||||
|
|
@ -1400,8 +1400,9 @@ be triggered at that time.
|
|||
* 'arg' as its argument in task 'task'.
|
||||
*/
|
||||
isc_timer_t *timer = NULL;
|
||||
result = isc_timer_create(timermgr, isc_timertype_once, NULL,
|
||||
interval, task, timeout, arg, &timer);
|
||||
result = isc_timer_create(timermgr, task, timeout, arg, &timer);
|
||||
result = isc_timer_reset(timermgr, isc_timertype_once, NULL,
|
||||
interval, false);
|
||||
|
||||
An event can also be explicitly triggered via `isc_task_send()`.
|
||||
|
||||
|
|
|
|||
|
|
@ -617,7 +617,6 @@ dns_catz_catzs_set_view(dns_catz_zones_t *catzs, dns_view_t *view) {
|
|||
isc_result_t
|
||||
dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
|
||||
const dns_name_t *name) {
|
||||
isc_result_t result;
|
||||
dns_catz_zone_t *new_zone;
|
||||
|
||||
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
||||
|
|
@ -634,13 +633,9 @@ dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
|
|||
isc_ht_init(&new_zone->entries, catzs->mctx, 4);
|
||||
|
||||
new_zone->updatetimer = NULL;
|
||||
result = isc_timer_create(catzs->timermgr, isc_timertype_inactive, NULL,
|
||||
NULL, catzs->updater,
|
||||
dns_catz_update_taskaction, new_zone,
|
||||
&new_zone->updatetimer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_ht;
|
||||
}
|
||||
isc_timer_create(catzs->timermgr, catzs->updater,
|
||||
dns_catz_update_taskaction, new_zone,
|
||||
&new_zone->updatetimer);
|
||||
|
||||
isc_time_settoepoch(&new_zone->lastupdated);
|
||||
new_zone->updatepending = false;
|
||||
|
|
@ -658,13 +653,6 @@ dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
|
|||
*zonep = new_zone;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup_ht:
|
||||
isc_ht_destroy(&new_zone->entries);
|
||||
dns_name_free(&new_zone->name, catzs->mctx);
|
||||
isc_mem_put(catzs->mctx, new_zone, sizeof(*new_zone));
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -1684,7 +1672,7 @@ dns_catz_update_taskaction(isc_task_t *task, isc_event_t *event) {
|
|||
zone->updatepending = false;
|
||||
dns_catz_update_from_db(zone->db, zone->catzs);
|
||||
result = isc_timer_reset(zone->updatetimer, isc_timertype_inactive,
|
||||
NULL, NULL, true);
|
||||
NULL, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
isc_event_free(&event);
|
||||
result = isc_time_now(&zone->lastupdated);
|
||||
|
|
@ -1745,8 +1733,8 @@ dns_catz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
|
|||
0);
|
||||
dns_db_currentversion(db, &zone->dbversion);
|
||||
result = isc_timer_reset(zone->updatetimer,
|
||||
isc_timertype_once, NULL,
|
||||
&interval, true);
|
||||
isc_timertype_once, &interval,
|
||||
true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,9 +74,8 @@ nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
|
|||
isc_refcount_destroy(&nta->refcount);
|
||||
nta->magic = 0;
|
||||
if (nta->timer != NULL) {
|
||||
(void)isc_timer_reset(nta->timer,
|
||||
isc_timertype_inactive, NULL,
|
||||
NULL, true);
|
||||
(void)isc_timer_reset(
|
||||
nta->timer, isc_timertype_inactive, NULL, true);
|
||||
isc_timer_detach(&nta->timer);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&nta->rdataset)) {
|
||||
|
|
@ -233,7 +232,7 @@ fetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
*/
|
||||
if (nta->timer != NULL && nta->expiry - now < view->nta_recheck) {
|
||||
(void)isc_timer_reset(nta->timer, isc_timertype_inactive, NULL,
|
||||
NULL, true);
|
||||
true);
|
||||
}
|
||||
nta_detach(view->mctx, &nta);
|
||||
dns_view_weakdetach(&view);
|
||||
|
|
@ -289,10 +288,14 @@ settimer(dns_ntatable_t *ntatable, dns_nta_t *nta, uint32_t lifetime) {
|
|||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_timer_create(ntatable->timermgr, ntatable->task, checkbogus, nta,
|
||||
&nta->timer);
|
||||
isc_interval_set(&interval, view->nta_recheck, 0);
|
||||
result = isc_timer_create(ntatable->timermgr, isc_timertype_ticker,
|
||||
NULL, &interval, ntatable->task, checkbogus,
|
||||
nta, &nta->timer);
|
||||
result = isc_timer_reset(nta->timer, isc_timertype_ticker, &interval,
|
||||
false);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_timer_detach(&nta->timer);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
|
@ -476,9 +479,8 @@ again:
|
|||
"deleting expired NTA at %s", nb);
|
||||
|
||||
if (nta->timer != NULL) {
|
||||
(void)isc_timer_reset(nta->timer,
|
||||
isc_timertype_inactive, NULL,
|
||||
NULL, true);
|
||||
(void)isc_timer_reset(
|
||||
nta->timer, isc_timertype_inactive, NULL, true);
|
||||
isc_timer_detach(&nta->timer);
|
||||
}
|
||||
|
||||
|
|
@ -689,7 +691,7 @@ dns_ntatable_shutdown(dns_ntatable_t *ntatable) {
|
|||
if (nta->timer != NULL) {
|
||||
(void)isc_timer_reset(nta->timer,
|
||||
isc_timertype_inactive,
|
||||
NULL, NULL, true);
|
||||
NULL, true);
|
||||
}
|
||||
}
|
||||
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
||||
|
|
|
|||
|
|
@ -337,7 +337,6 @@ struct fetchctx {
|
|||
isc_time_t expires;
|
||||
isc_time_t expires_try_stale;
|
||||
isc_time_t next_timeout;
|
||||
isc_time_t final;
|
||||
isc_interval_t interval;
|
||||
dns_message_t *qmessage;
|
||||
ISC_LIST(resquery_t) queries;
|
||||
|
|
@ -1255,8 +1254,22 @@ update_edns_stats(resquery_t *query) {
|
|||
*/
|
||||
static inline isc_result_t
|
||||
fctx_starttimer(fetchctx_t *fctx) {
|
||||
return (isc_timer_reset(fctx->timer, isc_timertype_once, &fctx->final,
|
||||
NULL, true));
|
||||
isc_interval_t interval;
|
||||
isc_time_t now;
|
||||
isc_time_t expires;
|
||||
|
||||
isc_interval_set(&interval, 2, 0);
|
||||
isc_time_add(&fctx->expires, &interval, &expires);
|
||||
|
||||
isc_time_now(&now);
|
||||
if (isc_time_compare(&expires, &now) <= 0) {
|
||||
isc_interval_set(&interval, 0, 1);
|
||||
} else {
|
||||
isc_time_subtract(&expires, &now, &interval);
|
||||
}
|
||||
|
||||
return (isc_timer_reset(fctx->timer, isc_timertype_once, &interval,
|
||||
true));
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -1270,7 +1283,7 @@ fctx_stoptimer(fetchctx_t *fctx) {
|
|||
* cannot fail in that case.
|
||||
*/
|
||||
result = isc_timer_reset(fctx->timer, isc_timertype_inactive, NULL,
|
||||
NULL, true);
|
||||
true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_timer_reset(): %s",
|
||||
isc_result_totext(result));
|
||||
|
|
@ -1728,7 +1741,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
|
|||
}
|
||||
isc_interval_set(&i, 20 * 60, 0);
|
||||
result = isc_timer_reset(fctx->res->spillattimer,
|
||||
isc_timertype_ticker, NULL, &i,
|
||||
isc_timertype_ticker, &i,
|
||||
true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
}
|
||||
|
|
@ -4533,6 +4546,13 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
|
|||
|
||||
UNLOCK(&res->buckets[bucketnum].lock);
|
||||
|
||||
/*
|
||||
* As a backstop, we also set a timer to stop the fetch
|
||||
* if in-band netmgr timeouts don't work. It will fire two
|
||||
* seconds after the fetch should have finished. (This
|
||||
* 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(fctx, result, __LINE__);
|
||||
|
|
@ -4836,36 +4856,13 @@ fctx_create(dns_resolver_t *res, isc_task_t *task, const dns_name_t *name,
|
|||
goto cleanup_qmessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* As a backstop, we also set a timer to stop the fetch
|
||||
* if in-band netmgr timeouts don't work. It will fire two
|
||||
* seconds after the fetch should have finished. (This
|
||||
* should be enough of a gap to avoid the timer firing
|
||||
* while a response is being processed normally.)
|
||||
*/
|
||||
isc_interval_set(&interval, 2, 0);
|
||||
iresult = isc_time_add(&fctx->expires, &interval, &fctx->final);
|
||||
if (iresult != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_time_add: %s",
|
||||
isc_result_totext(iresult));
|
||||
result = ISC_R_UNEXPECTED;
|
||||
goto cleanup_qmessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an inactive timer to enforce maximum query
|
||||
* lifetime. It will be made active when the fetch is
|
||||
* started.
|
||||
*/
|
||||
iresult = isc_timer_create(res->timermgr, isc_timertype_inactive, NULL,
|
||||
NULL, res->buckets[bucketnum].task,
|
||||
fctx_expired, fctx, &fctx->timer);
|
||||
if (iresult != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_timer_create: %s",
|
||||
isc_result_totext(iresult));
|
||||
result = ISC_R_UNEXPECTED;
|
||||
goto cleanup_qmessage;
|
||||
}
|
||||
isc_timer_create(res->timermgr, res->buckets[bucketnum].task,
|
||||
fctx_expired, fctx, &fctx->timer);
|
||||
|
||||
/*
|
||||
* Default retry interval initialization. We set the interval
|
||||
|
|
@ -10029,8 +10026,7 @@ spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
if (res->spillat <= res->spillatmin) {
|
||||
result = isc_timer_reset(res->spillattimer,
|
||||
isc_timertype_inactive, NULL, NULL,
|
||||
true);
|
||||
isc_timertype_inactive, NULL, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
}
|
||||
count = res->spillat;
|
||||
|
|
@ -10167,13 +10163,9 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
|
|||
}
|
||||
isc_task_setname(task, "resolver_task", NULL);
|
||||
|
||||
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
|
||||
task, spillattimer_countdown, res,
|
||||
&res->spillattimer);
|
||||
isc_timer_create(timermgr, task, spillattimer_countdown, res,
|
||||
&res->spillattimer);
|
||||
isc_task_detach(&task);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_primelock;
|
||||
}
|
||||
|
||||
res->magic = RES_MAGIC;
|
||||
|
||||
|
|
@ -10405,8 +10397,7 @@ dns_resolver_shutdown(dns_resolver_t *res) {
|
|||
send_shutdown_events(res);
|
||||
}
|
||||
result = isc_timer_reset(res->spillattimer,
|
||||
isc_timertype_inactive, NULL, NULL,
|
||||
true);
|
||||
isc_timertype_inactive, NULL, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
}
|
||||
UNLOCK(&res->lock);
|
||||
|
|
|
|||
|
|
@ -1514,7 +1514,6 @@ cleanup_rbt:
|
|||
isc_result_t
|
||||
dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
|
||||
dns_rpz_zone_t *zone;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(rpzp != NULL && *rpzp == NULL);
|
||||
REQUIRE(rpzs != NULL);
|
||||
|
|
@ -1527,13 +1526,8 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
|
|||
memset(zone, 0, sizeof(*zone));
|
||||
isc_refcount_init(&zone->refs, 1);
|
||||
|
||||
result = isc_timer_create(rpzs->timermgr, isc_timertype_inactive, NULL,
|
||||
NULL, rpzs->updater,
|
||||
dns_rpz_update_taskaction, zone,
|
||||
&zone->updatetimer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_timer;
|
||||
}
|
||||
isc_timer_create(rpzs->timermgr, rpzs->updater,
|
||||
dns_rpz_update_taskaction, zone, &zone->updatetimer);
|
||||
|
||||
/*
|
||||
* This will never be used, but costs us nothing and
|
||||
|
|
@ -1573,14 +1567,6 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
|
|||
*rpzp = zone;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup_timer:
|
||||
isc_refcount_decrementz(&zone->refs);
|
||||
isc_refcount_destroy(&zone->refs);
|
||||
|
||||
isc_mem_put(rpzs->mctx, zone, sizeof(*zone));
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -1630,8 +1616,8 @@ dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
|
|||
isc_interval_set(&interval, (unsigned int)defer, 0);
|
||||
dns_db_currentversion(zone->db, &zone->dbversion);
|
||||
result = isc_timer_reset(zone->updatetimer,
|
||||
isc_timertype_once, NULL,
|
||||
&interval, true);
|
||||
isc_timertype_once, &interval,
|
||||
true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -1683,7 +1669,7 @@ dns_rpz_update_taskaction(isc_task_t *task, isc_event_t *event) {
|
|||
zone->updaterunning = true;
|
||||
dns_rpz_update_from_db(zone);
|
||||
result = isc_timer_reset(zone->updatetimer, isc_timertype_inactive,
|
||||
NULL, NULL, true);
|
||||
NULL, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
result = isc_time_now(&zone->lastupdated);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
|
@ -1784,7 +1770,7 @@ finish_update(dns_rpz_zone_t *rpz) {
|
|||
dname, defer);
|
||||
isc_interval_set(&interval, (unsigned int)defer, 0);
|
||||
isc_timer_reset(rpz->updatetimer, isc_timertype_once,
|
||||
NULL, &interval, true);
|
||||
&interval, true);
|
||||
} else {
|
||||
isc_event_t *event = NULL;
|
||||
INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
|
||||
|
|
@ -2224,7 +2210,7 @@ rpz_detach(dns_rpz_zone_t **rpzp) {
|
|||
}
|
||||
|
||||
isc_timer_reset(rpz->updatetimer, isc_timertype_inactive, NULL,
|
||||
NULL, true);
|
||||
true);
|
||||
isc_timer_detach(&rpz->updatetimer);
|
||||
|
||||
isc_ht_destroy(&rpz->nodes);
|
||||
|
|
|
|||
|
|
@ -15272,18 +15272,22 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) {
|
|||
if (isc_time_isepoch(&next)) {
|
||||
zone_debuglog(zone, me, 10, "settimer inactive");
|
||||
result = isc_timer_reset(zone->timer, isc_timertype_inactive,
|
||||
NULL, NULL, true);
|
||||
NULL, true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"could not deactivate zone timer: %s",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
} else {
|
||||
isc_interval_t interval;
|
||||
if (isc_time_compare(&next, now) <= 0) {
|
||||
next = *now;
|
||||
isc_interval_set(&interval, 0, 1);
|
||||
} else {
|
||||
isc_time_subtract(&next, now, &interval);
|
||||
}
|
||||
result = isc_timer_reset(zone->timer, isc_timertype_once, &next,
|
||||
NULL, true);
|
||||
|
||||
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",
|
||||
|
|
@ -18946,8 +18950,6 @@ dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
|
|||
|
||||
isc_result_t
|
||||
dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
|
||||
|
||||
|
|
@ -18972,13 +18974,8 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
|
|||
isc_task_setname(zone->task, "zone", zone);
|
||||
isc_task_setname(zone->loadtask, "loadzone", zone);
|
||||
|
||||
result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
|
||||
NULL, zone->task, zone_timer, zone,
|
||||
&zone->timer);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_tasks;
|
||||
}
|
||||
isc_timer_create(zmgr->timermgr, zone->task, zone_timer, zone,
|
||||
&zone->timer);
|
||||
|
||||
/*
|
||||
* The timer "holds" a iref.
|
||||
|
|
@ -18991,16 +18988,9 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
|
|||
zone->zmgr = zmgr;
|
||||
isc_refcount_increment(&zmgr->refs);
|
||||
|
||||
goto unlock;
|
||||
|
||||
cleanup_tasks:
|
||||
isc_task_detach(&zone->loadtask);
|
||||
isc_task_detach(&zone->task);
|
||||
|
||||
unlock:
|
||||
UNLOCK_ZONE(zone);
|
||||
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
|
||||
return (result);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -22485,7 +22475,6 @@ dns_zone_getserialupdatemethod(dns_zone_t *zone) {
|
|||
*/
|
||||
isc_result_t
|
||||
dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
|
||||
isc_result_t result;
|
||||
dns_zonemgr_t *zmgr;
|
||||
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
|
@ -22510,12 +22499,8 @@ dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
|
|||
LOCK_ZONE(zone);
|
||||
LOCK_ZONE(raw);
|
||||
|
||||
result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
|
||||
NULL, zone->task, zone_timer, raw,
|
||||
&raw->timer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto unlock;
|
||||
}
|
||||
isc_timer_create(zmgr->timermgr, zone->task, zone_timer, raw,
|
||||
&raw->timer);
|
||||
|
||||
/*
|
||||
* The timer "holds" a iref.
|
||||
|
|
@ -22536,11 +22521,10 @@ dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
|
|||
raw->zmgr = zmgr;
|
||||
isc_refcount_increment(&zmgr->refs);
|
||||
|
||||
unlock:
|
||||
UNLOCK_ZONE(raw);
|
||||
UNLOCK_ZONE(zone);
|
||||
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
|
||||
return (result);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/time.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
|
|
|||
|
|
@ -21,24 +21,6 @@
|
|||
#include <isc/lang.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
/***
|
||||
*** Intervals
|
||||
***/
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* The contents of this structure are private, and MUST NOT be accessed
|
||||
* directly by callers.
|
||||
*
|
||||
* The contents are exposed only to allow callers to avoid dynamic allocation.
|
||||
*/
|
||||
struct isc_interval {
|
||||
unsigned int seconds;
|
||||
unsigned int nanoseconds;
|
||||
};
|
||||
|
||||
extern const isc_interval_t *const isc_interval_zero;
|
||||
|
||||
/*
|
||||
* ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially
|
||||
* more for other locales to handle longer national abbreviations when
|
||||
|
|
@ -46,11 +28,16 @@ extern const isc_interval_t *const isc_interval_zero;
|
|||
*/
|
||||
#define ISC_FORMATHTTPTIMESTAMP_SIZE 50
|
||||
|
||||
/*
|
||||
* Semantic shims to distinguish between relative and absolute time
|
||||
*/
|
||||
#define isc_interval_zero isc_time_epoch
|
||||
#define isc_interval_t isc_time_t
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
void
|
||||
isc_interval_set(isc_interval_t *i, unsigned int seconds,
|
||||
unsigned int nanoseconds);
|
||||
#define isc_interval_set(i, seconds, nanoseconds) \
|
||||
isc_time_set((isc_time_t *)i, seconds, nanoseconds)
|
||||
/*%<
|
||||
* Set 'i' to a value representing an interval of 'seconds' seconds and
|
||||
* 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and
|
||||
|
|
@ -62,8 +49,7 @@ isc_interval_set(isc_interval_t *i, unsigned int seconds,
|
|||
*\li nanoseconds < 1000000000.
|
||||
*/
|
||||
|
||||
bool
|
||||
isc_interval_iszero(const isc_interval_t *i);
|
||||
#define isc_interval_iszero(i) isc_time_isepoch((const isc_time_t *)i)
|
||||
/*%<
|
||||
* Returns true iff. 'i' is the zero interval.
|
||||
*
|
||||
|
|
@ -72,8 +58,7 @@ isc_interval_iszero(const isc_interval_t *i);
|
|||
*\li 'i' is a valid pointer.
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
isc_interval_ms(const isc_interval_t *i);
|
||||
#define isc_interval_ms(i) isc_time_miliseconds((const isc_time_t *)i)
|
||||
/*%<
|
||||
* Returns interval 'i' expressed as a number of milliseconds.
|
||||
*
|
||||
|
|
@ -320,6 +305,16 @@ isc_time_nanoseconds(const isc_time_t *t);
|
|||
*\li The returned value is less than 1*10^9.
|
||||
*/
|
||||
|
||||
uint32_t
|
||||
isc_time_miliseconds(const isc_time_t *t);
|
||||
/*%<
|
||||
* Returns time 't' expressed as a number of milliseconds.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 't' is a valid pointer.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -24,13 +24,8 @@
|
|||
*
|
||||
*\li 'ticker' timers generate a periodic tick event.
|
||||
*
|
||||
*\li 'once' timers generate an idle timeout event if they are idle for too
|
||||
* long, and generate a life timeout event if their lifetime expires.
|
||||
* They are used to implement both (possibly expiring) idle timers and
|
||||
* 'one-shot' timers.
|
||||
*
|
||||
*\li 'limited' timers generate a periodic tick event until they reach
|
||||
* their lifetime when they generate a life timeout event.
|
||||
*\li 'once' timers generate an timeout event if the time reaches
|
||||
* the set interval.
|
||||
*
|
||||
*\li 'inactive' timers generate no events.
|
||||
*
|
||||
|
|
@ -83,7 +78,6 @@ typedef enum {
|
|||
isc_timertype_undefined = -1, /*%< Undefined */
|
||||
isc_timertype_ticker = 0, /*%< Ticker */
|
||||
isc_timertype_once = 1, /*%< Once */
|
||||
isc_timertype_limited = 2, /*%< Limited */
|
||||
isc_timertype_inactive = 3 /*%< Inactive */
|
||||
} isc_timertype_t;
|
||||
|
||||
|
|
@ -94,8 +88,7 @@ typedef struct isc_timerevent {
|
|||
|
||||
#define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0)
|
||||
#define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1)
|
||||
#define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2)
|
||||
#define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3)
|
||||
#define ISC_TIMEREVENT_ONCE (ISC_EVENTCLASS_TIMER + 2)
|
||||
#define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535)
|
||||
|
||||
/***
|
||||
|
|
@ -105,32 +98,15 @@ typedef struct isc_timerevent {
|
|||
*** those functions which return an isc_result_t.
|
||||
***/
|
||||
|
||||
isc_result_t
|
||||
isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
|
||||
const isc_time_t *expires, const isc_interval_t *interval,
|
||||
isc_task_t *task, isc_taskaction_t action, void *arg,
|
||||
isc_timer_t **timerp);
|
||||
void
|
||||
isc_timer_create(isc_timermgr_t *manager, isc_task_t *task,
|
||||
isc_taskaction_t action, void *arg, 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'.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
*\li For ticker timers, the timer will generate a 'tick' event every
|
||||
* 'interval' seconds. The value of 'expires' is ignored.
|
||||
*
|
||||
*\li For once timers, 'expires' specifies the time when a life timeout
|
||||
* event should be generated. If 'expires' is 0 (the epoch), then no life
|
||||
* timeout will be generated. 'interval' specifies how long the timer
|
||||
* can be idle before it generates an idle timeout. If 0, then no
|
||||
* idle timeout will be generated.
|
||||
*
|
||||
*\li If 'expires' is NULL, the epoch will be used.
|
||||
*
|
||||
* If 'interval' is NULL, the zero interval will be used.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'manager' is a valid manager
|
||||
|
|
@ -167,16 +143,20 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
|
|||
|
||||
isc_result_t
|
||||
isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
|
||||
const isc_time_t *expires, const isc_interval_t *interval,
|
||||
bool purge);
|
||||
const isc_interval_t *interval, bool purge);
|
||||
/*%<
|
||||
* Change the timer's type, expires, and interval values to the given
|
||||
* 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.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
*\li If 'expires' is NULL, the epoch will be used.
|
||||
*\li For ticker timers, the timer will generate a 'tick' event every
|
||||
* '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.
|
||||
*
|
||||
*\li If 'interval' is NULL, the zero interval will be used.
|
||||
*
|
||||
|
|
@ -184,8 +164,8 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
|
|||
*
|
||||
*\li 'timer' is a valid timer
|
||||
*
|
||||
*\li The same requirements that isc_timer_create() imposes on 'type',
|
||||
* 'expires' and 'interval' apply.
|
||||
*\li 'interval' points to a valid interval, or is NULL.
|
||||
*
|
||||
*
|
||||
* Ensures:
|
||||
*
|
||||
|
|
@ -200,27 +180,6 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
|
|||
*\li Unexpected error
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_timer_touch(isc_timer_t *timer);
|
||||
/*%<
|
||||
* Set the last-touched time of 'timer' to the current time.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'timer' is a valid once timer.
|
||||
*
|
||||
* 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 Unexpected error
|
||||
*/
|
||||
|
||||
void
|
||||
isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
|
||||
/*%<
|
||||
|
|
@ -277,7 +236,4 @@ isc_timer_gettype(isc_timer_t *timer);
|
|||
*\li 'timer' to be a valid timer.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_timermgr_poke(isc_timermgr_t *m);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ typedef struct isc_httpdurl isc_httpdurl_t; /*%< HTTP URL */
|
|||
typedef void(isc_httpdondestroy_t)(void *); /*%< Callback on destroying httpd */
|
||||
typedef struct isc_interface isc_interface_t; /*%< Interface */
|
||||
typedef struct isc_interfaceiter isc_interfaceiter_t; /*%< Interface Iterator */
|
||||
typedef struct isc_interval isc_interval_t; /*%< Interval */
|
||||
typedef struct isc_lex isc_lex_t; /*%< Lex */
|
||||
typedef struct isc_log isc_log_t; /*%< Log */
|
||||
typedef struct isc_logcategory isc_logcategory_t; /*%< Log Category */
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event);
|
|||
isc_result_t
|
||||
isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
|
||||
isc_task_t *task, isc_ratelimiter_t **ratelimiterp) {
|
||||
isc_result_t result;
|
||||
isc_ratelimiter_t *rl;
|
||||
INSIST(ratelimiterp != NULL && *ratelimiterp == NULL);
|
||||
|
||||
|
|
@ -74,11 +73,7 @@ isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
|
|||
|
||||
isc_mutex_init(&rl->lock);
|
||||
|
||||
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
|
||||
rl->task, ratelimiter_tick, rl, &rl->timer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto free_mutex;
|
||||
}
|
||||
isc_timer_create(timermgr, rl->task, ratelimiter_tick, rl, &rl->timer);
|
||||
|
||||
/*
|
||||
* Increment the reference count to indicate that we may
|
||||
|
|
@ -92,13 +87,6 @@ isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
|
|||
|
||||
*ratelimiterp = rl;
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
free_mutex:
|
||||
isc_refcount_decrementz(&rl->references);
|
||||
isc_refcount_destroy(&rl->references);
|
||||
isc_mutex_destroy(&rl->lock);
|
||||
isc_mem_put(mctx, rl, sizeof(*rl));
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -114,7 +102,7 @@ isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval) {
|
|||
* If the timer is currently running, change its rate.
|
||||
*/
|
||||
if (rl->state == isc_ratelimiter_ratelimited) {
|
||||
result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
|
||||
result = isc_timer_reset(rl->timer, isc_timertype_ticker,
|
||||
&rl->interval, false);
|
||||
}
|
||||
UNLOCK(&rl->lock);
|
||||
|
|
@ -162,7 +150,7 @@ isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
|
|||
ISC_LIST_APPEND(rl->pending, ev, ev_ratelink);
|
||||
}
|
||||
} else if (rl->state == isc_ratelimiter_idle) {
|
||||
result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
|
||||
result = isc_timer_reset(rl->timer, isc_timertype_ticker,
|
||||
&rl->interval, false);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
ev->ev_sender = task;
|
||||
|
|
@ -223,8 +211,7 @@ ratelimiter_tick(isc_task_t *task, isc_event_t *event) {
|
|||
* waste resources by having it fire periodically.
|
||||
*/
|
||||
isc_result_t result = isc_timer_reset(
|
||||
rl->timer, isc_timertype_inactive, NULL, NULL,
|
||||
false);
|
||||
rl->timer, isc_timertype_inactive, NULL, false);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
rl->state = isc_ratelimiter_idle;
|
||||
pertic = 0; /* Force the loop to exit. */
|
||||
|
|
@ -247,8 +234,7 @@ isc_ratelimiter_shutdown(isc_ratelimiter_t *rl) {
|
|||
|
||||
LOCK(&rl->lock);
|
||||
rl->state = isc_ratelimiter_shuttingdown;
|
||||
(void)isc_timer_reset(rl->timer, isc_timertype_inactive, NULL, NULL,
|
||||
false);
|
||||
(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);
|
||||
|
|
@ -323,7 +309,7 @@ isc_ratelimiter_stall(isc_ratelimiter_t *rl) {
|
|||
break;
|
||||
case isc_ratelimiter_ratelimited:
|
||||
result = isc_timer_reset(rl->timer, isc_timertype_inactive,
|
||||
NULL, NULL, false);
|
||||
NULL, false);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
/* FALLTHROUGH */
|
||||
case isc_ratelimiter_idle:
|
||||
|
|
@ -349,7 +335,7 @@ isc_ratelimiter_release(isc_ratelimiter_t *rl) {
|
|||
case isc_ratelimiter_stalled:
|
||||
if (!ISC_LIST_EMPTY(rl->pending)) {
|
||||
result = isc_timer_reset(rl->timer,
|
||||
isc_timertype_ticker, NULL,
|
||||
isc_timertype_ticker,
|
||||
&rl->interval, false);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
rl->state = isc_ratelimiter_ratelimited;
|
||||
|
|
|
|||
|
|
@ -480,7 +480,6 @@ basic(void **state) {
|
|||
isc_event_t *event = NULL;
|
||||
isc_timer_t *ti1 = NULL;
|
||||
isc_timer_t *ti2 = NULL;
|
||||
isc_time_t absolute;
|
||||
isc_interval_t interval;
|
||||
char *testarray[] = { one, one, one, one, one, one, one, one,
|
||||
one, two, three, four, two, three, four, NULL };
|
||||
|
|
@ -506,17 +505,15 @@ basic(void **state) {
|
|||
result = isc_task_onshutdown(task4, basic_shutdown, four);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_time_settoepoch(&absolute);
|
||||
isc_interval_set(&interval, 1, 0);
|
||||
result = isc_timer_create(timermgr, isc_timertype_ticker, &absolute,
|
||||
&interval, task1, basic_tick, tick, &ti1);
|
||||
isc_timer_create(timermgr, task1, basic_tick, tick, &ti1);
|
||||
result = isc_timer_reset(ti1, isc_timertype_ticker, &interval, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
ti2 = NULL;
|
||||
isc_time_settoepoch(&absolute);
|
||||
isc_interval_set(&interval, 1, 0);
|
||||
result = isc_timer_create(timermgr, isc_timertype_ticker, &absolute,
|
||||
&interval, task2, basic_tick, tock, &ti2);
|
||||
isc_timer_create(timermgr, task2, basic_tick, tock, &ti2);
|
||||
result = isc_timer_reset(ti2, isc_timertype_ticker, &interval, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
sleep(2);
|
||||
|
|
|
|||
|
|
@ -102,8 +102,7 @@ shutdown(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
|
||||
static void
|
||||
setup_test(isc_timertype_t timertype, isc_time_t *expires,
|
||||
isc_interval_t *interval,
|
||||
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;
|
||||
|
|
@ -130,8 +129,8 @@ setup_test(isc_timertype_t timertype, isc_time_t *expires,
|
|||
isc_mutex_unlock(&lasttime_mx);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_timer_create(timermgr, timertype, expires, interval, task,
|
||||
action, (void *)timertype, &timer);
|
||||
isc_timer_create(timermgr, task, action, (void *)timertype, &timer);
|
||||
result = isc_timer_reset(timer, timertype, interval, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
|
|
@ -207,7 +206,7 @@ ticktock(isc_task_t *task, isc_event_t *event) {
|
|||
print_message("# tick %d\n", tick);
|
||||
}
|
||||
|
||||
expected_event_type = ISC_TIMEREVENT_LIFE;
|
||||
expected_event_type = ISC_TIMEREVENT_ONCE;
|
||||
if ((uintptr_t)event->ev_arg == isc_timertype_ticker) {
|
||||
expected_event_type = ISC_TIMEREVENT_TICK;
|
||||
}
|
||||
|
|
@ -259,7 +258,6 @@ ticktock(isc_task_t *task, isc_event_t *event) {
|
|||
/* timer type ticker */
|
||||
static void
|
||||
ticker(void **state) {
|
||||
isc_time_t expires;
|
||||
isc_interval_t interval;
|
||||
|
||||
UNUSED(state);
|
||||
|
|
@ -269,31 +267,8 @@ ticker(void **state) {
|
|||
nanoseconds = 500000000;
|
||||
|
||||
isc_interval_set(&interval, seconds, nanoseconds);
|
||||
isc_time_settoepoch(&expires);
|
||||
|
||||
setup_test(isc_timertype_ticker, &expires, &interval, ticktock);
|
||||
}
|
||||
|
||||
/* timer type once reaches lifetime */
|
||||
static void
|
||||
once_life(void **state) {
|
||||
isc_result_t result;
|
||||
isc_time_t expires;
|
||||
isc_interval_t interval;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
nevents = 1;
|
||||
seconds = 1;
|
||||
nanoseconds = 100000000;
|
||||
|
||||
isc_interval_set(&interval, seconds, nanoseconds);
|
||||
result = isc_time_nowplusinterval(&expires, &interval);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_interval_set(&interval, 0, 0);
|
||||
|
||||
setup_test(isc_timertype_once, &expires, &interval, ticktock);
|
||||
setup_test(isc_timertype_ticker, &interval, ticktock);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -335,7 +310,7 @@ test_idle(isc_task_t *task, isc_event_t *event) {
|
|||
isc_time_add(&now, &interval, &lasttime);
|
||||
isc_mutex_unlock(&lasttime_mx);
|
||||
|
||||
subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_IDLE);
|
||||
subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_ONCE);
|
||||
|
||||
isc_timer_detach(&timer);
|
||||
isc_task_shutdown(task);
|
||||
|
|
@ -345,8 +320,6 @@ test_idle(isc_task_t *task, isc_event_t *event) {
|
|||
/* timer type once idles out */
|
||||
static void
|
||||
once_idle(void **state) {
|
||||
isc_result_t result;
|
||||
isc_time_t expires;
|
||||
isc_interval_t interval;
|
||||
|
||||
UNUSED(state);
|
||||
|
|
@ -355,13 +328,9 @@ once_idle(void **state) {
|
|||
seconds = 1;
|
||||
nanoseconds = 200000000;
|
||||
|
||||
isc_interval_set(&interval, seconds + 1, nanoseconds);
|
||||
result = isc_time_nowplusinterval(&expires, &interval);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_interval_set(&interval, seconds, nanoseconds);
|
||||
|
||||
setup_test(isc_timertype_once, &expires, &interval, test_idle);
|
||||
setup_test(isc_timertype_once, &interval, test_idle);
|
||||
}
|
||||
|
||||
/* timer reset */
|
||||
|
|
@ -372,7 +341,6 @@ test_reset(isc_task_t *task, isc_event_t *event) {
|
|||
isc_time_t base;
|
||||
isc_time_t ulim;
|
||||
isc_time_t llim;
|
||||
isc_time_t expires;
|
||||
isc_interval_t interval;
|
||||
|
||||
int tick = atomic_fetch_add(&eventcnt, 1);
|
||||
|
|
@ -413,19 +381,14 @@ test_reset(isc_task_t *task, isc_event_t *event) {
|
|||
|
||||
if (_eventcnt < 3) {
|
||||
subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_TICK);
|
||||
|
||||
if (_eventcnt == 2) {
|
||||
isc_interval_set(&interval, seconds, nanoseconds);
|
||||
result = isc_time_nowplusinterval(&expires, &interval);
|
||||
subthread_assert_result_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_interval_set(&interval, 0, 0);
|
||||
result = isc_timer_reset(timer, isc_timertype_once,
|
||||
&expires, &interval, false);
|
||||
&interval, false);
|
||||
subthread_assert_result_equal(result, ISC_R_SUCCESS);
|
||||
}
|
||||
} else {
|
||||
subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_LIFE);
|
||||
subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_ONCE);
|
||||
|
||||
isc_timer_detach(&timer);
|
||||
isc_task_shutdown(task);
|
||||
|
|
@ -436,7 +399,6 @@ test_reset(isc_task_t *task, isc_event_t *event) {
|
|||
|
||||
static void
|
||||
reset(void **state) {
|
||||
isc_time_t expires;
|
||||
isc_interval_t interval;
|
||||
|
||||
UNUSED(state);
|
||||
|
|
@ -446,9 +408,8 @@ reset(void **state) {
|
|||
nanoseconds = 750000000;
|
||||
|
||||
isc_interval_set(&interval, seconds, nanoseconds);
|
||||
isc_time_settoepoch(&expires);
|
||||
|
||||
setup_test(isc_timertype_ticker, &expires, &interval, test_reset);
|
||||
setup_test(isc_timertype_ticker, &interval, test_reset);
|
||||
}
|
||||
|
||||
static atomic_bool startflag;
|
||||
|
|
@ -492,7 +453,7 @@ tick_event(isc_task_t *task, isc_event_t *event) {
|
|||
isc_time_settoepoch(&expires);
|
||||
isc_interval_set(&interval, seconds, 0);
|
||||
result = isc_timer_reset(tickertimer, isc_timertype_ticker,
|
||||
&expires, &interval, true);
|
||||
&interval, true);
|
||||
subthread_assert_result_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_task_shutdown(task);
|
||||
|
|
@ -537,7 +498,6 @@ shutdown_purge(isc_task_t *task, isc_event_t *event) {
|
|||
static void
|
||||
purge(void **state) {
|
||||
isc_result_t result;
|
||||
isc_time_t expires;
|
||||
isc_interval_t interval;
|
||||
|
||||
UNUSED(state);
|
||||
|
|
@ -557,25 +517,21 @@ purge(void **state) {
|
|||
result = isc_task_create(taskmgr, 0, &task2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_time_settoepoch(&expires);
|
||||
isc_interval_set(&interval, seconds, 0);
|
||||
|
||||
tickertimer = NULL;
|
||||
result = isc_timer_create(timermgr, isc_timertype_ticker, &expires,
|
||||
&interval, task1, tick_event, NULL,
|
||||
&tickertimer);
|
||||
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);
|
||||
|
||||
oncetimer = NULL;
|
||||
|
||||
isc_interval_set(&interval, (seconds * 2) + 1, 0);
|
||||
result = isc_time_nowplusinterval(&expires, &interval);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_interval_set(&interval, 0, 0);
|
||||
result = isc_timer_create(timermgr, isc_timertype_once, &expires,
|
||||
&interval, task2, once_event, NULL,
|
||||
&oncetimer);
|
||||
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);
|
||||
|
||||
/*
|
||||
|
|
@ -598,8 +554,9 @@ purge(void **state) {
|
|||
int
|
||||
main(int argc, char **argv) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(ticker), cmocka_unit_test(once_life),
|
||||
cmocka_unit_test(once_idle), cmocka_unit_test(reset),
|
||||
cmocka_unit_test(ticker),
|
||||
cmocka_unit_test(once_idle),
|
||||
cmocka_unit_test(reset),
|
||||
cmocka_unit_test(purge),
|
||||
};
|
||||
int c;
|
||||
|
|
|
|||
|
|
@ -51,49 +51,6 @@
|
|||
#define CLOCKSOURCE_HIRES CLOCKSOURCE
|
||||
#endif /* #ifndef CLOCKSOURCE_HIRES */
|
||||
|
||||
/*%
|
||||
*** Intervals
|
||||
***/
|
||||
|
||||
#if !defined(UNIT_TESTING)
|
||||
static const isc_interval_t zero_interval = { 0, 0 };
|
||||
const isc_interval_t *const isc_interval_zero = &zero_interval;
|
||||
#endif
|
||||
|
||||
void
|
||||
isc_interval_set(isc_interval_t *i, unsigned int seconds,
|
||||
unsigned int nanoseconds) {
|
||||
REQUIRE(i != NULL);
|
||||
REQUIRE(nanoseconds < NS_PER_S);
|
||||
|
||||
i->seconds = seconds;
|
||||
i->nanoseconds = nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
isc_interval_iszero(const isc_interval_t *i) {
|
||||
REQUIRE(i != NULL);
|
||||
INSIST(i->nanoseconds < NS_PER_S);
|
||||
|
||||
if (i->seconds == 0 && i->nanoseconds == 0) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_interval_ms(const isc_interval_t *i) {
|
||||
REQUIRE(i != NULL);
|
||||
INSIST(i->nanoseconds < NS_PER_S);
|
||||
|
||||
return ((i->seconds * MS_PER_S) + (i->nanoseconds / NS_PER_MS));
|
||||
}
|
||||
|
||||
/***
|
||||
*** Absolute Times
|
||||
***/
|
||||
|
||||
#if !defined(UNIT_TESTING)
|
||||
static const isc_time_t epoch = { 0, 0 };
|
||||
const isc_time_t *const isc_time_epoch = &epoch;
|
||||
|
|
@ -131,11 +88,11 @@ isc_time_isepoch(const isc_time_t *t) {
|
|||
static inline isc_result_t
|
||||
time_now(isc_time_t *t, clockid_t clock) {
|
||||
struct timespec ts;
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
|
||||
REQUIRE(t != NULL);
|
||||
|
||||
if (clock_gettime(clock, &ts) == -1) {
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
strerror_r(errno, strbuf, sizeof(strbuf));
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
|
||||
return (ISC_R_UNEXPECTED);
|
||||
|
|
@ -173,13 +130,13 @@ isc_time_now(isc_time_t *t) {
|
|||
isc_result_t
|
||||
isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
|
||||
struct timespec ts;
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
|
||||
REQUIRE(t != NULL);
|
||||
REQUIRE(i != NULL);
|
||||
INSIST(i->nanoseconds < NS_PER_S);
|
||||
|
||||
if (clock_gettime(CLOCKSOURCE, &ts) == -1) {
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
strerror_r(errno, strbuf, sizeof(strbuf));
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
|
||||
return (ISC_R_UNEXPECTED);
|
||||
|
|
@ -373,6 +330,14 @@ isc_time_nanoseconds(const isc_time_t *t) {
|
|||
return ((uint32_t)t->nanoseconds);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
isc_time_miliseconds(const isc_time_t *t) {
|
||||
REQUIRE(t != NULL);
|
||||
INSIST(t->nanoseconds < NS_PER_S);
|
||||
|
||||
return ((t->seconds * MS_PER_S) + (t->nanoseconds / NS_PER_MS));
|
||||
}
|
||||
|
||||
void
|
||||
isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
|
||||
time_t now;
|
||||
|
|
|
|||
329
lib/isc/timer.c
329
lib/isc/timer.c
|
|
@ -64,7 +64,6 @@ struct isc_timer {
|
|||
isc_time_t idle;
|
||||
/*! Locked by manager lock. */
|
||||
isc_timertype_t type;
|
||||
isc_time_t expires;
|
||||
isc_interval_t interval;
|
||||
isc_task_t *task;
|
||||
isc_taskaction_t action;
|
||||
|
|
@ -92,46 +91,34 @@ struct isc_timermgr {
|
|||
isc_heap_t *heap;
|
||||
};
|
||||
|
||||
void
|
||||
isc_timermgr_poke(isc_timermgr_t *manager);
|
||||
|
||||
static inline isc_result_t
|
||||
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.
|
||||
*/
|
||||
|
||||
REQUIRE(timer->type != isc_timertype_inactive);
|
||||
|
||||
manager = timer->manager;
|
||||
|
||||
/*
|
||||
* Compute the new due time.
|
||||
*/
|
||||
if (timer->type != isc_timertype_once) {
|
||||
isc_result_t result = isc_time_add(now, &timer->interval, &due);
|
||||
switch (timer->type) {
|
||||
case isc_timertype_ticker:
|
||||
result = isc_time_add(now, &timer->interval, &due);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
if (timer->type == isc_timertype_limited &&
|
||||
isc_time_compare(&timer->expires, &due) < 0)
|
||||
{
|
||||
due = timer->expires;
|
||||
}
|
||||
} else {
|
||||
if (isc_time_isepoch(&timer->idle)) {
|
||||
due = timer->expires;
|
||||
} else if (isc_time_isepoch(&timer->expires)) {
|
||||
due = timer->idle;
|
||||
} else if (isc_time_compare(&timer->idle, &timer->expires) < 0)
|
||||
{
|
||||
due = timer->idle;
|
||||
} else {
|
||||
due = timer->expires;
|
||||
}
|
||||
break;
|
||||
case isc_timertype_once:
|
||||
due = timer->idle;
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -175,10 +162,10 @@ schedule(isc_timer_t *timer, isc_time_t *now, bool signal_ok) {
|
|||
SIGNAL(&manager->wakeup);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
deschedule(isc_timer_t *timer) {
|
||||
isc_timermgr_t *manager;
|
||||
|
||||
|
|
@ -227,123 +214,58 @@ destroy(isc_timer_t *timer) {
|
|||
isc_mem_put(manager->mctx, timer, sizeof(*timer));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
|
||||
const isc_time_t *expires, const isc_interval_t *interval,
|
||||
isc_task_t *task, isc_taskaction_t action, void *arg,
|
||||
isc_timer_t **timerp) {
|
||||
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);
|
||||
|
||||
isc_timer_t *timer;
|
||||
isc_result_t result;
|
||||
isc_time_t now;
|
||||
|
||||
/*
|
||||
* 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'.
|
||||
*/
|
||||
if (expires == NULL) {
|
||||
expires = isc_time_epoch;
|
||||
}
|
||||
if (interval == NULL) {
|
||||
interval = isc_interval_zero;
|
||||
}
|
||||
REQUIRE(type == isc_timertype_inactive ||
|
||||
!(isc_time_isepoch(expires) && isc_interval_iszero(interval)));
|
||||
REQUIRE(timerp != NULL && *timerp == NULL);
|
||||
REQUIRE(type != isc_timertype_limited ||
|
||||
!(isc_time_isepoch(expires) || 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);
|
||||
}
|
||||
TIME_NOW(&now);
|
||||
|
||||
timer = isc_mem_get(manager->mctx, sizeof(*timer));
|
||||
*timer = (isc_timer_t){
|
||||
.manager = manager,
|
||||
.type = isc_timertype_inactive,
|
||||
.interval = *isc_interval_zero,
|
||||
.action = action,
|
||||
.arg = arg,
|
||||
};
|
||||
|
||||
timer->manager = manager;
|
||||
isc_refcount_init(&timer->references, 1);
|
||||
|
||||
if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
|
||||
result = isc_time_add(&now, interval, &timer->idle);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(manager->mctx, timer, sizeof(*timer));
|
||||
return (result);
|
||||
}
|
||||
} else {
|
||||
isc_time_settoepoch(&timer->idle);
|
||||
}
|
||||
isc_time_settoepoch(&timer->idle);
|
||||
|
||||
timer->type = type;
|
||||
timer->expires = *expires;
|
||||
timer->interval = *interval;
|
||||
timer->task = NULL;
|
||||
isc_task_attach(task, &timer->task);
|
||||
timer->action = action;
|
||||
/*
|
||||
* Removing the const attribute from "arg" is the best of two
|
||||
* evils here. If the timer->arg member is made const, then
|
||||
* it affects a great many recipients of the timer event
|
||||
* which did not pass in an "arg" that was truly const.
|
||||
* Changing isc_timer_create() to not have "arg" prototyped as const,
|
||||
* though, can cause compilers warnings for calls that *do*
|
||||
* have a truly const arg. The caller will have to carefully
|
||||
* keep track of whether arg started as a true const.
|
||||
*/
|
||||
DE_CONST(arg, timer->arg);
|
||||
timer->index = 0;
|
||||
|
||||
isc_mutex_init(&timer->lock);
|
||||
ISC_LINK_INIT(timer, link);
|
||||
timer->magic = TIMER_MAGIC;
|
||||
|
||||
LOCK(&manager->lock);
|
||||
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.
|
||||
*/
|
||||
|
||||
if (type != isc_timertype_inactive) {
|
||||
result = schedule(timer, &now, true);
|
||||
} else {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
*timerp = timer;
|
||||
APPEND(manager->timers, timer, link);
|
||||
}
|
||||
*timerp = timer;
|
||||
|
||||
LOCK(&manager->lock);
|
||||
APPEND(manager->timers, timer, link);
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
timer->magic = 0;
|
||||
isc_mutex_destroy(&timer->lock);
|
||||
isc_task_detach(&timer->task);
|
||||
isc_mem_put(manager->mctx, timer, sizeof(*timer));
|
||||
return (result);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
|
||||
const isc_time_t *expires, const isc_interval_t *interval,
|
||||
bool purge) {
|
||||
const isc_interval_t *interval, bool purge) {
|
||||
isc_time_t now;
|
||||
isc_timermgr_t *manager;
|
||||
isc_result_t result;
|
||||
|
|
@ -358,16 +280,11 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
|
|||
manager = timer->manager;
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
|
||||
if (expires == NULL) {
|
||||
expires = isc_time_epoch;
|
||||
}
|
||||
if (interval == NULL) {
|
||||
interval = isc_interval_zero;
|
||||
}
|
||||
REQUIRE(type == isc_timertype_inactive ||
|
||||
!(isc_time_isepoch(expires) && isc_interval_iszero(interval)));
|
||||
REQUIRE(type != isc_timertype_limited ||
|
||||
!(isc_time_isepoch(expires) || isc_interval_iszero(interval)));
|
||||
!isc_interval_iszero(interval));
|
||||
|
||||
/*
|
||||
* Get current time.
|
||||
|
|
@ -392,7 +309,6 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
|
|||
ISC_TIMEREVENT_LASTEVENT, NULL);
|
||||
}
|
||||
timer->type = type;
|
||||
timer->expires = *expires;
|
||||
timer->interval = *interval;
|
||||
if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
|
||||
result = isc_time_add(&now, interval, &timer->idle);
|
||||
|
|
@ -429,36 +345,6 @@ isc_timer_gettype(isc_timer_t *timer) {
|
|||
return (t);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_timer_touch(isc_timer_t *timer) {
|
||||
isc_result_t result;
|
||||
isc_time_t now;
|
||||
|
||||
/*
|
||||
* Set the last-touched time of 'timer' to the current time.
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_TIMER(timer));
|
||||
|
||||
LOCK(&timer->lock);
|
||||
|
||||
/*
|
||||
* We'd like to
|
||||
*
|
||||
* REQUIRE(timer->type == isc_timertype_once);
|
||||
*
|
||||
* but we cannot without locking the manager lock too, which we
|
||||
* don't want to do.
|
||||
*/
|
||||
|
||||
TIME_NOW(&now);
|
||||
result = isc_time_add(&now, &timer->interval, &timer->idle);
|
||||
|
||||
UNLOCK(&timer->lock);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
|
||||
REQUIRE(VALID_TIMER(timer));
|
||||
|
|
@ -488,107 +374,73 @@ isc_timer_detach(isc_timer_t **timerp) {
|
|||
}
|
||||
|
||||
static void
|
||||
dispatch(isc_timermgr_t *manager, isc_time_t *now) {
|
||||
bool done = false, post_event, need_schedule;
|
||||
post_event(isc_timermgr_t *manager, isc_timer_t *timer, isc_eventtype_t type) {
|
||||
isc_timerevent_t *event;
|
||||
XTRACEID("posting", timer);
|
||||
/*
|
||||
* XXX We could preallocate this event.
|
||||
*/
|
||||
event = (isc_timerevent_t *)isc_event_allocate(
|
||||
manager->mctx, timer, type, timer->action, timer->arg,
|
||||
sizeof(*event));
|
||||
|
||||
if (event != NULL) {
|
||||
event->due = timer->due;
|
||||
isc_task_send(timer->task, ISC_EVENT_PTR(&event));
|
||||
} else {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__, "%s",
|
||||
"couldn't allocate event");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
bool idle;
|
||||
|
||||
/*!
|
||||
* The caller must be holding the manager lock.
|
||||
*/
|
||||
|
||||
while (manager->nscheduled > 0 && !done) {
|
||||
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) {
|
||||
if (timer->type == isc_timertype_ticker) {
|
||||
type = ISC_TIMEREVENT_TICK;
|
||||
post_event = true;
|
||||
need_schedule = true;
|
||||
} else if (timer->type == isc_timertype_limited) {
|
||||
int cmp;
|
||||
cmp = isc_time_compare(now, &timer->expires);
|
||||
if (cmp >= 0) {
|
||||
type = ISC_TIMEREVENT_LIFE;
|
||||
post_event = true;
|
||||
need_schedule = false;
|
||||
} else {
|
||||
type = ISC_TIMEREVENT_TICK;
|
||||
post_event = true;
|
||||
need_schedule = true;
|
||||
}
|
||||
} else if (!isc_time_isepoch(&timer->expires) &&
|
||||
isc_time_compare(now, &timer->expires) >= 0)
|
||||
{
|
||||
type = ISC_TIMEREVENT_LIFE;
|
||||
post_event = true;
|
||||
need_schedule = false;
|
||||
} else {
|
||||
idle = false;
|
||||
|
||||
LOCK(&timer->lock);
|
||||
if (!isc_time_isepoch(&timer->idle) &&
|
||||
isc_time_compare(now, &timer->idle) >= 0) {
|
||||
idle = true;
|
||||
}
|
||||
UNLOCK(&timer->lock);
|
||||
if (idle) {
|
||||
type = ISC_TIMEREVENT_IDLE;
|
||||
post_event = true;
|
||||
need_schedule = false;
|
||||
} else {
|
||||
/*
|
||||
* Idle timer has been touched;
|
||||
* reschedule.
|
||||
*/
|
||||
XTRACEID("idle reschedule", timer);
|
||||
post_event = false;
|
||||
need_schedule = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (post_event) {
|
||||
XTRACEID("posting", timer);
|
||||
/*
|
||||
* XXX We could preallocate this event.
|
||||
*/
|
||||
event = (isc_timerevent_t *)isc_event_allocate(
|
||||
manager->mctx, timer, type,
|
||||
timer->action, timer->arg,
|
||||
sizeof(*event));
|
||||
|
||||
if (event != NULL) {
|
||||
event->due = timer->due;
|
||||
isc_task_send(timer->task,
|
||||
ISC_EVENT_PTR(&event));
|
||||
} else {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"%s",
|
||||
"couldn't allocate "
|
||||
"event");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isc_time_compare(now, &timer->due) < 0) {
|
||||
manager->due = timer->due;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
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:
|
||||
INSIST(0);
|
||||
ISC_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -680,13 +532,6 @@ isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
|
|||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_timermgr_poke(isc_timermgr_t *manager) {
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
|
||||
SIGNAL(&manager->wakeup);
|
||||
}
|
||||
|
||||
void
|
||||
isc__timermgr_destroy(isc_timermgr_t **managerp) {
|
||||
isc_timermgr_t *manager;
|
||||
|
|
|
|||
Loading…
Reference in a new issue