diff --git a/bin/tests/timer_test.c b/bin/tests/timer_test.c index 023b7b9efc..ea41111102 100644 --- a/bin/tests/timer_test.c +++ b/bin/tests/timer_test.c @@ -47,7 +47,7 @@ tick(task_t task, task_event_t event) interval.seconds = 4; interval.nanoseconds = 0; printf("*** resetting ti3 ***\n"); - INSIST(timer_reset(ti3, timer_type_idle, expires, interval) + INSIST(timer_reset(ti3, timer_type_once, expires, interval) == ISC_R_SUCCESS); } @@ -106,7 +106,7 @@ main(int argc, char *argv[]) { expires.nanoseconds = 0; interval.seconds = 2; interval.nanoseconds = 0; - INSIST(timer_create(timgr, timer_type_idle, expires, interval, + INSIST(timer_create(timgr, timer_type_once, expires, interval, t2, timeout, "2", &ti2) == ISC_R_SUCCESS); expires.seconds = 0; expires.nanoseconds = 0; @@ -119,7 +119,7 @@ main(int argc, char *argv[]) { os_time_add(&now, &expires, &expires); interval.seconds = 2; interval.nanoseconds = 0; - INSIST(timer_create(timgr, timer_type_idle, expires, interval, + INSIST(timer_create(timgr, timer_type_once, expires, interval, t3, timeout, "3", &ti3) == ISC_R_SUCCESS); task_detach(&t1); diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h index aadb8bb4ef..dcf3b15bbd 100644 --- a/lib/isc/include/isc/timer.h +++ b/lib/isc/include/isc/timer.h @@ -15,10 +15,10 @@ * * 'ticker' timers generate a periodic tick event. * - * 'idle' timers generate an idle timeout event if they are idle for too + * '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 expiring idle timers and 'one-shot' - * timers. + * They are used to implement both (possibly expiring) idle timers and + * 'one-shot' timers. * * Note: unlike in eventlib, a timer's resources are never reclaimed merely * because it generated an event. A timer reference will remain valid until @@ -67,7 +67,7 @@ typedef struct timer_t *timer_t; typedef struct timer_manager_t *timer_manager_t; typedef enum { - timer_type_ticker = 0, timer_type_idle + timer_type_ticker = 0, timer_type_once } timer_type_t; typedef struct timer_event { @@ -107,7 +107,7 @@ timer_create(timer_manager_t manager, * For ticker timers, the timer will generate a 'tick' event every * 'interval' seconds. The value of 'expires' is ignored. * - * For idle timers, 'expires' specifies the time when a life timeout + * For once timers, 'expires' specifies the time when a life timeout * event should be generated. If 'expires' is 0, 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 @@ -131,8 +131,9 @@ timer_create(timer_manager_t manager, * * The timer is attached to the task * - * If 'type' is idle, then the last-touched time is set to the - * current time. + * 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: * @@ -159,8 +160,9 @@ timer_reset(timer_t timer, * * Ensures: * - * If 'type' is idle, then the last-touched time is set to the - * current time. + * 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: * @@ -196,12 +198,13 @@ timer_touch(timer_t timer); * * Requires: * - * 'timer' is a valid idle timer. + * 'timer' is a valid once timer. * * Ensures: * * An idle timeout will not be generated until at least Now + the - * timer's interval if 'timer' is an idle timer. + * timer's interval if 'timer' is a once timer with a non-zero + * interval. * * Returns: * diff --git a/lib/isc/task.c b/lib/isc/task.c index 38ee8e6b09..bca4a08c10 100644 --- a/lib/isc/task.c +++ b/lib/isc/task.c @@ -26,7 +26,7 @@ #define WAIT(cvp, lp) INSIST(os_condition_wait((cvp), (lp))) #define BROADCAST(cvp) INSIST(os_condition_broadcast((cvp))) -#ifdef DEBUGTRACE +#ifdef TASK_TRACE #define XTRACE(m) printf("%s task %p thread %p\n", (m), \ task, os_thread_self()) #else diff --git a/lib/isc/timer.c b/lib/isc/timer.c index 79314614a5..727ff279f6 100644 --- a/lib/isc/timer.c +++ b/lib/isc/timer.c @@ -152,10 +152,12 @@ schedule(timer_t timer, os_time_t *nowp, boolean_t broadcast_ok) { manager->nscheduled++; } +#ifdef TIMER_TRACE printf("schedule %p at %lu.%09lu\n", timer, (unsigned long)due.seconds, (unsigned long)due.nanoseconds); +#endif /* * If this timer is at the head of the queue, we wake up the run @@ -164,7 +166,9 @@ schedule(timer_t timer, os_time_t *nowp, boolean_t broadcast_ok) { * want it to oversleep. */ if (timer->index == 1 && broadcast_ok) { +#ifdef TIMER_TRACE printf("broadcast (schedule)\n"); +#endif BROADCAST(&manager->wakeup); } @@ -189,7 +193,9 @@ deschedule(timer_t timer) { INSIST(manager->nscheduled > 0); manager->nscheduled--; if (need_wakeup) { +#ifdef TIMER_TRACE printf("broadcast (deschedule)\n"); +#endif BROADCAST(&manager->wakeup); } } @@ -258,7 +264,7 @@ timer_create(timer_manager_t manager, timer_type_t type, timer->magic = TIMER_MAGIC; timer->manager = manager; timer->references = 1; - if (type == timer_type_idle && !ZERO(interval)) + if (type == timer_type_once && !ZERO(interval)) os_time_add(&now, &interval, &timer->idle); else { timer->idle.seconds = 0; @@ -333,7 +339,7 @@ timer_reset(timer_t timer, timer_type_t type, timer->type = type; timer->expires = expires; timer->interval = interval; - if (type == timer_type_idle && !ZERO(interval)) + if (type == timer_type_once && !ZERO(interval)) os_time_add(&now, &interval, &timer->idle); else { timer->idle.seconds = 0; @@ -385,7 +391,7 @@ timer_touch(timer_t timer) { LOCK(&timer->lock); - INSIST(timer->type == timer_type_idle); + INSIST(timer->type == timer_type_once); result = os_time_get(&now); if (result != ISC_R_SUCCESS) { @@ -474,20 +480,25 @@ dispatch(timer_manager_t manager, os_time_t *nowp) { /* * Idle timer has been touched; reschedule. */ +#ifdef TIMER_TRACE printf("timer %p idle reschedule\n", timer); +#endif post_event = FALSE; need_schedule = TRUE; } if (post_event) { +#ifdef TIMER_TRACE printf("timer %p posting %u\n", timer, type); +#endif event = task_event_allocate(manager->mctx, timer, type, timer->action, timer->arg, sizeof *event); + if (event != NULL) INSIST(task_send_event(timer->task, &event)); @@ -524,26 +535,36 @@ run(void *uap) { LOCK(&manager->lock); while (!manager->done) { INSIST(os_time_get(&now) == ISC_R_SUCCESS); +#ifdef TIMER_TRACE printf("running, now %lu.%09lu\n", (unsigned long)now.seconds, (unsigned long)now.nanoseconds); +#endif dispatch(manager, &now); if (manager->nscheduled > 0) { ts.tv_sec = manager->due.seconds; ts.tv_nsec = manager->due.nanoseconds; +#ifdef TIMER_TRACE printf("waituntil %lu.%09lu\n", (unsigned long)manager->due.seconds, (unsigned long)manager->due.nanoseconds); +#endif WAITUNTIL(&manager->wakeup, &manager->lock, &ts, &timeout); +#ifdef TIMER_TRACE if (!timeout) printf("wakeup\n"); +#endif } else { +#ifdef TIMER_TRACE printf("wait\n"); +#endif WAIT(&manager->wakeup, &manager->lock); +#ifdef TIMER_TRACE printf("wakeup\n"); +#endif } } UNLOCK(&manager->lock); @@ -628,7 +649,9 @@ timer_manager_destroy(timer_manager_t *managerp) { UNLOCK(&manager->lock); +#ifdef TIMER_TRACE printf("broadcast (destroy)\n"); +#endif BROADCAST(&manager->wakeup); /*