Run spatch on devcons.c
[akaros.git] / kern / drivers / dev / alarm.c
index 9c7613e..889384c 100644 (file)
@@ -2,22 +2,23 @@
  * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  *
- * devalarm/#A: a device for registering per-process alarms.
+ * #alarm: a device for registering per-process alarms.
  *
  * Allows a process to set up alarms, where the kernel will send an event to a
  * posted ev_q at a certain TSC time.
  *
- * Every process has their own alarm sets and view of #A; gen and friends look
- * at current's alarmset when it is time to gen or open a file.
+ * Every process has their own alarm sets and view of #alarm; gen and friends
+ * look at current's alarmset when it is time to gen or open a file.
  *
- * To use, first open #A/clone, and that gives you an alarm directory aN, where
- * N is ID of the alarm.  ctl takes two commands: "evq POINTER" (to tell the
- * kernel the pointer of your ev_q) and "cancel", to stop an alarm.  timer takes
- * just the value (in absolute tsc time) to fire the alarm.
+ * To use, first open #alarm/clone, and that gives you an alarm directory aN,
+ * where N is ID of the alarm.  ctl takes two commands: "evq POINTER" (to tell
+ * the kernel the pointer of your ev_q) and "cancel", to stop an alarm.  timer
+ * takes just the value (in absolute tsc time) to fire the alarm.
  *
- * While each process has a separate view of #A, it is possible to post a chan
- * to Qctl or Qtimer to #s.  If another proc has your Qtimer, it can set it in
- * the past, thereby triggering an immediate event.  More clever than useful.
+ * While each process has a separate view of #alarm, it is possible to post a
+ * chan to Qctl or Qtimer to #srv.  If another proc has your Qtimer, it can set
+ * it in the past, thereby triggering an immediate event.  More clever than
+ * useful.
  *
  * Notes on refcnting (the trickier parts here):
  * - the proc_alarms have counted references to their proc
 #include <umem.h>
 #include <devalarm.h>
 
+struct dev alarmdevtab;
+
+static char *devname(void)
+{
+       return alarmdevtab.name;
+}
+
 /* qid path types */
 #define Qtopdir                                        1
 #define Qclone                                 2
