Adds devalarm (#A)
[akaros.git] / kern / drivers / dev / alarm.c
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  * devalarm/#A: a device for registering per-process alarms.
6  *
7  * Allows a process to set up alarms, where the kernel will send an event to a
8  * posted ev_q at a certain TSC time.
9  *
10  * Every process has their own alarm sets and view of #A; gen and friends look
11  * at current's alarmset when it is time to gen or open a file.
12  *
13  * To use, first open #A/clone, and that gives you an alarm directory aN, where
14  * N is ID of the alarm.  ctl takes two commands: "evq POINTER" (to tell the
15  * kernel the pointer of your ev_q) and "cancel", to stop an alarm.  timer takes
16  * just the value (in absolute tsc time) to fire the alarm.
17  *
18  * While each process has a separate view of #A, it is possible to post a chan
19  * to Qctl or Qtimer to #s.  If another proc has your Qtimer, it can set it in
20  * the past, thereby triggering an immediate event.  More clever than useful.
21  *
22  * Notes on refcnting (the trickier parts here):
23  * - the proc_alarms have counted references to their proc
24  *              proc won't free til all alarms are closed, which is fine.  we close
25  *              all files in destroy.  if a proc drops a chan in srv, the proc will stay
26  *              alive because the alarm is alive - til that chan is closed (srvremove)
27  *
28  *              other shady ways to keep a chan alive: cd to it!  if it is ., we'd
29  *              keep a ref around.  however, only alarmdir *file* grab refs, not
30  *              directories.
31  *
32  * - proc_alarms are kref'd, since there can be multiple chans per alarm
33  *              the only thing that keeps an alarm alive is a chan on a CTL or TIMER (or
34  *              other file).  when you cloned, you got back an open CTL, which keeps the
35  *              alarm (and the dir) alive.
36  *
37  *              we need to be careful generating krefs, in case alarms are concurrently
38  *              released and removed from the lists.  just like with procs and pid2proc,
39  *              we need to sync with the source of the kref. */
40
41 #include <kmalloc.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <assert.h>
45 #include <error.h>
46 #include <pmap.h>
47 #include <sys/queue.h>
48 #include <smp.h>
49 #include <kref.h>
50 #include <atomic.h>
51 #include <alarm.h>
52 #include <event.h>
53 #include <umem.h>
54 #include <devalarm.h>
55
56 /* qid path types */
57 #define Qtopdir                                 1
58 #define Qclone                                  2
59 #define Qalarmdir                               3
60 #define Qctl                                    4
61 #define Qtimer                                  5       /* Qctl + 1 */
62
63 /* This paddr/kaddr is a bit dangerous.  it'll work so long as we don't need all
64  * 64 bits for a physical address (48 is the current norm on x86_64). */
65 #define ADDR_SHIFT 5
66 #define QID2A(q) ((struct proc_alarm*)KADDR(((q).path >> ADDR_SHIFT)))
67 #define TYPE(q) ((q).path & ((1 << ADDR_SHIFT) - 1))
68 #define QID(ptr, type) ((PADDR(ptr) << ADDR_SHIFT) | type)
69
70 static void alarm_release(struct kref *kref)
71 {
72         struct proc_alarm *a = container_of(kref, struct proc_alarm, kref);
73         struct proc *p = a->proc;
74         assert(p);
75         spin_lock(&p->alarmset.lock);
76         TAILQ_REMOVE(&p->alarmset.list, a, link);
77         spin_unlock(&p->alarmset.lock);
78         /* When this returns, the alarm has either fired or it never will */
79         unset_alarm(p->alarmset.tchain, &a->a_waiter);
80         proc_decref(p);
81         kfree(a);
82 }
83
84 static void proc_alarm_handler(struct alarm_waiter *a_waiter)
85 {
86         struct proc_alarm *a = container_of(a_waiter, struct proc_alarm, a_waiter);
87         struct event_queue *ev_q = ACCESS_ONCE(a->ev_q);
88         struct event_msg msg;
89         if (!ev_q || !a->proc) {
90                 printk("[kernel] proc_alarm, bad ev_q %p or proc %p\n", ev_q, a->proc);
91                 return;
92         }
93         memset(&msg, 0, sizeof(struct event_msg));
94         msg.ev_type = EV_ALARM;
95         send_event(a->proc, ev_q, &msg, 0);
96 }
97
98 void devalarm_init(struct proc *p)
99 {
100         TAILQ_INIT(&p->alarmset.list);
101         spinlock_init(&p->alarmset.lock);
102         /* Just running all the proc alarms on core 0. */
103         p->alarmset.tchain = &per_cpu_info[0].tchain;
104         p->alarmset.id_counter = 0;
105 }
106
107 static int alarmgen(struct chan *c, char *entry_name,
108                     struct dirtab *unused, int unused_nr_dirtab,
109                     int s, struct dir *dp)
110 {
111         struct qid q;
112         struct proc_alarm *a_i;
113         struct proc *p = current;
114         /* Whether we're in one dir or at the top, .. still takes us to the top. */
115         if (s == DEVDOTDOT) {
116                 mkqid(&q, Qtopdir, 0, QTDIR);
117                 devdir(c, c->qid, "#A", 0, eve, 0555, dp);
118                 return 1;
119         }
120         switch (TYPE(c->qid)) {
121                 case Qtopdir:
122                         /* Generate elements for the top level dir.  We support a clone and
123                          * alarm dirs at the top level */
124                         if (s == 0) {
125                                 mkqid(&q, Qclone, 0, QTFILE);
126                                 devdir(c, q, "clone", 0, eve, 0666, dp);
127                                 return 1;
128                         }
129                         s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
130                         /* Gets the s-th element (0 index)
131                          * 
132                          * I would like to take advantage of the state machine and our
133                          * previous answer to get the sth element of the list.  We can get
134                          * at our previous run of gen from dp (struct dir), and use that to
135                          * get the next item.  I'd like to do something like:
136                          *
137                          * if (dp->qid.path >> ADDR_SHIFT)
138                          *              a_i = TAILQ_NEXT(QID2A(dp->qid), link);
139                          *
140                          * Dev would give us a 0'd dp path on the first run, so if we have a
141                          * path, we know we're on an iterative run.  However, the problem is
142                          * that we could have lost the element dp refers to (QID2A(dp->qid))
143                          * since our previous run, so we can't even access that memory to
144                          * check for refcnts or anything.  We need a new model for how gen
145                          * works (probably a gen_start and gen_stop devop, passed as
146                          * parameters to devwalk), so that we can have some invariants
147                          * between gen runs.
148                          *
149                          * Til then, we're stuck with arrays like in #I (though we can use
150                          * Linux style fdsets) or lousy O(n^2) linked lists (like #s).
151                          *
152                          * Note that we won't always start a gen loop with s == 0
153                          * (devdirread, for instance) */
154                         spin_lock(&p->alarmset.lock);
155                         TAILQ_FOREACH(a_i, &p->alarmset.list, link) {
156                                 if (s-- == 0)
157                                         break;
158                         }
159                         /* As soon as we unlock, someone could free a_i */
160                         if (!a_i) {
161                                 spin_unlock(&p->alarmset.lock);
162                                 return -1;
163                         }
164                         snprintf(get_cur_genbuf(), GENBUF_SZ, "a%d", a_i->id);
165                         mkqid(&q, QID(a_i, Qalarmdir), 0, QTDIR);
166                         devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
167                         spin_unlock(&p->alarmset.lock);
168                         return 1;
169                 case Qalarmdir:
170                         /* Gen the contents of the alarm dirs */
171                         s += Qctl;      /* first time through, start on Qctl */
172                         switch (s) {
173                                 case Qctl:
174                                         mkqid(&q, QID(QID2A(c->qid), Qctl), 0, QTFILE);
175                                         devdir(c, q, "ctl", 0, eve, 0666, dp);
176                                         return 1;
177                                 case Qtimer:
178                                         mkqid(&q, QID(QID2A(c->qid), Qtimer), 0, QTFILE);
179                                         devdir(c, q, "timer", 0, eve, 0666, dp);
180                                         return 1;
181                         }
182                         return -1;
183                 /* Need to also provide a direct hit for Qclone and all other files (at
184                  * all levels of the hierarchy).  Every file is both
185                  * generated (via the s increments in their respective directories) and
186                  * directly gen-able.  devstat() will call gen with a specific path in
187                  * the qid.  In these cases, we make a dir for whatever they are asking
188                  * for.  Note the qid stays the same.  I think this is what the old
189                  * plan9 comments above devgen were talking about for (ii).
190                  *
191                  * We don't need to do this for the directories - devstat will look for
192                  * the a directory by path and fail.  Then it will manually build the
193                  * stat output (check the -1 case in devstat). */
194                 case Qclone:
195                         devdir(c, c->qid, "clone", 0, eve, 0666, dp);
196                         return 1;
197                 case Qctl:
198                         devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
199                         return 1;
200                 case Qtimer:
201                         devdir(c, c->qid, "timer", 0, eve, 0666, dp);
202                         return 1;
203         }
204         return -1;
205 }
206
207 static void alarminit(void)
208 {
209 }
210
211 static struct chan *alarmattach(char *spec)
212 {
213         struct chan *c = devattach('A', spec);
214         mkqid(&c->qid, Qtopdir, 0, QTDIR);
215         return c;
216 }
217
218 static struct walkqid *alarmwalk(struct chan *c, struct chan *nc, char **name,
219                                  int nname)
220 {
221         return devwalk(c, nc, name, nname, 0, 0, alarmgen);
222 }
223
224 static long alarmstat(struct chan *c, uint8_t *db, long n)
225 {
226         return devstat(c, db, n, 0, 0, alarmgen);
227 }
228
229 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
230  * the open chan into p's fd table, then decref the chan. */
231 static struct chan *alarmopen(struct chan *c, int omode)
232 {
233         struct proc *p = current;
234         struct proc_alarm *a, *a_i;
235         switch (TYPE(c->qid)) {
236                 case Qtopdir:
237                 case Qalarmdir:
238                         if (omode & ORCLOSE)
239                                 error(Eperm);
240                         if (omode != OREAD)
241                                 error(Eisdir);
242                         break;
243                 case Qclone:
244                         a = kzmalloc(sizeof(struct proc_alarm), KMALLOC_WAIT);
245                         kref_init(&a->kref, alarm_release, 1);
246                         init_awaiter(&a->a_waiter, proc_alarm_handler);
247                         spin_lock(&p->alarmset.lock);
248                         a->id = p->alarmset.id_counter++;
249                         proc_incref(p, 1);
250                         a->proc = p;
251                         TAILQ_INSERT_TAIL(&p->alarmset.list, a, link);
252                         spin_unlock(&p->alarmset.lock);
253                         mkqid(&c->qid, QID(a, Qctl), 0, QTFILE);
254                         break;
255                 case Qctl:
256                 case Qtimer:
257                         /* the purpose of opening is to hold a kref on the proc_alarm */
258                         a = QID2A(c->qid);
259                         assert(a);
260                         assert(a->proc == current);
261                         /* this isn't a valid pointer yet, since our chan doesn't have a
262                          * ref.  since the time that walk gave our chan the qid, the chan
263                          * could have been closed, and the alarm decref'd and freed.  the
264                          * qid is essentially an uncounted reference, and we need to go to
265                          * the source to attempt to get a real ref.  Unfortunately, this is
266                          * another scan of the list, same as devsrv.  We could speed it up
267                          * by storing an "on_list" bool in the a_is. */
268                         spin_lock(&p->alarmset.lock);
269                         TAILQ_FOREACH(a_i, &p->alarmset.list, link) {
270                                 if (a_i == a) {
271                                         /* it's still possible we're not getting the ref, racing
272                                          * with the release method */
273                                         if (!kref_get_not_zero(&a->kref, 1)) {
274                                                 a_i = 0;        /* lost the race, will error out later */
275                                         }
276                                         break;
277                                 }
278                         }
279                         spin_unlock(&p->alarmset.lock);
280                         if (!a_i)
281                                 error("Unable to open alarm, concurrent closing");
282                         break;
283         }
284         c->mode = openmode(omode);
285         /* Assumes c is unique (can't be closed concurrently */
286         c->flag |= COPEN;
287         c->offset = 0;
288         return c;
289 }
290
291 static void alarmcreate(struct chan *c, char *name, int omode, int perm)
292 {
293         error(Eperm);
294 }
295
296 static void alarmremove(struct chan *c)
297 {
298         error(Eperm);
299 }
300
301 static long alarmwstat(struct chan *c, uint8_t *dp, long n)
302 {
303         error("No alarmwstat");
304         return 0;
305 }
306
307 static void alarmclose(struct chan *c)
308 {
309         /* There are more closes than opens.  For instance, sysstat doesn't open,
310          * but it will close the chan it got from namec.  We only want to clean
311          * up/decref chans that were actually open. */
312         if (!(c->flag & COPEN))
313                 return;
314         switch (TYPE(c->qid)) {
315                 case Qctl:
316                 case Qtimer:
317                         kref_put(&QID2A(c->qid)->kref);
318                         break;
319         }
320 }
321
322 static long alarmread(struct chan *c, void *ubuf, long n, int64_t offset)
323 {
324         struct proc_alarm *p_alarm;
325         switch (TYPE(c->qid)) {
326                 case Qtopdir:
327                 case Qalarmdir:
328                         return devdirread(c, ubuf, n, 0, 0, alarmgen);
329                 case Qctl:
330                         p_alarm = QID2A(c->qid);
331                         return readnum(offset, ubuf, n, p_alarm->id, NUMSIZE32);
332                 case Qtimer:
333                         p_alarm = QID2A(c->qid);
334                         return readnum(offset, ubuf, n, p_alarm->a_waiter.wake_up_time,
335                                        NUMSIZE64);
336                 default:
337                         panic("Bad QID %p in devalarm", c->qid.path);
338         }
339         return 0;
340 }
341
342 /* Note that in read and write we have an open chan, which means we have an
343  * active kref on the p_alarm.  Also note that we make no assumptions about
344  * current here - we find the proc (and the tchain) via the ref stored in the
345  * proc_alarm. */
346 static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
347 {
348         ERRSTACK(1);
349         char buf[32];
350         struct cmdbuf *cb;
351         struct proc_alarm *p_alarm;
352         uint64_t hexval;
353
354         switch (TYPE(c->qid)) {
355                 case Qtopdir:
356                 case Qalarmdir:
357                         error(Eperm);
358                 case Qctl:
359                         p_alarm = QID2A(c->qid);
360                         cb = parsecmd(ubuf, n);
361                         if (waserror()) {
362                                 kfree(cb);
363                                 nexterror();
364                         }
365                         if (!strcmp(cb->f[0], "evq")) {
366                                 if (cb->nf < 2)
367                                         error("evq needs a pointer");
368                                 /* i think it's safe to do a stroul on a parsecmd.  it's kernel
369                                  * memory, and space or 0 terminated */
370                                 hexval = strtoul(cb->f[1], 0, 16);
371                                 /* This is just to help userspace - event code can handle it */
372                                 if (!is_user_rwaddr((void*)hexval, sizeof(struct event_queue)))
373                                         error("Non-user ev_q pointer");
374                                 p_alarm->ev_q = (struct event_queue*)hexval;
375                         } else if (!strcmp(cb->f[0], "cancel")) {
376                                 unset_alarm(p_alarm->proc->alarmset.tchain, &p_alarm->a_waiter);
377                         } else {
378                                 error("%s: not implemented", cb->f[0]);
379                         }
380                         kfree(cb);
381                         poperror();
382                         break;
383                 case Qtimer:
384                         /* want to give strtoul a null-terminated buf (can't handle random
385                          * user strings) */
386                         if (n >= sizeof(buf))
387                                 error(Egreg);
388                         memcpy(buf, ubuf, n);
389                         buf[n] = 0;
390                         hexval = strtoul(buf, 0, 16);
391                         p_alarm = QID2A(c->qid);
392                         /* if you don't know if it was running or not, resetting will turn
393                          * it on regardless. */
394                         reset_alarm_abs(p_alarm->proc->alarmset.tchain, &p_alarm->a_waiter,
395                                         hexval);
396                         break;
397                 default:
398                         panic("Bad QID %p in devalarm", c->qid.path);
399         }
400         return n;
401 }
402
403 struct dev alarmdevtab = {
404         'A',
405         "alarm",
406
407         devreset,
408         alarminit,
409         devshutdown,
410         alarmattach,
411         alarmwalk,
412         alarmstat,
413         alarmopen,
414         alarmcreate,
415         alarmclose,
416         alarmread,
417         devbread,
418         alarmwrite,
419         devbwrite,
420         alarmremove,
421         alarmwstat,
422         devpower,
423         devconfig,
424         devchaninfo,
425 };