Add period and count to #alarm
[akaros.git] / kern / include / alarm.h
1 /* Copyright (c) 2011 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Alarms.  This includes various ways to sleep for a while or defer work on a
6  * specific timer.  These can be per-core, global or whatever.  Deferred work
7  * is a function pointer which runs in interrupt context when the alarm goes off
8  * (picture running the ksched then).  The other style is to block/sleep on the
9  * awaiter after the alarm is set.
10  *
11  * Like with most systems, you won't wake up til after the time you specify (for
12  * now).  This might change, esp if we tweak things to coalesce alarms.
13  *
14  * All tchains come with locks.  Originally, I left these out, since the pcpu
15  * tchains didn't need them (disable_irq was sufficient).  However, disabling
16  * alarms remotely (a valid use case) is a real pain without locks, so now
17  * everyone has locks.  As an added benefit, you can submit an alarm to another
18  * core's pcpu tchain (though it probably costs an extra IRQ).  Note there is a
19  * lock ordering, tchains before awaiters (when they are grabbed together).
20  *
21  * There are two options for pcpu alarms: hard IRQ and routine KMSG (RKM).
22  * IRQ alarms are run directly in the timer interrupt handler and take a hw_tf
23  * parameter in addition to the standard alarm_waiter.  RKM alarms are executed
24  * when kernel messages are executed, which is out of IRQ context.  RKMs are
25  * safer, since you can sleep (qlock, some kmalloc, etc) and you do not need
26  * irqsave locks.
27  *
28  * Another important difference between IRQ and RKM alarms comes when cancelling
29  * or unsetting an alarm.  When you cancel (unset or reset) an alarm, the alarm
30  * is yanked off the tchain.  If the waiter was on the chain, then it will not
31  * fire for both IRQ and RKM alarms.  If the waiter was not on the chain, then
32  * for IRQ alarms, this means that the alarm has already fired.  However, for
33  * RKM alarms, the alarm may have already fired or it may still be waiting to
34  * fire (sitting in an RKM queue).  It will fire at some point, but perhaps it
35  * has not fired yet.  It is also possibly (though extremely unlikely) that if
36  * you reset an RKM alarm that the new alarm actually happens before the old one
37  * (if the new RKM was sent to another core).  
38  * 
39  * To use an IRQ alarm, init the waiter with init_awaiter_irq().
40  *
41  * Quick howto, using the pcpu tchains:
42  *      struct timer_chain *tchain = &per_cpu_info[core_id()].tchain;
43  * 1) To block your kthread on an alarm:
44  *      struct alarm_waiter a_waiter;
45  *      init_awaiter(&a_waiter, 0); // or init_awaiter_irq() for IRQ ctx alarms
46  *      set_awaiter_rel(&a_waiter, USEC);
47  *      set_alarm(tchain, &a_waiter);
48  *      sleep_on_awaiter(&a_waiter);
49  * 2) To set a handler to run on an alarm:
50  *      struct alarm_waiter *waiter = kmalloc(sizeof(struct alarm_waiter), 0);
51  *      init_awaiter(waiter, HANDLER);
52  *      set_awaiter_rel(waiter, USEC);
53  *      set_alarm(tchain, waiter);
54  * If you want the HANDLER to run again, do this at the end of it:
55  *      set_awaiter_rel(waiter, USEC);  // or whenever you want it to fire
56  *      set_alarm(tchain, waiter);
57  * or:
58  *      reset_alarm_rel(tchain, waiter, USEC);
59  *
60  * Don't forget to manage your memory at some (safe) point:
61  *      kfree(waiter);
62  * In the future, we might have a slab for these.  You can get it from wherever
63  * you want, just don't use the stack for handler style, since you'll usually
64  * return and pop up the stack after setting the alarm.
65  * */
66
67 #pragma once
68
69 #include <ros/common.h>
70 #include <sys/queue.h>
71 #include <kthread.h>
72
73 /* These structures allow code to block or defer work for a certain amount of
74  * time.  Timer chains (like off a per-core timer) are made of lists/trees of
75  * these. 
76  *
77  * If you have a func pointer, that handler will run when the alarm goes off.
78  * If you don't have a func pointer, you sleep on the semaphore and block your
79  * kthread.  In the latter case, you ought to allocate space for them on the
80  * stack of the thread you're about to block on. */
81 struct alarm_waiter {
82         uint64_t                                        wake_up_time;   /* ugh, this is a TSC for now */
83         union {
84                 void (*func) (struct alarm_waiter *waiter);
85                 void (*func_irq) (struct alarm_waiter *waiter,
86                                   struct hw_trapframe *hw_tf);
87                 struct semaphore                        sem;            /* kthread will sleep on this */
88         };
89         void                                            *data;
90         TAILQ_ENTRY(alarm_waiter)       next;
91         bool                                            on_tchain;
92         bool                                            irq_ok;
93         bool                                            holds_tchain_lock;
94         bool                                            has_func;
95 };
96 TAILQ_HEAD(awaiters_tailq, alarm_waiter);               /* ideally not a LL */
97
98 typedef void (*alarm_handler)(struct alarm_waiter *waiter);
99
100 /* One of these per alarm source, such as a per-core timer.  All tchains come
101  * with a lock, even if its rarely needed (like the pcpu tchains).
102  * set_interrupt() is a method for setting the interrupt source. */
103 struct timer_chain {
104         spinlock_t                                      lock;
105         struct awaiters_tailq           waiters;
106         uint64_t                                        earliest_time;
107         uint64_t                                        latest_time;
108         void (*set_interrupt)(struct timer_chain *);
109 };
110
111 /* Called once per timer chain, currently in per_cpu_init() */
112 void init_timer_chain(struct timer_chain *tchain,
113                       void (*set_interrupt)(struct timer_chain *));
114 /* For fresh alarm waiters.  func == 0 for kthreads */
115 void init_awaiter(struct alarm_waiter *waiter,
116                   void (*func) (struct alarm_waiter *));
117 void init_awaiter_irq(struct alarm_waiter *waiter,
118                       void (*func_irq) (struct alarm_waiter *awaiter,
119                                         struct hw_trapframe *hw_tf));
120 /* Sets the time an awaiter goes off */
121 void set_awaiter_abs(struct alarm_waiter *waiter, uint64_t abs_time);
122 void set_awaiter_rel(struct alarm_waiter *waiter, uint64_t usleep);
123 void set_awaiter_inc(struct alarm_waiter *waiter, uint64_t usleep);
124 /* Arms/disarms the alarm. */
125 void set_alarm(struct timer_chain *tchain, struct alarm_waiter *waiter);
126 bool unset_alarm(struct timer_chain *tchain, struct alarm_waiter *waiter);
127 bool reset_alarm_abs(struct timer_chain *tchain, struct alarm_waiter *waiter,
128                      uint64_t abs_time);
129 bool reset_alarm_rel(struct timer_chain *tchain, struct alarm_waiter *waiter,
130                      uint64_t usleep);
131
132 /* Blocks on the alarm waiter */
133 int sleep_on_awaiter(struct alarm_waiter *waiter);
134 /* Interrupt handlers need to call this.  Don't call it directly. */
135 void __trigger_tchain(struct timer_chain *tchain, struct hw_trapframe *hw_tf);
136 /* Sets the timer chain interrupt according to the next timer in the chain. */
137 void set_pcpu_alarm_interrupt(struct timer_chain *tchain);
138
139 /* Debugging */
140 #define ALARM_POISON_TIME 12345                         /* could use some work */
141 void print_chain(struct timer_chain *tchain);
142 void print_pcpu_chains(void);