Add AKAROS_TOOLCHAINS (XCC)
[akaros.git] / kern / include / alarm.h
1 /* Copyright (c) 2011 The Regents of the University of California
2  * Copyright (c) 2018 Google Inc.
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  *
6  * Alarms.  This includes various ways to sleep for a while or defer work on a
7  * specific timer.  These can be per-core, global or whatever.  Deferred work
8  * is a function pointer which runs in interrupt context when the alarm goes off
9  * (picture running the ksched then).
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, you may
30  * need to block until the RKM has run.  IRQ alarms run with the tchain lock
31  * held, so once the canceller grabs the lock, it has either run already or will
32  * not at all.  With RKMs, the handler runs outside of the lock.  Thus you may
33  * have to wait until the RKM has run, and the RKM might be waiting to run on
34  * your core.
35  *
36  * Note that RKM unset_alarm() has a waits-on dependency with the actual alarm
37  * handler, so be careful of deadlock.
38  *
39  * Quick howto, using the pcpu tchains:
40  *      struct timer_chain *tchain = &per_cpu_info[core_id()].tchain;
41  * To block your kthread on an alarm:
42  *      struct alarm_waiter *waiter = kmalloc(sizeof(struct alarm_waiter), 0);
43  *
44  *      init_awaiter(waiter, HANDLER);
45  *      set_awaiter_rel(waiter, USEC);
46  *      set_alarm(tchain, waiter);
47  *
48  * If you want the HANDLER to run again, do this at the end of it:
49  *      set_awaiter_rel(waiter, USEC);  // or whenever you want it to fire
50  *      set_alarm(tchain, waiter);
51  * or:
52  *      reset_alarm_rel(tchain, waiter, USEC);
53  *
54  * Don't forget to manage your memory at some (safe) point:
55  *      kfree(waiter);
56  * In the future, we might have a slab for these.  You can get it from wherever
57  * you want, just be careful if you use the stack. */
58
59 #pragma once
60
61 #include <ros/common.h>
62 #include <sys/queue.h>
63 #include <kthread.h>
64
65 /* These structures allow code to defer work for a certain amount of time.
66  * Timer chains (like off a per-core timer) are made of lists/trees of these. */
67 struct alarm_waiter {
68         uint64_t                        wake_up_time;
69         void (*func) (struct alarm_waiter *waiter);
70         void                            *data;
71         TAILQ_ENTRY(alarm_waiter)       next;
72         bool                            on_tchain;
73 };
74 TAILQ_HEAD(awaiters_tailq, alarm_waiter);               /* ideally not a LL */
75
76 typedef void (*alarm_handler)(struct alarm_waiter *waiter);
77
78 /* One of these per alarm source, such as a per-core timer.  All tchains come
79  * with a lock, even if its rarely needed (like the pcpu tchains).
80  * set_interrupt() is a method for setting the interrupt source. */
81 struct timer_chain {
82         spinlock_t                      lock;
83         struct awaiters_tailq           waiters;
84         struct alarm_waiter             *running;
85         uint64_t                        earliest_time;
86         uint64_t                        latest_time;
87         struct cond_var                 cv;
88         void (*set_interrupt)(struct timer_chain *);
89 };
90
91 /* Called once per timer chain, currently in per_cpu_init() */
92 void init_timer_chain(struct timer_chain *tchain,
93                       void (*set_interrupt)(struct timer_chain *));
94 /* For fresh alarm waiters.  func == 0 for kthreads */
95 void init_awaiter(struct alarm_waiter *waiter,
96                   void (*func) (struct alarm_waiter *));
97 /* Sets the time an awaiter goes off */
98 void set_awaiter_abs(struct alarm_waiter *waiter, uint64_t abs_time);
99 void set_awaiter_rel(struct alarm_waiter *waiter, uint64_t usleep);
100 void set_awaiter_inc(struct alarm_waiter *waiter, uint64_t usleep);
101 /* Arms/disarms the alarm.  Can be called from within a handler.*/
102 void set_alarm(struct timer_chain *tchain, struct alarm_waiter *waiter);
103 /* Unset and reset may block if the alarm is not IRQ.  Do not call from within a
104  * handler.  Returns TRUE if you stopped the alarm from firing. */
105 bool unset_alarm(struct timer_chain *tchain, struct alarm_waiter *waiter);
106 /* Convenience wrappers for unset, then set.  Slower, but easier than just
107  * setting, since you don't need to know if it fired.  Returns TRUE if the alarm
108  * did not fire before your reset. */
109 bool reset_alarm_abs(struct timer_chain *tchain, struct alarm_waiter *waiter,
110                      uint64_t abs_time);
111 bool reset_alarm_rel(struct timer_chain *tchain, struct alarm_waiter *waiter,
112                      uint64_t usleep);
113
114 /* Interrupt handlers need to call this.  Don't call it directly. */
115 void __trigger_tchain(struct timer_chain *tchain, struct hw_trapframe *hw_tf);
116 /* Sets the timer chain interrupt according to the next timer in the chain. */
117 void set_pcpu_alarm_interrupt(struct timer_chain *tchain);
118
119 static inline bool alarm_expired(struct alarm_waiter *awaiter)
120 {
121         return awaiter->wake_up_time <= read_tsc();
122 }
123
124 /* Debugging */
125 #define ALARM_POISON_TIME 12345         /* could use some work */
126 void print_chain(struct timer_chain *tchain);
127 void print_pcpu_chains(void);