Lines Matching full:timer

26  * @brief  Kernel timer subsystem
27 * @defgroup timer Timers
29 * The timer subsystem allows functions to be scheduled for later
30 * execution. Each timer object is used to cause one function to
33 * Timer callback functions are called in interrupt context.
42 #include <kernel/timer.h>
45 #include <platform/timer.h>
61 * @brief Initialize a timer object
63 void timer_initialize(timer_t *timer) in timer_initialize() argument
65 *timer = (timer_t)TIMER_INITIAL_VALUE(*timer); in timer_initialize()
68 static void insert_timer_in_queue(uint cpu, timer_t *timer) in insert_timer_in_queue() argument
74 LTRACEF("timer %p, cpu %u, scheduled %llu, periodic %llu\n", timer, cpu, in insert_timer_in_queue()
75 timer->scheduled_time, timer->periodic_time); in insert_timer_in_queue()
78 if (time_gt(entry->scheduled_time, timer->scheduled_time)) { in insert_timer_in_queue()
79 list_add_before(&entry->node, &timer->node); in insert_timer_in_queue()
85 list_add_tail(&timers[cpu].timer_queue, &timer->node); in insert_timer_in_queue()
88 static void timer_set(timer_t *timer, lk_time_ns_t delay, lk_time_ns_t period, in timer_set() argument
93 LTRACEF("timer %p, delay %llu, period %llu, callback %p, arg %p\n", timer, in timer_set()
96 DEBUG_ASSERT(timer->magic == TIMER_MAGIC); in timer_set()
101 if (list_in_list(&timer->node)) { in timer_set()
102 panic("timer %p already in list\n", timer); in timer_set()
106 timer->scheduled_time = now + delay; in timer_set()
107 timer->periodic_time = period; in timer_set()
108 timer->callback = callback; in timer_set()
109 timer->arg = arg; in timer_set()
111 LTRACEF("scheduled time %llu\n", timer->scheduled_time); in timer_set()
116 * It is not safe to move the timer to a new cpu while the callback is in timer_set()
119 DEBUG_ASSERT(!timer->running || timer->cpu == cpu); in timer_set()
122 timer->cpu = cpu; in timer_set()
124 insert_timer_in_queue(cpu, timer); in timer_set()
127 if (list_peek_head_type(&timers[cpu].timer_queue, timer_t, node) == timer) { in timer_set()
128 /* we just modified the head of the timer queue */ in timer_set()
129 LTRACEF("setting new timer for %llu nanosecs\n", delay); in timer_set()
130 platform_set_oneshot_timer(timer_tick, timer->scheduled_time); in timer_set()
138 * @brief Set up a timer that executes once
143 * @param timer The timer to use
144 * @param delay The delay, in ns, before the timer is executed
145 * @param callback The function to call when the timer expires
148 * The timer function is declared as:
149 * enum handler_return callback(struct timer *, lk_time_t now, void *arg) { ... }
151 void timer_set_oneshot_ns(timer_t *timer, lk_time_ns_t delay, in timer_set_oneshot_ns() argument
156 timer_set(timer, delay, 0, callback, arg); in timer_set_oneshot_ns()
160 * @brief Set up a timer that executes repeatedly
165 * @param timer The timer to use
166 * @param period The delay, in ns, before the timer is executed
167 * @param callback The function to call when the timer expires
170 * The timer function is declared as:
171 * enum handler_return callback(struct timer *, lk_time_t now, void *arg) { ... }
173 void timer_set_periodic_ns(timer_t *timer, lk_time_ns_t period, in timer_set_periodic_ns() argument
178 timer_set(timer, period, period, callback, arg); in timer_set_periodic_ns()
182 * @brief Cancel a pending timer
184 void timer_cancel_etc(timer_t *timer, bool wait) in timer_cancel_etc() argument
186 DEBUG_ASSERT(timer->magic == TIMER_MAGIC); in timer_cancel_etc()
194 * be updated. We must wait before freeing the timer. in timer_cancel_etc()
202 * It is safe to cancel the timer without waiting on the same cpu that the in timer_cancel_etc()
205 DEBUG_ASSERT(wait || arch_curr_cpu_num() == timer->cpu); in timer_cancel_etc()
207 while (wait && timer->running) { in timer_cancel_etc()
220 if (list_in_list(&timer->node)) in timer_cancel_etc()
221 list_delete(&timer->node); in timer_cancel_etc()
224 * periodic timer callback. in timer_cancel_etc()
226 timer->periodic_time = 0; in timer_cancel_etc()
229 /* see if we've just modified the head of the current cpu timer queue */ in timer_cancel_etc()
232 LTRACEF("clearing old hw timer, nothing in the queue\n"); in timer_cancel_etc()
243 LTRACEF("setting new timer to %llu\n", wakeup_time); in timer_cancel_etc()
254 timer_t *timer; in timer_tick() local
271 timer = list_peek_head_type(&timers[cpu].timer_queue, timer_t, node); in timer_tick()
272 if (likely(timer == 0)) in timer_tick()
274 LTRACEF("next item on timer queue %p at %llu now %llu (%p, arg %p)\n", in timer_tick()
275 timer, timer->scheduled_time, now, timer->callback, timer->arg); in timer_tick()
276 if (likely(time_lt(now, timer->scheduled_time))) in timer_tick()
280 LTRACEF("timer %p\n", timer); in timer_tick()
281 DEBUG_ASSERT(timer && timer->magic == TIMER_MAGIC); in timer_tick()
282 list_delete(&timer->node); in timer_tick()
283 timer->running = true; in timer_tick()
288 LTRACEF("dequeued timer %p, scheduled %llu periodic %llu\n", timer, in timer_tick()
289 timer->scheduled_time, timer->periodic_time); in timer_tick()
293 bool periodic = timer->periodic_time > 0; in timer_tick()
295 LTRACEF("timer %p firing callback %p, arg %p\n", timer, timer->callback, timer->arg); in timer_tick()
296 KEVLOG_TIMER_CALL(timer->callback, timer->arg); in timer_tick()
297 if (timer->callback(timer, now, timer->arg) == INT_RESCHEDULE) in timer_tick()
304 * Check that timer did not get freed and overwritten while the callback in timer_tick()
307 DEBUG_ASSERT(timer->magic == TIMER_MAGIC); in timer_tick()
309 timer->running = false; in timer_tick()
311 /* if it was a periodic timer and it hasn't been requeued in timer_tick()
314 if (periodic && !list_in_list(&timer->node) && timer->periodic_time > 0) { in timer_tick()
315 LTRACEF("periodic timer, period %llu\n", timer->periodic_time); in timer_tick()
316 timer->scheduled_time = now + timer->periodic_time; in timer_tick()
317 insert_timer_in_queue(cpu, timer); in timer_tick()
322 /* reset the timer to the next event */ in timer_tick()
323 timer = list_peek_head_type(&timers[cpu].timer_queue, timer_t, node); in timer_tick()
324 if (timer) { in timer_tick()
326 DEBUG_ASSERT(time_gt(timer->scheduled_time, now)); in timer_tick()
328 LTRACEF("setting new timer for %llu nanosecs from now (%llu) for event %p\n", in timer_tick()
329 timer->scheduled_time - now, timer->scheduled_time, timer); in timer_tick()
330 platform_set_oneshot_timer(timer_tick, timer->scheduled_time); in timer_tick()
333 /* we're done manipulating the timer queue */ in timer_tick()
347 /* register for a periodic timer tick */ in timer_init()