Add period and count to #alarm
[akaros.git] / kern / drivers / dev / alarm.c
1 /* Copyright (c) 2013 The Regents of the University of California
2  * Copyright (c) 2016 Google Inc.
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  *
6  * #alarm: a device for registering per-process alarms.
7  *
8  * Allows a process to set up alarms, which they can tap to get events at a
9  * certain TSC time.
10  *
11  * Every process has their own alarm sets and view of #alarm; gen and friends
12  * look at current's alarmset when it is time to gen or open a file.
13  *
14  * To use, first open #alarm/clone, and that gives you an alarm directory aN,
15  * where N is ID of the alarm.  The FD you get from clone points to 'ctl.'
16  *
17  * 'ctl' takes no commands.  You can read it to get the ID.  That's it.
18  *
19  * 'timer' takes the hex string value (in absolute tsc time) to fire the alarm.
20  * Writing 0 disables the alarm.  You can read 'timer' to get the next time it
21  * will fire, in TSC time.  0 means it is disabled.  To find out about the timer
22  * firing, put an FD tap on 'timer' for FDTAP_FILT_WRITTEN.
23  *
24  * 'period' takes the hex string value (in TSC ticks) for the period of the
25  * alarm.  If non-zero, the alarm will rearm when it fires.  You can read the
26  * period.
27  *
28  * Reading the 'count' file will return the number of times the alarm has
29  * expired since the last read or the last write to 'timer'.  If this is 0, then
30  * read() will block or EAGAIN.  You cannot write 'count'.  You can tap it for
31  * FDTAP_FILT_READABLE.
32  *
33  * While each process has a separate view of #alarm, it is possible to post a
34  * chan to Qctl or Qtimer to #srv.  If another proc has your Qtimer, it can set
35  * it in the past, thereby triggering an immediate event.  More clever than
36  * useful.
37  *
38  * Notes on refcnting (the trickier parts here):
39  * - the proc_alarms have counted references to their proc
40  *              proc won't free til all alarms are closed, which is fine.  we close
41  *              all files in destroy.  if a proc drops a chan in srv, the proc will stay
42  *              alive because the alarm is alive - til that chan is closed (srvremove)
43  *
44  *              other shady ways to keep a chan alive: cd to it!  if it is ., we'd
45  *              keep a ref around.  however, only alarmdir *file* grab refs, not
46  *              directories.
47  *
48  * - proc_alarms are kref'd, since there can be multiple chans per alarm
49  *              the only thing that keeps an alarm alive is a chan on a CTL or TIMER (or
50  *              other file).  when you cloned, you got back an open CTL, which keeps the
51  *              alarm (and the dir) alive.
52  *
53  *              we need to be careful generating krefs, in case alarms are concurrently
54  *              released and removed from the lists.  just like with procs and pid2proc,
55  *              we need to sync with the source of the kref. */
56
57 #include <kmalloc.h>
58 #include <string.h>
59 #include <stdio.h>
60 #include <assert.h>
61 #include <error.h>
62 #include <pmap.h>
63 #include <sys/queue.h>
64 #include <smp.h>
65 #include <kref.h>
66 #include <atomic.h>
67 #include <alarm.h>
68 #include <umem.h>
69 #include <devalarm.h>
70
71 struct dev alarmdevtab;
72
73 static char *devname(void)
74 {
75         return alarmdevtab.name;
76 }
77
78 /* qid path types */
79 #define Qtopdir                                 1
80 #define Qclone                                  2
81 #define Qalarmdir                               3
82 #define Qctl                                    4
83 #define Qtimer                                  5       /* Qctl + 1 */
84 #define Qperiod                                 6
85 #define Qcount                                  7
86
87 /* This paddr/kaddr is a bit dangerous.  it'll work so long as we don't need all
88  * 64 bits for a physical address (48 is the current norm on x86_64). */
89 #define ADDR_SHIFT 5
90 #define QID2A(q) ((struct proc_alarm*)KADDR(((q).path >> ADDR_SHIFT)))
91 #define TYPE(q) ((q).path & ((1 << ADDR_SHIFT) - 1))
92 #define QID(ptr, type) ((PADDR(ptr) << ADDR_SHIFT) | type)
93 extern char *eve;
94
95 static void alarm_release(struct kref *kref)
96 {
97         struct proc_alarm *a = container_of(kref, struct proc_alarm, kref);
98         struct proc *p = a->proc;
99         assert(p);
100         spin_lock(&p->alarmset.lock);
101         TAILQ_REMOVE(&p->alarmset.list, a, link);
102         spin_unlock(&p->alarmset.lock);
103         /* When this returns, the alarm has either fired or it never will */
104         unset_alarm(p->alarmset.tchain, &a->a_waiter);
105         proc_decref(p);
106         kfree(a);
107 }
108
109 static void alarm_fire_taps(struct proc_alarm *a, int filter)
110 {
111         struct fd_tap *tap_i;
112
113         SLIST_FOREACH(tap_i, &a->fd_taps, link)
114                 fire_tap(tap_i, filter);
115 }
116
117 static void proc_alarm_handler(struct alarm_waiter *a_waiter)
118 {
119         struct proc_alarm *a = container_of(a_waiter, struct proc_alarm, a_waiter);
120
121         /* We need the alarm to *not* hold the tchain lock (i.e. not in IRQ ctx),
122          * o/w we could deadlock.  The lock ordering is alarm_lock->tchain_lock. */
123         assert(!a_waiter->holds_tchain_lock);
124         cv_lock(&a->cv);
125         a->count++;
126         if (a->should_stop || !a->period) {
127                 a_waiter->wake_up_time = 0;
128                 a->armed = FALSE;
129         } else {
130                 a_waiter->wake_up_time += a->period;
131                 set_alarm(a->proc->alarmset.tchain, a_waiter);
132         }
133         __cv_broadcast(&a->cv);
134         cv_unlock(&a->cv);
135         /* Fires taps for both Qtimer and Qcount. */
136         alarm_fire_taps(a, FDTAP_FILT_WRITTEN | FDTAP_FILT_READABLE);
137 }
138
139 void devalarm_init(struct proc *p)
140 {
141         TAILQ_INIT(&p->alarmset.list);
142         spinlock_init(&p->alarmset.lock);
143         /* Just running all the proc alarms on core 0. */
144         p->alarmset.tchain = &per_cpu_info[0].tchain;
145         p->alarmset.id_counter = 0;
146 }
147
148 static int alarmgen(struct chan *c, char *entry_name,
149                                         struct dirtab *unused, int unused_nr_dirtab,
150                                         int s, struct dir *dp)
151 {
152         struct qid q;
153         struct proc_alarm *a_i;
154         struct proc *p = current;
155         /* Whether we're in one dir or at the top, .. still takes us to the top. */
156         if (s == DEVDOTDOT) {
157                 mkqid(&q, Qtopdir, 0, QTDIR);
158                 devdir(c, q, devname(), 0, eve, 0555, dp);
159                 return 1;
160         }
161         switch (TYPE(c->qid)) {
162                 case Qtopdir:
163                         /* Generate elements for the top level dir.  We support a clone and
164                          * alarm dirs at the top level */
165                         if (s == 0) {
166                                 mkqid(&q, Qclone, 0, QTFILE);
167                                 devdir(c, q, "clone", 0, eve, 0666, dp);
168                                 return 1;
169                         }
170                         s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
171                         /* Gets the s-th element (0 index)
172                          * 
173                          * I would like to take advantage of the state machine and our
174                          * previous answer to get the sth element of the list.  We can get
175                          * at our previous run of gen from dp (struct dir), and use that to
176                          * get the next item.  I'd like to do something like:
177                          *
178                          * if (dp->qid.path >> ADDR_SHIFT)
179                          *      a_i = TAILQ_NEXT(QID2A(dp->qid), link);
180                          *
181                          * Dev would give us a 0'd dp path on the first run, so if we have a
182                          * path, we know we're on an iterative run.  However, the problem is
183                          * that we could have lost the element dp refers to (QID2A(dp->qid))
184                          * since our previous run, so we can't even access that memory to
185                          * check for refcnts or anything.  We need a new model for how gen
186                          * works (probably a gen_start and gen_stop devop, passed as
187                          * parameters to devwalk), so that we can have some invariants
188                          * between gen runs.
189                          *
190                          * Til then, we're stuck with arrays like in #ip (though we can use
191                          * Linux style fdsets) or lousy O(n^2) linked lists (like #srv).
192                          *
193                          * Note that we won't always start a gen loop with s == 0
194                          * (devdirread, for instance) */
195                         spin_lock(&p->alarmset.lock);
196                         TAILQ_FOREACH(a_i, &p->alarmset.list, link) {
197                                 if (s-- == 0)
198                                         break;
199                         }
200                         /* As soon as we unlock, someone could free a_i */
201                         if (!a_i) {
202                                 spin_unlock(&p->alarmset.lock);
203                                 return -1;
204                         }
205                         snprintf(get_cur_genbuf(), GENBUF_SZ, "a%d", a_i->id);
206                         mkqid(&q, QID(a_i, Qalarmdir), 0, QTDIR);
207                         devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
208                         spin_unlock(&p->alarmset.lock);
209                         return 1;
210                 case Qalarmdir:
211                         /* Gen the contents of the alarm dirs */
212                         s += Qctl;      /* first time through, start on Qctl */
213                         switch (s) {
214                                 case Qctl:
215                                         mkqid(&q, QID(QID2A(c->qid), Qctl), 0, QTFILE);
216                                         devdir(c, q, "ctl", 0, eve, 0666, dp);
217                                         return 1;
218                                 case Qtimer:
219                                         mkqid(&q, QID(QID2A(c->qid), Qtimer), 0, QTFILE);
220                                         devdir(c, q, "timer", 0, eve, 0666, dp);
221                                         return 1;
222                                 case Qperiod:
223                                         mkqid(&q, QID(QID2A(c->qid), Qperiod), 0, QTFILE);
224                                         devdir(c, q, "period", 0, eve, 0666, dp);
225                                         return 1;
226                                 case Qcount:
227                                         mkqid(&q, QID(QID2A(c->qid), Qcount), 0, QTFILE);
228                                         devdir(c, q, "count", 0, eve, 0666, dp);
229                                         return 1;
230                         }
231                         return -1;
232                         /* Need to also provide a direct hit for Qclone and all other files
233                          * (at all levels of the hierarchy).  Every file is both generated
234                          * (via the s increments in their respective directories) and
235                          * directly gen-able.  devstat() will call gen with a specific path
236                          * in the qid.  In these cases, we make a dir for whatever they are
237                          * asking for.  Note the qid stays the same.  I think this is what
238                          * the old plan9 comments above devgen were talking about for (ii).
239                          *
240                          * We don't need to do this for the directories - devstat will look
241                          * for the a directory by path and fail.  Then it will manually
242                          * build the stat output (check the -1 case in devstat). */
243                 case Qclone:
244                         devdir(c, c->qid, "clone", 0, eve, 0666, dp);
245                         return 1;
246                 case Qctl:
247                         devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
248                         return 1;
249                 case Qtimer:
250                         devdir(c, c->qid, "timer", 0, eve, 0666, dp);
251                         return 1;
252                 case Qperiod:
253                         devdir(c, c->qid, "period", 0, eve, 0666, dp);
254                         return 1;
255                 case Qcount:
256                         devdir(c, c->qid, "count", 0, eve, 0666, dp);
257                         return 1;
258         }
259         return -1;
260 }
261
262 static void alarminit(void)
263 {
264 }
265
266 static struct chan *alarmattach(char *spec)
267 {
268         struct chan *c = devattach(devname(), spec);
269         mkqid(&c->qid, Qtopdir, 0, QTDIR);
270         return c;
271 }
272
273 static struct walkqid *alarmwalk(struct chan *c, struct chan *nc, char **name,
274                                                                  int nname)
275 {
276         return devwalk(c, nc, name, nname, 0, 0, alarmgen);
277 }
278
279 static int alarmstat(struct chan *c, uint8_t * db, int n)
280 {
281         return devstat(c, db, n, 0, 0, alarmgen);
282 }
283
284 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
285  * the open chan into p's fd table, then decref the chan. */
286 static struct chan *alarmopen(struct chan *c, int omode)
287 {
288         struct proc *p = current;
289         struct proc_alarm *a, *a_i;
290         switch (TYPE(c->qid)) {
291                 case Qtopdir:
292                 case Qalarmdir:
293                         if (omode & O_REMCLO)
294                                 error(EPERM, ERROR_FIXME);
295                         if (omode & O_WRITE)
296                                 error(EISDIR, ERROR_FIXME);
297                         break;
298                 case Qclone:
299                         a = kzmalloc(sizeof(struct proc_alarm), MEM_WAIT);
300                         kref_init(&a->kref, alarm_release, 1);
301                         SLIST_INIT(&a->fd_taps);
302                         cv_init(&a->cv);
303                         init_awaiter(&a->a_waiter, proc_alarm_handler);
304                         spin_lock(&p->alarmset.lock);
305                         a->id = p->alarmset.id_counter++;
306                         proc_incref(p, 1);
307                         a->proc = p;
308                         TAILQ_INSERT_TAIL(&p->alarmset.list, a, link);
309                         spin_unlock(&p->alarmset.lock);
310                         mkqid(&c->qid, QID(a, Qctl), 0, QTFILE);
311                         break;
312                 case Qctl:
313                 case Qtimer:
314                 case Qperiod:
315                 case Qcount:
316                         /* the purpose of opening is to hold a kref on the proc_alarm */
317                         a = QID2A(c->qid);
318                         assert(a);
319                         /* this isn't a valid pointer yet, since our chan doesn't have a
320                          * ref.  since the time that walk gave our chan the qid, the chan
321                          * could have been closed, and the alarm decref'd and freed.  the
322                          * qid is essentially an uncounted reference, and we need to go to
323                          * the source to attempt to get a real ref.  Unfortunately, this is
324                          * another scan of the list, same as devsrv. */
325                         spin_lock(&p->alarmset.lock);
326                         TAILQ_FOREACH(a_i, &p->alarmset.list, link) {
327                                 if (a_i == a) {
328                                         assert(a->proc == current);
329                                         /* it's still possible we're not getting the ref, racing
330                                          * with the release method */
331                                         if (!kref_get_not_zero(&a->kref, 1)) {
332                                                 a_i = 0;        /* lost the race, will error out later */
333                                         }
334                                         break;
335                                 }
336                         }
337                         spin_unlock(&p->alarmset.lock);
338                         if (!a_i)
339                                 error(EFAIL, "Unable to open alarm, concurrent closing");
340                         break;
341         }
342         c->mode = openmode(omode);
343         /* Assumes c is unique (can't be closed concurrently */
344         c->flag |= COPEN;
345         c->offset = 0;
346         return c;
347 }
348
349 static void alarmcreate(struct chan *c, char *name, int omode, uint32_t perm)
350 {
351         error(EPERM, ERROR_FIXME);
352 }
353
354 static void alarmremove(struct chan *c)
355 {
356         error(EPERM, ERROR_FIXME);
357 }
358
359 static int alarmwstat(struct chan *c, uint8_t * dp, int n)
360 {
361         error(EFAIL, "No alarmwstat");
362         return 0;
363 }
364
365 static void alarmclose(struct chan *c)
366 {
367         /* There are more closes than opens.  For instance, sysstat doesn't open,
368          * but it will close the chan it got from namec.  We only want to clean
369          * up/decref chans that were actually open. */
370         if (!(c->flag & COPEN))
371                 return;
372         switch (TYPE(c->qid)) {
373                 case Qctl:
374                 case Qtimer:
375                 case Qperiod:
376                 case Qcount:
377                         kref_put(&QID2A(c->qid)->kref);
378                         break;
379         }
380 }
381
382 /* Helper for Qcount to encapsulate timerfd. */
383 static long read_qcount(struct chan *c, void *ubuf, size_t n)
384 {
385         ERRSTACK(1);
386         struct proc_alarm *a = QID2A(c->qid);
387         struct cv_lookup_elm cle;
388         unsigned long old_count;
389
390         if (n > sizeof(old_count))
391                 error(EINVAL, "timerfd buffer is too small (%llu)", n);
392         /* TODO: have easily abortable CVs that don't require this mechanism. */
393         cv_lock(&a->cv);
394         __reg_abortable_cv(&cle, &a->cv);
395         if (waserror()) {
396                 cv_unlock(&a->cv);
397                 dereg_abortable_cv(&cle);
398                 nexterror();
399         }
400         while (!a->count) {
401                 if (c->flag & O_NONBLOCK)
402                         error(EAGAIN, "#alarm count was 0");
403                 if (should_abort(&cle))
404                         error(EINTR, "syscall aborted");
405                 cv_wait(&a->cv);
406         }
407         old_count = a->count;
408         a->count = 0;
409         cv_unlock(&a->cv);
410         dereg_abortable_cv(&cle);
411         poperror();
412         if (copy_to_user(ubuf, &old_count, sizeof(old_count)))
413                 error(EFAULT, "timerfd copy_to_user failed");
414         return sizeof(old_count);
415 }
416
417 static long alarmread(struct chan *c, void *ubuf, long n, int64_t offset)
418 {
419         struct proc_alarm *p_alarm;
420
421         switch (TYPE(c->qid)) {
422                 case Qtopdir:
423                 case Qalarmdir:
424                         return devdirread(c, ubuf, n, 0, 0, alarmgen);
425                 case Qctl:
426                         p_alarm = QID2A(c->qid);
427                         /* simple reads from p_alarm shouldn't need a lock */
428                         return readnum(offset, ubuf, n, p_alarm->id, NUMSIZE32);
429                 case Qtimer:
430                         p_alarm = QID2A(c->qid);
431                         return readnum(offset, ubuf, n, p_alarm->a_waiter.wake_up_time,
432                                                    NUMSIZE64);
433                 case Qperiod:
434                         p_alarm = QID2A(c->qid);
435                         return readnum(offset, ubuf, n, p_alarm->period, NUMSIZE64);
436                 case Qcount:
437                         return read_qcount(c, ubuf, n); /* ignore offset */
438                 default:
439                         panic("Bad QID %p in devalarm", c->qid.path);
440         }
441         return 0;
442 }
443
444 /* Helper, sets the procalarm to hexval (abs TSC ticks).  0 disarms. */
445 static void set_proc_alarm(struct proc_alarm *a, uint64_t hexval)
446 {
447         cv_lock(&a->cv);
448         /* Due to how we have to maintain 'count', we need to strictly account for
449          * the firings of the alarm.  Easiest thing is to disarm it, make sure it is
450          * off, reset everything, then rearm it. */
451         while (a->armed) {
452                 a->should_stop = TRUE;
453                 if (unset_alarm(a->proc->alarmset.tchain, &a->a_waiter)) {
454                         a->armed = FALSE;
455                         break;
456                 }
457                 /* We didn't find it on the tchain, which means it has left the chain,
458                  * but hasn't fired yet.  We need to block til it fired and disarmed
459                  * itself */
460                 cv_wait(&a->cv);
461         }
462         a->should_stop = FALSE;
463         a->count = 0;
464         if (hexval) {
465                 a->armed = TRUE;
466                 set_awaiter_abs(&a->a_waiter, hexval);
467                 set_alarm(a->proc->alarmset.tchain, &a->a_waiter);
468         }
469         cv_unlock(&a->cv);
470 }
471
472 /* Note that in read and write we have an open chan, which means we have an
473  * active kref on the p_alarm.  Also note that we make no assumptions about
474  * current here - we find the proc (and the tchain) via the ref stored in the
475  * proc_alarm. */
476 static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
477 {
478         struct proc_alarm *p_alarm;
479
480         switch (TYPE(c->qid)) {
481                 case Qtopdir:
482                 case Qalarmdir:
483                 case Qctl:
484                 case Qcount:
485                         error(EPERM, ERROR_FIXME);
486                 case Qtimer:
487                         set_proc_alarm(QID2A(c->qid), strtoul_from_ubuf(ubuf, n, 16));
488                         break;
489                 case Qperiod:
490                         p_alarm = QID2A(c->qid);
491                         /* racing with the handler which checks the val repeatedly */
492                         cv_lock(&p_alarm->cv);
493                         p_alarm->period = strtoul_from_ubuf(ubuf, n, 16);
494                         cv_unlock(&p_alarm->cv);
495                         break;
496                 default:
497                         panic("Bad QID %p in devalarm", c->qid.path);
498         }
499         return n;
500 }
501
502 /* We use the same tap list, regardless of Qtimer or Qcount */
503 static int tap_alarm(struct proc_alarm *a, struct fd_tap *tap, int cmd,
504                      int legal_filter)
505 {
506         int ret;
507
508         if (tap->filter & ~legal_filter) {
509                 set_error(ENOSYS, "Unsupported #%s tap, must be %p", devname(),
510                                   legal_filter);
511                 return -1;
512         }
513         cv_lock(&a->cv);
514         switch (cmd) {
515         case (FDTAP_CMD_ADD):
516                 SLIST_INSERT_HEAD(&a->fd_taps, tap, link);
517                 ret = 0;
518                 break;
519         case (FDTAP_CMD_REM):
520                 SLIST_REMOVE(&a->fd_taps, tap, fd_tap, link);
521                 ret = 0;
522                 break;
523         default:
524                 set_error(ENOSYS, "Unsupported #%s tap command %p",
525                                   devname(), cmd);
526                 ret = -1;
527         }
528         cv_unlock(&a->cv);
529         return ret;
530 }
531
532 static int alarm_tapfd(struct chan *c, struct fd_tap *tap, int cmd)
533 {
534         struct proc_alarm *a = QID2A(c->qid);
535
536         /* We don't actually support HANGUP, but epoll implies it. */
537         #define ALARM_LEGAL_TIMER_TAPS (FDTAP_FILT_WRITTEN | FDTAP_FILT_HANGUP)
538         #define ALARM_LEGAL_COUNT_TAPS (FDTAP_FILT_READABLE | FDTAP_FILT_HANGUP)
539
540         switch (TYPE(c->qid)) {
541         case Qtimer:
542                 return tap_alarm(a, tap, cmd, ALARM_LEGAL_TIMER_TAPS);
543         case Qcount:
544                 return tap_alarm(a, tap, cmd, ALARM_LEGAL_COUNT_TAPS);
545         default:
546                 set_error(ENOSYS, "Can't tap #%s file type %d", devname(),
547                           c->qid.path);
548                 return -1;
549         }
550 }
551
552 static char *alarm_chaninfo(struct chan *ch, char *ret, size_t ret_l)
553 {
554         struct proc_alarm *a;
555
556         switch (TYPE(ch->qid)) {
557         case Qctl:
558         case Qtimer:
559         case Qperiod:
560         case Qcount:
561                 a = QID2A(ch->qid);
562                 snprintf(ret, ret_l, "Id %d, %s, expires %llu, period %llu, count %llu",
563                          a->id, SLIST_EMPTY(&a->fd_taps) ? "untapped" : "tapped",
564                          a->a_waiter.wake_up_time, a->period, a->count);
565                 break;
566         default:
567                 return devchaninfo(ch, ret, ret_l);
568         }
569         return ret;
570 }
571
572 struct dev alarmdevtab __devtab = {
573         .name = "alarm",
574
575         .reset = devreset,
576         .init = alarminit,
577         .shutdown = devshutdown,
578         .attach = alarmattach,
579         .walk = alarmwalk,
580         .stat = alarmstat,
581         .open = alarmopen,
582         .create = alarmcreate,
583         .close = alarmclose,
584         .read = alarmread,
585         .bread = devbread,
586         .write = alarmwrite,
587         .bwrite = devbwrite,
588         .remove = alarmremove,
589         .wstat = alarmwstat,
590         .power = devpower,
591         .chaninfo = alarm_chaninfo,
592         .tapfd = alarm_tapfd,
593 };