1 /******************************************************************************
2  * timer.c
3  *
4  * Copyright (c) 2002-2003 Rolf Neugebauer
5  * Copyright (c) 2002-2005 K A Fraser
6  */
7 
8 #include <xen/init.h>
9 #include <xen/types.h>
10 #include <xen/errno.h>
11 #include <xen/sched.h>
12 #include <xen/lib.h>
13 #include <xen/smp.h>
14 #include <xen/perfc.h>
15 #include <xen/time.h>
16 #include <xen/softirq.h>
17 #include <xen/timer.h>
18 #include <xen/keyhandler.h>
19 #include <xen/percpu.h>
20 #include <xen/cpu.h>
21 #include <xen/rcupdate.h>
22 #include <xen/symbols.h>
23 #include <asm/system.h>
24 #include <asm/desc.h>
25 #include <asm/atomic.h>
26 
27 /* We program the time hardware this far behind the closest deadline. */
28 static unsigned int timer_slop __read_mostly = 50000; /* 50 us */
29 integer_param("timer_slop", timer_slop);
30 
31 struct timers {
32     spinlock_t     lock;
33     struct timer **heap;
34     struct timer  *list;
35     struct timer  *running;
36     struct list_head inactive;
37 } __cacheline_aligned;
38 
39 static DEFINE_PER_CPU(struct timers, timers);
40 
41 /* Protects lock-free access to per-timer cpu field against cpu offlining. */
42 static DEFINE_RCU_READ_LOCK(timer_cpu_read_lock);
43 
44 DEFINE_PER_CPU(s_time_t, timer_deadline);
45 
46 /****************************************************************************
47  * HEAP OPERATIONS.
48  */
49 
50 #define GET_HEAP_SIZE(_h)     ((int)(((u16 *)(_h))[0]))
51 #define SET_HEAP_SIZE(_h,_v)  (((u16 *)(_h))[0] = (u16)(_v))
52 
53 #define GET_HEAP_LIMIT(_h)    ((int)(((u16 *)(_h))[1]))
54 #define SET_HEAP_LIMIT(_h,_v) (((u16 *)(_h))[1] = (u16)(_v))
55 
56 /* Sink down element @pos of @heap. */
down_heap(struct timer ** heap,int pos)57 static void down_heap(struct timer **heap, int pos)
58 {
59     int sz = GET_HEAP_SIZE(heap), nxt;
60     struct timer *t = heap[pos];
61 
62     while ( (nxt = (pos << 1)) <= sz )
63     {
64         if ( ((nxt+1) <= sz) && (heap[nxt+1]->expires < heap[nxt]->expires) )
65             nxt++;
66         if ( heap[nxt]->expires > t->expires )
67             break;
68         heap[pos] = heap[nxt];
69         heap[pos]->heap_offset = pos;
70         pos = nxt;
71     }
72 
73     heap[pos] = t;
74     t->heap_offset = pos;
75 }
76 
77 /* Float element @pos up @heap. */
up_heap(struct timer ** heap,int pos)78 static void up_heap(struct timer **heap, int pos)
79 {
80     struct timer *t = heap[pos];
81 
82     while ( (pos > 1) && (t->expires < heap[pos>>1]->expires) )
83     {
84         heap[pos] = heap[pos>>1];
85         heap[pos]->heap_offset = pos;
86         pos >>= 1;
87     }
88 
89     heap[pos] = t;
90     t->heap_offset = pos;
91 }
92 
93 
94 /* Delete @t from @heap. Return TRUE if new top of heap. */
remove_from_heap(struct timer ** heap,struct timer * t)95 static int remove_from_heap(struct timer **heap, struct timer *t)
96 {
97     int sz = GET_HEAP_SIZE(heap);
98     int pos = t->heap_offset;
99 
100     if ( unlikely(pos == sz) )
101     {
102         SET_HEAP_SIZE(heap, sz-1);
103         goto out;
104     }
105 
106     heap[pos] = heap[sz];
107     heap[pos]->heap_offset = pos;
108 
109     SET_HEAP_SIZE(heap, --sz);
110 
111     if ( (pos > 1) && (heap[pos]->expires < heap[pos>>1]->expires) )
112         up_heap(heap, pos);
113     else
114         down_heap(heap, pos);
115 
116  out:
117     return (pos == 1);
118 }
119 
120 
121 /* Add new entry @t to @heap. Return TRUE if new top of heap. */
add_to_heap(struct timer ** heap,struct timer * t)122 static int add_to_heap(struct timer **heap, struct timer *t)
123 {
124     int sz = GET_HEAP_SIZE(heap);
125 
126     /* Fail if the heap is full. */
127     if ( unlikely(sz == GET_HEAP_LIMIT(heap)) )
128         return 0;
129 
130     SET_HEAP_SIZE(heap, ++sz);
131     heap[sz] = t;
132     t->heap_offset = sz;
133     up_heap(heap, sz);
134 
135     return (t->heap_offset == 1);
136 }
137 
138 
139 /****************************************************************************
140  * LINKED LIST OPERATIONS.
141  */
142 
remove_from_list(struct timer ** pprev,struct timer * t)143 static int remove_from_list(struct timer **pprev, struct timer *t)
144 {
145     struct timer *curr, **_pprev = pprev;
146 
147     while ( (curr = *_pprev) != t )
148         _pprev = &curr->list_next;
149 
150     *_pprev = t->list_next;
151 
152     return (_pprev == pprev);
153 }
154 
add_to_list(struct timer ** pprev,struct timer * t)155 static int add_to_list(struct timer **pprev, struct timer *t)
156 {
157     struct timer *curr, **_pprev = pprev;
158 
159     while ( ((curr = *_pprev) != NULL) && (curr->expires <= t->expires) )
160         _pprev = &curr->list_next;
161 
162     t->list_next = curr;
163     *_pprev = t;
164 
165     return (_pprev == pprev);
166 }
167 
168 
169 /****************************************************************************
170  * TIMER OPERATIONS.
171  */
172 
remove_entry(struct timer * t)173 static int remove_entry(struct timer *t)
174 {
175     struct timers *timers = &per_cpu(timers, t->cpu);
176     int rc;
177 
178     switch ( t->status )
179     {
180     case TIMER_STATUS_in_heap:
181         rc = remove_from_heap(timers->heap, t);
182         break;
183     case TIMER_STATUS_in_list:
184         rc = remove_from_list(&timers->list, t);
185         break;
186     default:
187         rc = 0;
188         BUG();
189     }
190 
191     t->status = TIMER_STATUS_invalid;
192     return rc;
193 }
194 
add_entry(struct timer * t)195 static int add_entry(struct timer *t)
196 {
197     struct timers *timers = &per_cpu(timers, t->cpu);
198     int rc;
199 
200     ASSERT(t->status == TIMER_STATUS_invalid);
201 
202     /* Try to add to heap. t->heap_offset indicates whether we succeed. */
203     t->heap_offset = 0;
204     t->status = TIMER_STATUS_in_heap;
205     rc = add_to_heap(timers->heap, t);
206     if ( t->heap_offset != 0 )
207         return rc;
208 
209     /* Fall back to adding to the slower linked list. */
210     t->status = TIMER_STATUS_in_list;
211     return add_to_list(&timers->list, t);
212 }
213 
activate_timer(struct timer * timer)214 static inline void activate_timer(struct timer *timer)
215 {
216     ASSERT(timer->status == TIMER_STATUS_inactive);
217     timer->status = TIMER_STATUS_invalid;
218     list_del(&timer->inactive);
219 
220     if ( add_entry(timer) )
221         cpu_raise_softirq(timer->cpu, TIMER_SOFTIRQ);
222 }
223 
deactivate_timer(struct timer * timer)224 static inline void deactivate_timer(struct timer *timer)
225 {
226     if ( remove_entry(timer) )
227         cpu_raise_softirq(timer->cpu, TIMER_SOFTIRQ);
228 
229     timer->status = TIMER_STATUS_inactive;
230     list_add(&timer->inactive, &per_cpu(timers, timer->cpu).inactive);
231 }
232 
timer_lock(struct timer * timer)233 static inline bool_t timer_lock(struct timer *timer)
234 {
235     unsigned int cpu;
236 
237     rcu_read_lock(&timer_cpu_read_lock);
238 
239     for ( ; ; )
240     {
241         cpu = read_atomic(&timer->cpu);
242         if ( unlikely(cpu == TIMER_CPU_status_killed) )
243         {
244             rcu_read_unlock(&timer_cpu_read_lock);
245             return 0;
246         }
247         spin_lock(&per_cpu(timers, cpu).lock);
248         if ( likely(timer->cpu == cpu) )
249             break;
250         spin_unlock(&per_cpu(timers, cpu).lock);
251     }
252 
253     rcu_read_unlock(&timer_cpu_read_lock);
254     return 1;
255 }
256 
257 #define timer_lock_irqsave(t, flags) ({         \
258     bool_t __x;                                 \
259     local_irq_save(flags);                      \
260     if ( !(__x = timer_lock(t)) )               \
261         local_irq_restore(flags);               \
262     __x;                                        \
263 })
264 
timer_unlock(struct timer * timer)265 static inline void timer_unlock(struct timer *timer)
266 {
267     spin_unlock(&per_cpu(timers, timer->cpu).lock);
268 }
269 
270 #define timer_unlock_irqrestore(t, flags) ({    \
271     timer_unlock(t);                            \
272     local_irq_restore(flags);                   \
273 })
274 
275 
active_timer(struct timer * timer)276 static bool_t active_timer(struct timer *timer)
277 {
278     ASSERT(timer->status >= TIMER_STATUS_inactive);
279     ASSERT(timer->status <= TIMER_STATUS_in_list);
280     return (timer->status >= TIMER_STATUS_in_heap);
281 }
282 
283 
init_timer(struct timer * timer,void (* function)(void *),void * data,unsigned int cpu)284 void init_timer(
285     struct timer *timer,
286     void        (*function)(void *),
287     void         *data,
288     unsigned int  cpu)
289 {
290     unsigned long flags;
291     memset(timer, 0, sizeof(*timer));
292     timer->function = function;
293     timer->data = data;
294     write_atomic(&timer->cpu, cpu);
295     timer->status = TIMER_STATUS_inactive;
296     if ( !timer_lock_irqsave(timer, flags) )
297         BUG();
298     list_add(&timer->inactive, &per_cpu(timers, cpu).inactive);
299     timer_unlock_irqrestore(timer, flags);
300 }
301 
302 
set_timer(struct timer * timer,s_time_t expires)303 void set_timer(struct timer *timer, s_time_t expires)
304 {
305     unsigned long flags;
306 
307     if ( !timer_lock_irqsave(timer, flags) )
308         return;
309 
310     if ( active_timer(timer) )
311         deactivate_timer(timer);
312 
313     timer->expires = expires;
314 
315     activate_timer(timer);
316 
317     timer_unlock_irqrestore(timer, flags);
318 }
319 
320 
stop_timer(struct timer * timer)321 void stop_timer(struct timer *timer)
322 {
323     unsigned long flags;
324 
325     if ( !timer_lock_irqsave(timer, flags) )
326         return;
327 
328     if ( active_timer(timer) )
329         deactivate_timer(timer);
330 
331     timer_unlock_irqrestore(timer, flags);
332 }
333 
timer_expires_before(struct timer * timer,s_time_t t)334 bool timer_expires_before(struct timer *timer, s_time_t t)
335 {
336     unsigned long flags;
337     bool ret;
338 
339     if ( !timer_lock_irqsave(timer, flags) )
340         return false;
341 
342     ret = active_timer(timer) && timer->expires <= t;
343 
344     timer_unlock_irqrestore(timer, flags);
345 
346     return ret;
347 }
348 
migrate_timer(struct timer * timer,unsigned int new_cpu)349 void migrate_timer(struct timer *timer, unsigned int new_cpu)
350 {
351     unsigned int old_cpu;
352     bool_t active;
353     unsigned long flags;
354 
355     rcu_read_lock(&timer_cpu_read_lock);
356 
357     for ( ; ; )
358     {
359         old_cpu = read_atomic(&timer->cpu);
360         if ( (old_cpu == new_cpu) || (old_cpu == TIMER_CPU_status_killed) )
361         {
362             rcu_read_unlock(&timer_cpu_read_lock);
363             return;
364         }
365 
366         if ( old_cpu < new_cpu )
367         {
368             spin_lock_irqsave(&per_cpu(timers, old_cpu).lock, flags);
369             spin_lock(&per_cpu(timers, new_cpu).lock);
370         }
371         else
372         {
373             spin_lock_irqsave(&per_cpu(timers, new_cpu).lock, flags);
374             spin_lock(&per_cpu(timers, old_cpu).lock);
375         }
376 
377         if ( likely(timer->cpu == old_cpu) )
378              break;
379 
380         spin_unlock(&per_cpu(timers, old_cpu).lock);
381         spin_unlock_irqrestore(&per_cpu(timers, new_cpu).lock, flags);
382     }
383 
384     rcu_read_unlock(&timer_cpu_read_lock);
385 
386     active = active_timer(timer);
387     if ( active )
388         deactivate_timer(timer);
389 
390     list_del(&timer->inactive);
391     write_atomic(&timer->cpu, new_cpu);
392     list_add(&timer->inactive, &per_cpu(timers, new_cpu).inactive);
393 
394     if ( active )
395         activate_timer(timer);
396 
397     spin_unlock(&per_cpu(timers, old_cpu).lock);
398     spin_unlock_irqrestore(&per_cpu(timers, new_cpu).lock, flags);
399 }
400 
401 
kill_timer(struct timer * timer)402 void kill_timer(struct timer *timer)
403 {
404     unsigned int old_cpu, cpu;
405     unsigned long flags;
406 
407     BUG_ON(this_cpu(timers).running == timer);
408 
409     if ( !timer_lock_irqsave(timer, flags) )
410         return;
411 
412     if ( active_timer(timer) )
413         deactivate_timer(timer);
414 
415     list_del(&timer->inactive);
416     timer->status = TIMER_STATUS_killed;
417     old_cpu = timer->cpu;
418     write_atomic(&timer->cpu, TIMER_CPU_status_killed);
419 
420     spin_unlock_irqrestore(&per_cpu(timers, old_cpu).lock, flags);
421 
422     for_each_online_cpu ( cpu )
423         while ( per_cpu(timers, cpu).running == timer )
424             cpu_relax();
425 }
426 
427 
execute_timer(struct timers * ts,struct timer * t)428 static void execute_timer(struct timers *ts, struct timer *t)
429 {
430     void (*fn)(void *) = t->function;
431     void *data = t->data;
432 
433     t->status = TIMER_STATUS_inactive;
434     list_add(&t->inactive, &ts->inactive);
435 
436     ts->running = t;
437     spin_unlock_irq(&ts->lock);
438     (*fn)(data);
439     spin_lock_irq(&ts->lock);
440     ts->running = NULL;
441 }
442 
443 
timer_softirq_action(void)444 static void timer_softirq_action(void)
445 {
446     struct timer  *t, **heap, *next;
447     struct timers *ts;
448     s_time_t       now, deadline;
449 
450     ts = &this_cpu(timers);
451     heap = ts->heap;
452 
453     /* If we overflowed the heap, try to allocate a larger heap. */
454     if ( unlikely(ts->list != NULL) )
455     {
456         /* old_limit == (2^n)-1; new_limit == (2^(n+4))-1 */
457         int old_limit = GET_HEAP_LIMIT(heap);
458         int new_limit = ((old_limit + 1) << 4) - 1;
459         struct timer **newheap = xmalloc_array(struct timer *, new_limit + 1);
460         if ( newheap != NULL )
461         {
462             spin_lock_irq(&ts->lock);
463             memcpy(newheap, heap, (old_limit + 1) * sizeof(*heap));
464             SET_HEAP_LIMIT(newheap, new_limit);
465             ts->heap = newheap;
466             spin_unlock_irq(&ts->lock);
467             if ( old_limit != 0 )
468                 xfree(heap);
469             heap = newheap;
470         }
471     }
472 
473     spin_lock_irq(&ts->lock);
474 
475     now = NOW();
476 
477     /* Execute ready heap timers. */
478     while ( (GET_HEAP_SIZE(heap) != 0) &&
479             ((t = heap[1])->expires < now) )
480     {
481         remove_from_heap(heap, t);
482         execute_timer(ts, t);
483     }
484 
485     /* Execute ready list timers. */
486     while ( ((t = ts->list) != NULL) && (t->expires < now) )
487     {
488         ts->list = t->list_next;
489         execute_timer(ts, t);
490     }
491 
492     /* Try to move timers from linked list to more efficient heap. */
493     next = ts->list;
494     ts->list = NULL;
495     while ( unlikely((t = next) != NULL) )
496     {
497         next = t->list_next;
498         t->status = TIMER_STATUS_invalid;
499         add_entry(t);
500     }
501 
502     /* Find earliest deadline from head of linked list and top of heap. */
503     deadline = STIME_MAX;
504     if ( GET_HEAP_SIZE(heap) != 0 )
505         deadline = heap[1]->expires;
506     if ( (ts->list != NULL) && (ts->list->expires < deadline) )
507         deadline = ts->list->expires;
508     now = NOW();
509     this_cpu(timer_deadline) =
510         (deadline == STIME_MAX) ? 0 : MAX(deadline, now + timer_slop);
511 
512     if ( !reprogram_timer(this_cpu(timer_deadline)) )
513         raise_softirq(TIMER_SOFTIRQ);
514 
515     spin_unlock_irq(&ts->lock);
516 }
517 
align_timer(s_time_t firsttick,uint64_t period)518 s_time_t align_timer(s_time_t firsttick, uint64_t period)
519 {
520     if ( !period )
521         return firsttick;
522 
523     return firsttick + (period - 1) - ((firsttick - 1) % period);
524 }
525 
dump_timer(struct timer * t,s_time_t now)526 static void dump_timer(struct timer *t, s_time_t now)
527 {
528     printk("  ex=%12"PRId64"us timer=%p cb=%ps(%p)\n",
529            (t->expires - now) / 1000, t, t->function, t->data);
530 }
531 
dump_timerq(unsigned char key)532 static void dump_timerq(unsigned char key)
533 {
534     struct timer  *t;
535     struct timers *ts;
536     unsigned long  flags;
537     s_time_t       now = NOW();
538     int            i, j;
539 
540     printk("Dumping timer queues:\n");
541 
542     for_each_online_cpu( i )
543     {
544         ts = &per_cpu(timers, i);
545 
546         printk("CPU%02d:\n", i);
547         spin_lock_irqsave(&ts->lock, flags);
548         for ( j = 1; j <= GET_HEAP_SIZE(ts->heap); j++ )
549             dump_timer(ts->heap[j], now);
550         for ( t = ts->list, j = 0; t != NULL; t = t->list_next, j++ )
551             dump_timer(t, now);
552         spin_unlock_irqrestore(&ts->lock, flags);
553     }
554 }
555 
migrate_timers_from_cpu(unsigned int old_cpu)556 static void migrate_timers_from_cpu(unsigned int old_cpu)
557 {
558     unsigned int new_cpu = cpumask_any(&cpu_online_map);
559     struct timers *old_ts, *new_ts;
560     struct timer *t;
561     bool_t notify = 0;
562 
563     ASSERT(!cpu_online(old_cpu) && cpu_online(new_cpu));
564 
565     old_ts = &per_cpu(timers, old_cpu);
566     new_ts = &per_cpu(timers, new_cpu);
567 
568     if ( old_cpu < new_cpu )
569     {
570         spin_lock_irq(&old_ts->lock);
571         spin_lock(&new_ts->lock);
572     }
573     else
574     {
575         spin_lock_irq(&new_ts->lock);
576         spin_lock(&old_ts->lock);
577     }
578 
579     while ( (t = GET_HEAP_SIZE(old_ts->heap)
580              ? old_ts->heap[1] : old_ts->list) != NULL )
581     {
582         remove_entry(t);
583         write_atomic(&t->cpu, new_cpu);
584         notify |= add_entry(t);
585     }
586 
587     while ( !list_empty(&old_ts->inactive) )
588     {
589         t = list_entry(old_ts->inactive.next, struct timer, inactive);
590         list_del(&t->inactive);
591         write_atomic(&t->cpu, new_cpu);
592         list_add(&t->inactive, &new_ts->inactive);
593     }
594 
595     spin_unlock(&old_ts->lock);
596     spin_unlock_irq(&new_ts->lock);
597 
598     if ( notify )
599         cpu_raise_softirq(new_cpu, TIMER_SOFTIRQ);
600 }
601 
602 static struct timer *dummy_heap;
603 
cpu_callback(struct notifier_block * nfb,unsigned long action,void * hcpu)604 static int cpu_callback(
605     struct notifier_block *nfb, unsigned long action, void *hcpu)
606 {
607     unsigned int cpu = (unsigned long)hcpu;
608     struct timers *ts = &per_cpu(timers, cpu);
609 
610     switch ( action )
611     {
612     case CPU_UP_PREPARE:
613         INIT_LIST_HEAD(&ts->inactive);
614         spin_lock_init(&ts->lock);
615         ts->heap = &dummy_heap;
616         break;
617     case CPU_UP_CANCELED:
618     case CPU_DEAD:
619         migrate_timers_from_cpu(cpu);
620         break;
621     default:
622         break;
623     }
624 
625     return NOTIFY_DONE;
626 }
627 
628 static struct notifier_block cpu_nfb = {
629     .notifier_call = cpu_callback,
630     .priority = 99
631 };
632 
timer_init(void)633 void __init timer_init(void)
634 {
635     void *cpu = (void *)(long)smp_processor_id();
636 
637     open_softirq(TIMER_SOFTIRQ, timer_softirq_action);
638 
639     /*
640      * All CPUs initially share an empty dummy heap. Only those CPUs that
641      * are brought online will be dynamically allocated their own heap.
642      */
643     SET_HEAP_SIZE(&dummy_heap, 0);
644     SET_HEAP_LIMIT(&dummy_heap, 0);
645 
646     cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
647     register_cpu_notifier(&cpu_nfb);
648 
649     register_keyhandler('a', dump_timerq, "dump timer queues", 1);
650 }
651 
652 /*
653  * Local variables:
654  * mode: C
655  * c-file-style: "BSD"
656  * c-basic-offset: 4
657  * tab-width: 4
658  * indent-tabs-mode: nil
659  * End:
660  */
661