1 #include <lwk/kernel.h>
2 #include <lwk/spinlock.h>
3 #include <lwk/percpu.h>
10 struct list_head timer_list;
13 static DEFINE_PER_CPU(struct timer_queue, timer_queue);
16 timer_subsys_init(void)
19 struct timer_queue *timerq;
21 for_each_cpu_mask(cpu, cpu_present_map) {
22 timerq = &per_cpu(timer_queue, cpu);
23 spin_lock_init(&timerq->lock);
24 list_head_init(&timerq->timer_list);
31 timer_add(struct timer *timer)
33 struct timer_queue *timerq;
34 struct list_head *pos;
35 unsigned long irqstate;
37 timerq = &per_cpu(timer_queue, this_cpu);
38 spin_lock_irqsave(&timerq->lock, irqstate);
40 /* Initialize fields we don't expect the caller to set */
41 list_head_init(&timer->link);
42 timer->cpu = this_cpu;
44 /* Insert the new timer into the CPU's sorted timer_list */
45 list_for_each(pos, &timerq->timer_list) {
46 struct timer *cur = list_entry(pos, struct timer, link);
47 if (cur->expires > timer->expires)
50 list_add_tail(&timer->link, pos);
52 spin_unlock_irqrestore(&timerq->lock, irqstate);
56 timer_del(struct timer *timer)
58 struct timer_queue *timerq;
59 unsigned long irqstate;
61 timerq = &per_cpu(timer_queue, timer->cpu);
62 spin_lock_irqsave(&timerq->lock, irqstate);
64 /* Remove the timer, if it hasn't already expired */
65 if (!list_empty(&timer->link))
66 list_del(&timer->link);
68 spin_unlock_irqrestore(&timerq->lock, irqstate);
72 wakeup_task(uintptr_t task)
74 sched_wakeup_task((struct task_struct *)task, TASKSTATE_INTERRUPTIBLE);
77 /* Returns the time remaining */
79 timer_sleep_until(uint64_t when)
85 timer.function = &wakeup_task;
86 timer.data = (uintptr_t)current;
90 set_mb(current->state, TASKSTATE_INTERRUPTIBLE);
93 /* Return the time remaining */
95 return (when > now) ? (when - now) : 0;
101 struct timer_queue *timerq = &per_cpu(timer_queue, this_cpu);
103 uint64_t now = get_time();
104 unsigned long irqstate;
107 /* Pop the head entry off of the timer list */
108 spin_lock_irqsave(&timerq->lock, irqstate);
109 if (!list_empty(&timerq->timer_list)) {
110 timer = list_entry(timerq->timer_list.next,
113 if (timer->expires <= now) {
114 list_del_init(&timer->link);
121 spin_unlock_irqrestore(&timerq->lock, irqstate);
123 /* Execute the timer's callback function.
124 * Note that we have released the timerq->lock, so the
125 * callback function is free to call timer_add(). */
127 (*timer->function)(timer->data);