@@ -107,8 +115,8 @@ void devalarm_init(struct proc *p)
 }
 
 static int alarmgen(struct chan *c, char *entry_name,
-                    struct dirtab *unused, int unused_nr_dirtab,
-                    int s, struct dir *dp)
+                                       struct dirtab *unused, int unused_nr_dirtab,
+                                       int s, struct dir *dp)
 {
        struct qid q;
        struct proc_alarm *a_i;
@@ -116,7 +124,7 @@ static int alarmgen(struct chan *c, char *entry_name,
        /* Whether we're in one dir or at the top, .. still takes us to the top. */
        if (s == DEVDOTDOT) {
                mkqid(&q, Qtopdir, 0, QTDIR);
-               devdir(c, c->qid, "#A", 0, eve, 0555, dp);
+               devdir(c, q, devname(), 0, eve, 0555, dp);
                return 1;
        }
        switch (TYPE(c->qid)) {
@@ -137,7 +145,7 @@ static int alarmgen(struct chan *c, char *entry_name,
                         * get the next item.  I'd like to do something like:
                         *
                         * if (dp->qid.path >> ADDR_SHIFT)
-                        *              a_i = TAILQ_NEXT(QID2A(dp->qid), link);
+                        *      a_i = TAILQ_NEXT(QID2A(dp->qid), link);
                         *
                         * Dev would give us a 0'd dp path on the first run, so if we have a
                         * path, we know we're on an iterative run.  However, the problem is
@@ -148,8 +156,8 @@ static int alarmgen(struct chan *c, char *entry_name,
                         * parameters to devwalk), so that we can have some invariants
                         * between gen runs.
                         *
-                        * Til then, we're stuck with arrays like in #I (though we can use
-                        * Linux style fdsets) or lousy O(n^2) linked lists (like #s).
+                        * Til then, we're stuck with arrays like in #ip (though we can use
+                        * Linux style fdsets) or lousy O(n^2) linked lists (like #srv).
                         *
                         * Note that we won't always start a gen loop with s == 0
                         * (devdirread, for instance) */
@@ -182,17 +190,17 @@ static int alarmgen(struct chan *c, char *entry_name,
                                        return 1;
                        }
                        return -1;
-               /* Need to also provide a direct hit for Qclone and all other files (at
-                * all levels of the hierarchy).  Every file is both
-                * generated (via the s increments in their respective directories) and
-                * directly gen-able.  devstat() will call gen with a specific path in
-                * the qid.  In these cases, we make a dir for whatever they are asking
-                * for.  Note the qid stays the same.  I think this is what the old
-                * plan9 comments above devgen were talking about for (ii).
-                *
-                * We don't need to do this for the directories - devstat will look for
-                * the a directory by path and fail.  Then it will manually build the
-                * stat output (check the -1 case in devstat). */
+                       /* Need to also provide a direct hit for Qclone and all other files
+                        * (at all levels of the hierarchy).  Every file is both generated
+                        * (via the s increments in their respective directories) and
+                        * directly gen-able.  devstat() will call gen with a specific path
+                        * in the qid.  In these cases, we make a dir for whatever they are
+                        * asking for.  Note the qid stays the same.  I think this is what
+                        * the old plan9 comments above devgen were talking about for (ii).
+                        *
+                        * We don't need to do this for the directories - devstat will look
+                        * for the a directory by path and fail.  Then it will manually
+                        * build the stat output (check the -1 case in devstat). */
                case Qclone:
                        devdir(c, c->qid, "clone", 0, eve, 0666, dp);
                        return 1;
@@ -212,18 +220,18 @@ static void alarminit(void)
 
 static struct chan *alarmattach(char *spec)
 {
-       struct chan *c = devattach('A', spec);
+       struct chan *c = devattach(devname(), spec);
        mkqid(&c->qid, Qtopdir, 0, QTDIR);
        return c;
 }
 
 static struct walkqid *alarmwalk(struct chan *c, struct chan *nc, char **name,
-                                 int nname)
+                                                                int nname)
 {
        return devwalk(c, nc, name, nname, 0, 0, alarmgen);
 }
 
-static int alarmstat(struct chan *c, uint8_t *db, int n)
+static int alarmstat(struct chan *c, uint8_t * db, int n)
 {
        return devstat(c, db, n, 0, 0, alarmgen);
 }
@@ -237,10 +245,10 @@ static struct chan *alarmopen(struct chan *c, int omode)
        switch (TYPE(c->qid)) {
                case Qtopdir:
                case Qalarmdir:
-                       if (omode & ORCLOSE)
-                               error(Eperm);
-                       if ((omode & OREAD) != OREAD)
-                               error(Eisdir);
+                       if (omode & O_REMCLO)
+                               error(EPERM, NULL);
+                       if (omode & O_WRITE)
+                               error(EISDIR, NULL);
                        break;
                case Qclone:
                        a = kzmalloc(sizeof(struct proc_alarm), KMALLOC_WAIT);
@@ -259,17 +267,16 @@ static struct chan *alarmopen(struct chan *c, int omode)
                        /* the purpose of opening is to hold a kref on the proc_alarm */
                        a = QID2A(c->qid);
                        assert(a);
-                       assert(a->proc == current);
                        /* this isn't a valid pointer yet, since our chan doesn't have a
                         * ref.  since the time that walk gave our chan the qid, the chan
                         * could have been closed, and the alarm decref'd and freed.  the
                         * qid is essentially an uncounted reference, and we need to go to
                         * the source to attempt to get a real ref.  Unfortunately, this is
-                        * another scan of the list, same as devsrv.  We could speed it up
-                        * by storing an "on_list" bool in the a_is. */
+                        * another scan of the list, same as devsrv. */
                        spin_lock(&p->alarmset.lock);
                        TAILQ_FOREACH(a_i, &p->alarmset.list, link) {
                                if (a_i == a) {
+                                       assert(a->proc == current);
                                        /* it's still possible we're not getting the ref, racing
                                         * with the release method */
                                        if (!kref_get_not_zero(&a->kref, 1)) {
@@ -280,7 +287,7 @@ static struct chan *alarmopen(struct chan *c, int omode)
                        }
                        spin_unlock(&p->alarmset.lock);
                        if (!a_i)
-                               error("Unable to open alarm, concurrent closing");
+                               error(EFAIL, "Unable to open alarm, concurrent closing");
                        break;
        }
        c->mode = openmode(omode);
@@ -292,17 +299,17 @@ static struct chan *alarmopen(struct chan *c, int omode)
 
 static void alarmcreate(struct chan *c, char *name, int omode, uint32_t perm)
 {
-       error(Eperm);
+       error(EPERM, NULL);
 }
 
 static void alarmremove(struct chan *c)
 {
-       error(Eperm);
+       error(EPERM, NULL);
 }
 
-static int alarmwstat(struct chan *c, uint8_t *dp, int n)
+static int alarmwstat(struct chan *c, uint8_t * dp, int n)
 {
-       error("No alarmwstat");
+       error(EFAIL, "No alarmwstat");
        return 0;
 }
 
@@ -334,7 +341,7 @@ static long alarmread(struct chan *c, void *ubuf, long n, int64_t offset)
                case Qtimer:
                        p_alarm = QID2A(c->qid);
                        return readnum(offset, ubuf, n, p_alarm->a_waiter.wake_up_time,
-                                      NUMSIZE64);
+                                                  NUMSIZE64);
                default:
                        panic("Bad QID %p in devalarm", c->qid.path);
        }
@@ -348,7 +355,7 @@ static long alarmread(struct chan *c, void *ubuf, long n, int64_t offset)
 static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
 {
        ERRSTACK(1);
-       char buf[32];
+       char num64[NUMSIZE64];
        struct cmdbuf *cb;
        struct proc_alarm *p_alarm;
        uint64_t hexval;
@@ -356,7 +363,7 @@ static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
        switch (TYPE(c->qid)) {
                case Qtopdir:
                case Qalarmdir:
-                       error(Eperm);
+                       error(EPERM, NULL);
                case Qctl:
                        p_alarm = QID2A(c->qid);
                        cb = parsecmd(ubuf, n);
@@ -364,20 +371,22 @@ static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                                kfree(cb);
                                nexterror();
                        }
+                       if (cb->nf < 1)
+                               error(EFAIL, "short control request");
                        if (!strcmp(cb->f[0], "evq")) {
                                if (cb->nf < 2)
-                                       error("evq needs a pointer");
+                                       error(EFAIL, "evq needs a pointer");
                                /* i think it's safe to do a stroul on a parsecmd.  it's kernel
                                 * memory, and space or 0 terminated */
                                hexval = strtoul(cb->f[1], 0, 16);
                                /* This is just to help userspace - event code can handle it */
-                               if (!is_user_rwaddr((void*)hexval, sizeof(struct event_queue)))
-                                       error("Non-user ev_q pointer");
-                               p_alarm->ev_q = (struct event_queue*)hexval;
+                               if (!is_user_rwaddr((void *)hexval, sizeof(struct event_queue)))
+                                       error(EFAIL, "Non-user ev_q pointer");
+                               p_alarm->ev_q = (struct event_queue *)hexval;
                        } else if (!strcmp(cb->f[0], "cancel")) {
                                unset_alarm(p_alarm->proc->alarmset.tchain, &p_alarm->a_waiter);
                        } else {
-                               error("%s: not implemented", cb->f[0]);
+                               error(EFAIL, "%s: not implemented", cb->f[0]);
                        }
                        kfree(cb);
                        poperror();
@@ -385,16 +394,19 @@ static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                case Qtimer:
                        /* want to give strtoul a null-terminated buf (can't handle random
                         * user strings) */
-                       if (n >= sizeof(buf))
-                               error(Egreg);
-                       memcpy(buf, ubuf, n);
-                       buf[n] = 0;
-                       hexval = strtoul(buf, 0, 16);
+                       if (n > sizeof(num64)) {
+                               set_errno(EINVAL);
+                               error(EFAIL, "attempted to write %d chars, max %d", n,
+                                         sizeof(num64));
+                       }
+                       memcpy(num64, ubuf, n);
+                       num64[n] = 0;   /* enforce trailing 0 */
+                       hexval = strtoul(num64, 0, 16);
                        p_alarm = QID2A(c->qid);
                        /* if you don't know if it was running or not, resetting will turn
                         * it on regardless. */
                        reset_alarm_abs(p_alarm->proc->alarmset.tchain, &p_alarm->a_waiter,
-                                       hexval);
+                                                       hexval);
                        break;
                default:
                        panic("Bad QID %p in devalarm", c->qid.path);
@@ -403,25 +415,23 @@ static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
 }
 
 struct dev alarmdevtab __devtab = {
-       'A',
-       "alarm",
+       .name = "alarm",
 
-       devreset,
-       alarminit,
-       devshutdown,
-       alarmattach,
-       alarmwalk,
-       alarmstat,
-       alarmopen,
-       alarmcreate,
-       alarmclose,
-       alarmread,
-       devbread,
-       alarmwrite,
-       devbwrite,
-       alarmremove,
-       alarmwstat,
-       devpower,
-       //devconfig,
-       //devchaninfo,
+       .reset = devreset,
+       .init = alarminit,
+       .shutdown = devshutdown,
+       .attach = alarmattach,
+       .walk = alarmwalk,
+       .stat = alarmstat,
+       .open = alarmopen,
+       .create = alarmcreate,
+       .close = alarmclose,
+       .read = alarmread,
+       .bread = devbread,
+       .write = alarmwrite,
+       .bwrite = devbwrite,
+       .remove = alarmremove,
+       .wstat = alarmwstat,
+       .power = devpower,
+       .chaninfo = devchaninfo,
 };