And now for some files.
[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         msg.ev_arg2 = a->id;
96         send_event(a->proc, ev_q, &msg, 0);
97 }
98
99 void devalarm_init(struct proc *p)
100 {
101         TAILQ_INIT(&p->alarmset.list);
102         spinlock_init(&p->alarmset.lock);
103         /* Just running all the proc alarms on core 0. */
104         p->alarmset.tchain = &per_cpu_info[0].tchain;
105         p->alarmset.id_counter = 0;
106 }
107
108 static int alarmgen(struct chan *c, char *entry_name,
109                     struct dirtab *unused, int unused_nr_dirtab,
110                     int s, struct dir *dp)
111 {
112         struct qid q;
113         struct proc_alarm *a_i;
114         struct proc *p = current;
115         /* Whether we're in one dir or at the top, .. still takes us to the top. */
116         if (s == DEVDOTDOT) {
117                 mkqid(&q, Qtopdir, 0, QTDIR);
118                 devdir(c, c->qid, "#A", 0, eve, 0555, dp);
119                 return 1;
120         }
121         switch (TYPE(c->qid)) {
122                 case Qtopdir:
123                         /* Generate elements for the top level dir.  We support a clone and
124                          * alarm dirs at the top level */
125                         if (s == 0) {
126                                 mkqid(&q, Qclone, 0, QTFILE);
127                                 devdir(c, q, "clone", 0, eve, 0666, dp);
128                                 return 1;
129                         }
130                         s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
131                         /* Gets the s-th element (0 index)
132                          * 
133                          * I would like to take advantage of the state machine and our
134                          * previous answer to get the sth element of the list.  We can get
135                          * at our previous run of gen from dp (struct dir), and use that to
136                          * get the next item.  I'd like to do something like:
137                          *
138                          * if (dp->qid.path >> ADDR_SHIFT)
139                          *              a_i = TAILQ_NEXT(QID2A(dp->qid), link);
140                          *
141                          * Dev would give us a 0'd dp path on the first run, so if we have a
142                          * path, we know we're on an iterative run.  However, the problem is
143                          * that we could have lost the element dp refers to (QID2A(dp->qid))
144                          * since our previous run, so we can't even access that memory to
145                          * check for refcnts or anything.  We need a new model for how gen
146                          * works (probably a gen_start and gen_stop devop, passed as
147                          * parameters to devwalk), so that we can have some invariants
148                          * between gen runs.
149                          *
150                          * Til then, we're stuck with arrays like in #I (though we can use
151                          * Linux style fdsets) or lousy O(n^2) linked lists (like #s).
152                          *
153                          * Note that we won't always start a gen loop with s == 0
154                          * (devdirread, for instance) */
155                         spin_lock(&p->alarmset.lock);
156                         TAILQ_FOREACH(a_i, &p->alarmset.list, link) {
157                                 if (s-- == 0)
158                                         break;
159                         }
160                         /* As soon as we unlock, someone could free a_i */
161                         if (!a_i) {
162                                 spin_unlock(&p->alarmset.lock);
163                                 return -1;
164                         }
165                         snprintf(get_cur_genbuf(), GENBUF_SZ, "a%d", a_i->id);
166                         mkqid(&q, QID(a_i, Qalarmdir), 0, QTDIR);
167                         devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
168                         spin_unlock(&p->alarmset.lock);
169                         return 1;
170                 case Qalarmdir:
171                         /* Gen the contents of the alarm dirs */
172                         s += Qctl;      /* first time through, start on Qctl */
173                         switch (s) {
174                                 case Qctl:
175                                         mkqid(&q, QID(QID2A(c->qid), Qctl), 0, QTFILE);
176                                         devdir(c, q, "ctl", 0, eve, 0666, dp);
177                                         return 1;
178                                 case Qtimer:
179                                         mkqid(&q, QID(QID2A(c->qid), Qtimer), 0, QTFILE);
180                                         devdir(c, q, "timer", 0, eve, 0666, dp);
181                                         return 1;
182                         }
183                         return -1;
184                 /* Need to also provide a direct hit for Qclone and all other files (at
185                  * all levels of the hierarchy).  Every file is both
186                  * generated (via the s increments in their respective directories) and
187                  * directly gen-able.  devstat() will call gen with a specific path in
188                  * the qid.  In these cases, we make a dir for whatever they are asking
189                  * for.  Note the qid stays the same.  I think this is what the old
190                  * plan9 comments above devgen were talking about for (ii).
191                  *
192                  * We don't need to do this for the directories - devstat will look for
193                  * the a directory by path and fail.  Then it will manually build the
194                  * stat output (check the -1 case in devstat). */
195                 case Qclone:
196                         devdir(c, c->qid, "clone", 0, eve, 0666, dp);
197                         return 1;
198                 case Qctl:
199                         devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
200                         return 1;
201                 case Qtimer:
202                         devdir(c, c->qid, "timer", 0, eve, 0666, dp);
203                         return 1;
204         }
205         return -1;
206 }
207
208 static void alarminit(void)
209 {
210 }
211
212 static struct chan *alarmattach(char *spec)
213 {
214         struct chan *c = devattach('A', spec);
215         mkqid(&c->qid, Qtopdir, 0, QTDIR);
216         return c;
217 }
218
219 static struct walkqid *alarmwalk(struct chan *c, struct chan *nc, char **name,
220                                  int nname)
221 {
222         return devwalk(c, nc, name, nname, 0, 0, alarmgen);
223 }
224
225 static int alarmstat(struct chan *c, uint8_t *db, int n)
226 {
227         return devstat(c, db, n, 0, 0, alarmgen);
228 }
229
230 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
231  * the open chan into p's fd table, then decref the chan. */
232 static struct chan *alarmopen(struct chan *c, int omode)
233 {
234         struct proc *p = current;
235         struct proc_alarm *a, *a_i;
236         switch (TYPE(c->qid)) {
237                 case Qtopdir:
238                 case Qalarmdir:
239                         if (omode & ORCLOSE)
240                                 error(Eperm);
241                         if (omode != OREAD)
242                                 error(Eisdir);
243                         break;
244                 case Qclone:
245                         a = kzmalloc(sizeof(struct proc_alarm), KMALLOC_WAIT);
246                         kref_init(&a->kref, alarm_release, 1);
247                         init_awaiter(&a->a_waiter, proc_alarm_handler);
248                         spin_lock(&p->alarmset.lock);
249                         a->id = p->alarmset.id_counter++;
250                         proc_incref(p, 1);
251                         a->proc = p;
252                         TAILQ_INSERT_TAIL(&p->alarmset.list, a, link);
253                         spin_unlock(&p->alarmset.lock);
254                         mkqid(&c->qid, QID(a, Qctl), 0, QTFILE);
255                         break;
256                 case Qctl:
257                 case Qtimer:
258                         /* the purpose of opening is to hold a kref on the proc_alarm */
259                         a = QID2A(c->qid);
260                         assert(a);
261                         assert(a->proc == current);
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.  We could speed it up
268                          * by storing an "on_list" bool in the a_is. */
269                         spin_lock(&p->alarmset.lock);
270                         TAILQ_FOREACH(a_i, &p->alarmset.list, link) {
271                                 if (a_i == a) {
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 = {
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 };