parlib: Run alarm handlers outside the tchain lock
[akaros.git] / user / parlib / include / parlib / alarm.h
1 /* Copyright (c) 2013 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Userspace alarms.  There are lower level helpers to build your own alarms
6  * from the #A device and an alarm service, based off a slimmed down version of
7  * the kernel alarms.  Under the hood, the user alarm uses the #A service for
8  * the root of the alarm chain.
9  *
10  * There's only one timer chain, unlike in the kernel, for the entire process.
11  * If you want one-off timers unrelated to the chain (and sent to other vcores),
12  * use #A directly.
13  *
14  * Your handlers will run from vcore context.
15  *
16  * 1) To set a handler to run on an alarm:
17  *      struct alarm_waiter *waiter = malloc(sizeof(struct alarm_waiter));
18  *      init_awaiter(waiter, HANDLER);
19  *      waiter->data = something;
20  *      set_awaiter_rel(waiter, USEC);
21  *      set_alarm(waiter);
22  * If you want the HANDLER to run again, do this at the end of it:
23  *      set_awaiter_rel(waiter, USEC);
24  *      __set_alarm(waiter);
25  * Do not call set_alarm() from within an alarm handler; you'll deadlock.
26  * Don't forget to manage your memory at some (safe) point:
27  *      free(waiter); */
28
29 #pragma once
30
31 #include <parlib/common.h>
32 #include <sys/queue.h>
33 #include <parlib/spinlock.h>
34 #include <parlib/event.h>
35 #include <parlib/uthread.h>
36
37 __BEGIN_DECLS
38
39 /* Low-level alarm interface */
40
41 int devalarm_get_fds(int *ctlfd_r, int *timerfd_r, int *alarmid_r);
42 int devalarm_set_evq(int timerfd, struct event_queue *ev_q, int alarmid);
43 int devalarm_set_time(int timerfd, uint64_t tsc_time);
44 int devalarm_get_id(struct event_msg *ev_msg);
45 int devalarm_disable(int timerfd);
46
47 /* Alarm service */
48
49 /* Specifc waiter, per alarm */
50 struct alarm_waiter {
51         uint64_t                                        wake_up_time;   /* tsc time */
52         void (*func) (struct alarm_waiter *waiter);
53         void                                            *data;
54         TAILQ_ENTRY(alarm_waiter)       next;
55         bool                                            on_tchain;
56         bool                                            is_running;
57         bool                                            no_rearm;
58         struct uth_cond_var                     done_cv;
59 };
60 TAILQ_HEAD(awaiters_tailq, alarm_waiter);               /* ideally not a LL */
61
62 typedef void (*alarm_handler)(struct alarm_waiter *waiter);
63
64 /* Sorted collection of alarms. */
65 struct timer_chain {
66         struct spin_pdr_lock            lock;
67         struct awaiters_tailq           waiters;
68         uint64_t                                        earliest_time;
69         uint64_t                                        latest_time;
70         int                                                     ctlfd;
71         int                                                     timerfd;
72         int                                                     alarmid;
73         struct event_queue                      *ev_q;
74 };
75
76 /* For fresh alarm waiters.  func == 0 for kthreads */
77 void init_awaiter(struct alarm_waiter *waiter,
78                   void (*func) (struct alarm_waiter *));
79 /* Sets the time an awaiter goes off */
80 void set_awaiter_abs_unix(struct alarm_waiter *waiter, uint64_t abs_usec);
81 void set_awaiter_rel(struct alarm_waiter *waiter, uint64_t usleep);
82 void set_awaiter_inc(struct alarm_waiter *waiter, uint64_t usleep);
83
84 /* Helper: converts a timespec to the units of the #alarm service (usec).  A
85  * common usage:
86  *              set_awaiter_abs_unix(w, timespec_to_alarm_time(abs_ts));
87  */
88 static uint64_t timespec_to_alarm_time(const struct timespec *ts)
89 {
90         return ts->tv_nsec / 1000 + ts->tv_sec * 1000000ULL;
91 }
92
93 /* Arms/disarms the alarm */
94 void set_alarm(struct alarm_waiter *waiter);
95 bool unset_alarm(struct alarm_waiter *waiter);
96 bool reset_alarm_abs(struct alarm_waiter *waiter, uint64_t abs_time);
97
98 /* "parlib" alarm handlers */
99 void alarm_abort_sysc(struct alarm_waiter *awaiter);
100
101 /* Debugging */
102 #define ALARM_POISON_TIME 12345
103 void print_chain(struct timer_chain *tchain);
104
105 __END_DECLS