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