* Example:
* struct timers timeouts;
*
- * timers_init(&timeouts, time_now());
+ * timers_init(&timeouts, time_mono());
*/
-void timers_init(struct timers *timers, struct timespec start);
+void timers_init(struct timers *timers, struct timemono start);
/**
* timers_cleanup - free allocations within timers struct.
void timers_cleanup(struct timers *timers);
/**
- * timer_add - insert a timer.
+ * timer_init - initialize a timer.
+ * @timer: the timer to initialize
+ *
+ * Example:
+ * struct timer t;
+ *
+ * timer_init(&t);
+ */
+void timer_init(struct timer *t);
+
+/**
+ * timer_addrel - insert a relative timer.
* @timers: the struct timers
- * @timer: the (uninitialized) timer to add
- * @when: when @timer expires.
+ * @timer: the (initialized or timer_del'd) timer to add
+ * @rel: when @timer expires (relative).
+ *
+ * This efficiently adds @timer to @timers, to expire @rel (rounded to
+ * TIMER_GRANULARITY nanoseconds) after the current time. This
+ * is a convenient wrapper around timer_addmono().
+ *
+ * Example:
+ * // Timeout in 100ms.
+ * timer_addrel(&timeouts, &t, time_from_msec(100));
+ */
+void timer_addrel(struct timers *timers, struct timer *timer, struct timerel rel);
+
+/**
+ * timer_addmono - insert an absolute timer.
+ * @timers: the struct timers
+ * @timer: the (initialized or timer_del'd) timer to add
+ * @when: when @timer expires (absolute).
*
* This efficiently adds @timer to @timers, to expire @when (rounded to
* TIMER_GRANULARITY nanoseconds).
*
- * Example:
- * struct timer t;
+ * Note that if @when is before time_mono(), then it will be set to expire
+ * immediately.
*
+ * Example:
* // Timeout in 100ms.
- * timer_add(&timeouts, &t, time_add(time_now(), time_from_msec(100)));
+ * timer_addmono(&timeouts, &t, timemono_add(time_mono(), time_from_msec(100)));
*/
-void timer_add(struct timers *timers, struct timer *timer,
- struct timespec when);
+void timer_addmono(struct timers *timers, struct timer *timer,
+ struct timemono when);
/**
- * timer_del - remove an unexpired timer.
+ * timer_del - remove a timer.
* @timers: the struct timers
- * @timer: the timer previously added with timer_add()
+ * @timer: the timer
*
- * This efficiently removes @timer from @timers.
+ * This efficiently removes @timer from @timers, if timer_add() was
+ * called. It can be called multiple times without bad effect, and
+ * can be called any time after timer_init().
*
* Example:
* timer_del(&timeouts, &t);
/**
* timer_earliest - find out the first time when a timer will expire
* @timers: the struct timers
- * @first: the time, only set if there is a timer.
+ * @first: the expiry time, only set if there is a timer.
*
* This returns false, and doesn't alter @first if there are no
* timers. Otherwise, it sets @first to the expiry time of the first
* timer (rounded to TIMER_GRANULARITY nanoseconds), and returns true.
*
* Example:
- * struct timespec next = { (time_t)-1ULL, -1UL };
+ * struct timemono next = { { (time_t)-1ULL, -1UL } };
* timer_earliest(&timeouts, &next);
*/
-bool timer_earliest(struct timers *timers, struct timespec *first);
+bool timer_earliest(struct timers *timers, struct timemono *first);
/**
- * timers_expire - update timers structure and remove expired timers.
+ * timers_expire - update timers structure and remove one expire timer.
* @timers: the struct timers
* @expire: the current time
- * @list: the list for expired timers.
*
- * @list will be initialized to the empty list, then all timers added
- * with a @when arg less than or equal to @expire will be added to it in
- * expiry order (within TIMER_GRANULARITY nanosecond precision).
+ * A timers added with a @when arg less than or equal to @expire will be
+ * returned (within TIMER_GRANULARITY nanosecond precision). If
+ * there are no timers due to expire, NULL is returned.
*
- * After this, @expire is considered the current time, and adding any
- * timers with @when before this value will be silently changed to
- * adding them with immediate expiration.
+ * After this returns NULL, @expire is considered the current time,
+ * and adding any timers with @when before this value will be silently
+ * changed to adding them with immediate expiration.
*
* You should not move @expire backwards, though it need not move
* forwards.
*
* Example:
- * struct list_head expired;
+ * struct timer *expired;
*
- * timers_expire(&timeouts, time_now(), &expired);
- * if (!list_empty(&expired))
+ * while ((expired = timers_expire(&timeouts, time_mono())) != NULL)
* printf("Timer expired!\n");
+ *
*/
-void timers_expire(struct timers *timers,
- struct timespec expire,
- struct list_head *list);
+struct timer *timers_expire(struct timers *timers, struct timemono expire);
/**
* timers_check - check timer structure for consistency
struct timers {
/* Far in the future. */
struct list_head far;
+ /* Current time. */
uint64_t base;
+ /* Overall first value. */
uint64_t first;
+ /* First value in each level (plus 1 for far list) */
+ uint64_t firsts[(64 + TIMER_LEVEL_BITS-1) / TIMER_LEVEL_BITS + 1];
struct timer_level *level[(64 + TIMER_LEVEL_BITS-1) / TIMER_LEVEL_BITS];
};