d131d8f6e6a8f235495dbe3fc35de79d63e7dd15
[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, q, "#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
186                          * (at all levels of the hierarchy).  Every file is both generated
187                          * (via the s increments in their respective directories) and
188                          * directly gen-able.  devstat() will call gen with a specific path
189                          * in the qid.  In these cases, we make a dir for whatever they are
190                          * asking for.  Note the qid stays the same.  I think this is what
191                          * the old plan9 comments above devgen were talking about for (ii).
192                          *
193                          * We don't need to do this for the directories - devstat will look
194                          * for the a directory by path and fail.  Then it will manually
195                          * build the 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 (!IS_RDONLY(omode))
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                         /* this isn't a valid pointer yet, since our chan doesn't have a
263                          * ref.  since the time that walk gave our chan the qid, the chan
264                          * could have been closed, and the alarm decref'd and freed.  the
265                          * qid is essentially an uncounted reference, and we need to go to
266                          * the source to attempt to get a real ref.  Unfortunately, this is
267                          * another scan of the list, same as devsrv. */
268                         spin_lock(&p->alarmset.lock);
269                         TAILQ_FOREACH(a_i, &p->alarmset.list, link) {
270                                 if (a_i == a) {
271                                         assert(a->proc == current);
272                                         /* it's still possible we're not getting the ref, racing
273                                          * with the release method */
274                                         if (!kref_get_not_zero(&a->kref, 1)) {
275                                                 a_i = 0;        /* lost the race, will error out later */
276                                         }
277                                         break;
278                                 }
279                         }
280                         spin_unlock(&p->alarmset.lock);
281                         if (!a_i)
282                                 error("Unable to open alarm, concurrent closing");
283                         break;
284         }
285         c->mode = openmode(omode);
286         /* Assumes c is unique (can't be closed concurrently */
287         c->flag |= COPEN;
288         c->offset = 0;
289         return c;
290 }
291
292 static void alarmcreate(struct chan *c, char *name, int omode, uint32_t perm)
293 {
294         error(Eperm);
295 }
296
297 static void alarmremove(struct chan *c)
298 {
299         error(Eperm);
300 }
301
302 static int alarmwstat(struct chan *c, uint8_t * dp, int n)
303 {
304         error("No alarmwstat");
305         return 0;
306 }
307
308 static void alarmclose(struct chan *c)
309 {
310         /* There are more closes than opens.  For instance, sysstat doesn't open,
311          * but it will close the chan it got from namec.  We only want to clean
312          * up/decref chans that were actually open. */
313         if (!(c->flag & COPEN))
314                 return;
315         switch (TYPE(c->qid)) {
316                 case Qctl:
317                 case Qtimer:
318                         kref_put(&QID2A(c->qid)->kref);
319                         break;
320         }
321 }
322
323 static long alarmread(struct chan *c, void *ubuf, long n, int64_t offset)
324 {
325         struct proc_alarm *p_alarm;
326         switch (TYPE(c->qid)) {
327                 case Qtopdir:
328                 case Qalarmdir:
329                         return devdirread(c, ubuf, n, 0, 0, alarmgen);
330                 case Qctl:
331                         p_alarm = QID2A(c->qid);
332                         return readnum(offset, ubuf, n, p_alarm->id, NUMSIZE32);
333                 case Qtimer:
334                         p_alarm = QID2A(c->qid);
335                         return readnum(offset, ubuf, n, p_alarm->a_waiter.wake_up_time,
336                                                    NUMSIZE64);
337                 default:
338                         panic("Bad QID %p in devalarm", c->qid.path);
339         }
340         return 0;
341 }
342
343 /* Note that in read and write we have an open chan, which means we have an
344  * active kref on the p_alarm.  Also note that we make no assumptions about
345  * current here - we find the proc (and the tchain) via the ref stored in the
346  * proc_alarm. */
347 static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
348 {
349         ERRSTACK(1);
350         char buf[32];
351         struct cmdbuf *cb;
352         struct proc_alarm *p_alarm;
353         uint64_t hexval;
354
355         switch (TYPE(c->qid)) {
356                 case Qtopdir:
357                 case Qalarmdir:
358                         error(Eperm);
359                 case Qctl:
360                         p_alarm = QID2A(c->qid);
361                         cb = parsecmd(ubuf, n);
362                         if (waserror()) {
363                                 kfree(cb);
364                                 nexterror();
365                         }
366                         if (!strcmp(cb->f[0], "evq")) {
367                                 if (cb->nf < 2)
368                                         error("evq needs a pointer");
369                                 /* i think it's safe to do a stroul on a parsecmd.  it's kernel
370                                  * memory, and space or 0 terminated */
371                                 hexval = strtoul(cb->f[1], 0, 16);
372                                 /* This is just to help userspace - event code can handle it */
373                                 if (!is_user_rwaddr((void *)hexval, sizeof(struct event_queue)))
374                                         error("Non-user ev_q pointer");
375                                 p_alarm->ev_q = (struct event_queue *)hexval;
376                         } else if (!strcmp(cb->f[0], "cancel")) {
377                                 unset_alarm(p_alarm->proc->alarmset.tchain, &p_alarm->a_waiter);
378                         } else {
379                                 error("%s: not implemented", cb->f[0]);
380                         }
381                         kfree(cb);
382                         poperror();
383                         break;
384                 case Qtimer:
385                         /* want to give strtoul a null-terminated buf (can't handle random
386                          * user strings) */
387                         if (n >= sizeof(buf))
388                                 error(Egreg);
389                         memcpy(buf, ubuf, n);
390                         buf[n] = 0;
391                         hexval = strtoul(buf, 0, 16);
392                         p_alarm = QID2A(c->qid);
393                         /* if you don't know if it was running or not, resetting will turn
394                          * it on regardless. */
395                         reset_alarm_abs(p_alarm->proc->alarmset.tchain, &p_alarm->a_waiter,
396                                                         hexval);
397                         break;
398                 default:
399                         panic("Bad QID %p in devalarm", c->qid.path);
400         }
401         return n;
402 }
403
404 struct dev alarmdevtab __devtab = {
405         'A',
406         "alarm",
407
408         devreset,
409         alarminit,
410         devshutdown,
411         alarmattach,
412         alarmwalk,
413         alarmstat,
414         alarmopen,
415         alarmcreate,
416         alarmclose,
417         alarmread,
418         devbread,
419         alarmwrite,
420         devbwrite,
421         alarmremove,
422         alarmwstat,
423         devpower,
424         //devconfig,
425         devchaninfo,
426 };