9ns: Fix devtab function pointer signatures
[akaros.git] / kern / drivers / dev / alarm.c
index a50e65e..7b31548 100644 (file)
@@ -90,7 +90,7 @@ static char *devname(void)
 #define QID2A(q) ((struct proc_alarm*)KADDR(((q).path >> ADDR_SHIFT)))
 #define TYPE(q) ((q).path & ((1 << ADDR_SHIFT) - 1))
 #define QID(ptr, type) ((PADDR(ptr) << ADDR_SHIFT) | type)
-extern char *eve;
+extern struct username eve;
 
 static void alarm_release(struct kref *kref)
 {
@@ -118,22 +118,19 @@ static void proc_alarm_handler(struct alarm_waiter *a_waiter)
 {
        struct proc_alarm *a = container_of(a_waiter, struct proc_alarm, a_waiter);
 
-       /* We need the alarm to *not* hold the tchain lock (i.e. not in IRQ ctx),
-        * o/w we could deadlock.  The lock ordering is alarm_lock->tchain_lock. */
-       assert(!a_waiter->holds_tchain_lock);
        cv_lock(&a->cv);
        a->count++;
-       if (a->should_stop || !a->period) {
+       if (!a->period) {
                a_waiter->wake_up_time = 0;
-               a->armed = FALSE;
        } else {
+               /* TODO: use an alarm helper, once we switch over to nsec */
                a_waiter->wake_up_time += a->period;
                set_alarm(a->proc->alarmset.tchain, a_waiter);
        }
        __cv_broadcast(&a->cv);
-       cv_unlock(&a->cv);
        /* Fires taps for both Qtimer and Qcount. */
        alarm_fire_taps(a, FDTAP_FILT_WRITTEN | FDTAP_FILT_READABLE);
+       cv_unlock(&a->cv);
 }
 
 void devalarm_init(struct proc *p)
@@ -155,7 +152,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, q, devname(), 0, eve, 0555, dp);
+               devdir(c, q, devname(), 0, eve.name, 0555, dp);
                return 1;
        }
        switch (TYPE(c->qid)) {
@@ -164,12 +161,12 @@ static int alarmgen(struct chan *c, char *entry_name,
                         * alarm dirs at the top level */
                        if (s == 0) {
                                mkqid(&q, Qclone, 0, QTFILE);
-                               devdir(c, q, "clone", 0, eve, 0666, dp);
+                               devdir(c, q, "clone", 0, eve.name, 0666, dp);
                                return 1;
                        }
                        s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
                        /* Gets the s-th element (0 index)
-                        * 
+                        *
                         * I would like to take advantage of the state machine and our
                         * previous answer to get the sth element of the list.  We can get
                         * at our previous run of gen from dp (struct dir), and use that to
@@ -204,7 +201,7 @@ static int alarmgen(struct chan *c, char *entry_name,
                        }
                        snprintf(get_cur_genbuf(), GENBUF_SZ, "a%d", a_i->id);
                        mkqid(&q, QID(a_i, Qalarmdir), 0, QTDIR);
-                       devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
+                       devdir(c, q, get_cur_genbuf(), 0, eve.name, 0555, dp);
                        spin_unlock(&p->alarmset.lock);
                        return 1;
                case Qalarmdir:
@@ -213,19 +210,19 @@ static int alarmgen(struct chan *c, char *entry_name,
                        switch (s) {
                                case Qctl:
                                        mkqid(&q, QID(QID2A(c->qid), Qctl), 0, QTFILE);
-                                       devdir(c, q, "ctl", 0, eve, 0666, dp);
+                                       devdir(c, q, "ctl", 0, eve.name, 0666, dp);
                                        return 1;
                                case Qtimer:
                                        mkqid(&q, QID(QID2A(c->qid), Qtimer), 0, QTFILE);
-                                       devdir(c, q, "timer", 0, eve, 0666, dp);
+                                       devdir(c, q, "timer", 0, eve.name, 0666, dp);
                                        return 1;
                                case Qperiod:
                                        mkqid(&q, QID(QID2A(c->qid), Qperiod), 0, QTFILE);
-                                       devdir(c, q, "period", 0, eve, 0666, dp);
+                                       devdir(c, q, "period", 0, eve.name, 0666, dp);
                                        return 1;
                                case Qcount:
                                        mkqid(&q, QID(QID2A(c->qid), Qcount), 0, QTFILE);
-                                       devdir(c, q, "count", 0, eve, 0666, dp);
+                                       devdir(c, q, "count", 0, eve.name, 0666, dp);
                                        return 1;
                        }
                        return -1;
@@ -241,19 +238,19 @@ static int alarmgen(struct chan *c, char *entry_name,
                         * 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);
+                       devdir(c, c->qid, "clone", 0, eve.name, 0666, dp);
                        return 1;
                case Qctl:
-                       devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
+                       devdir(c, c->qid, "ctl", 0, eve.name, 0666, dp);
                        return 1;
                case Qtimer:
-                       devdir(c, c->qid, "timer", 0, eve, 0666, dp);
+                       devdir(c, c->qid, "timer", 0, eve.name, 0666, dp);
                        return 1;
                case Qperiod:
-                       devdir(c, c->qid, "period", 0, eve, 0666, dp);
+                       devdir(c, c->qid, "period", 0, eve.name, 0666, dp);
                        return 1;
                case Qcount:
-                       devdir(c, c->qid, "count", 0, eve, 0666, dp);
+                       devdir(c, c->qid, "count", 0, eve.name, 0666, dp);
                        return 1;
        }
        return -1;
@@ -271,12 +268,12 @@ static struct chan *alarmattach(char *spec)
 }
 
 static struct walkqid *alarmwalk(struct chan *c, struct chan *nc, char **name,
-                                                                int nname)
+                                                                unsigned int nname)
 {
        return devwalk(c, nc, name, nname, 0, 0, alarmgen);
 }
 
-static int alarmstat(struct chan *c, uint8_t * db, int n)
+static size_t alarmstat(struct chan *c, uint8_t *db, size_t n)
 {
        return devstat(c, db, n, 0, 0, alarmgen);
 }
@@ -300,6 +297,7 @@ static struct chan *alarmopen(struct chan *c, int omode)
                        kref_init(&a->kref, alarm_release, 1);
                        SLIST_INIT(&a->fd_taps);
                        cv_init(&a->cv);
+                       qlock_init(&a->qlock);
                        init_awaiter(&a->a_waiter, proc_alarm_handler);
                        spin_lock(&p->alarmset.lock);
                        a->id = p->alarmset.id_counter++;
@@ -346,22 +344,6 @@ static struct chan *alarmopen(struct chan *c, int omode)
        return c;
 }
 
-static void alarmcreate(struct chan *c, char *name, int omode, uint32_t perm)
-{
-       error(EPERM, ERROR_FIXME);
-}
-
-static void alarmremove(struct chan *c)
-{
-       error(EPERM, ERROR_FIXME);
-}
-
-static int alarmwstat(struct chan *c, uint8_t * dp, int n)
-{
-       error(EFAIL, "No alarmwstat");
-       return 0;
-}
-
 static void alarmclose(struct chan *c)
 {
        /* There are more closes than opens.  For instance, sysstat doesn't open,
@@ -414,7 +396,7 @@ static long read_qcount(struct chan *c, void *ubuf, size_t n)
        return sizeof(old_count);
 }
 
-static long alarmread(struct chan *c, void *ubuf, long n, int64_t offset)
+static size_t alarmread(struct chan *c, void *ubuf, size_t n, off64_t offset)
 {
        struct proc_alarm *p_alarm;
 
@@ -444,36 +426,35 @@ static long alarmread(struct chan *c, void *ubuf, long n, int64_t offset)
 /* Helper, sets the procalarm to hexval (abs TSC ticks).  0 disarms. */
 static void set_proc_alarm(struct proc_alarm *a, uint64_t hexval)
 {
-       cv_lock(&a->cv);
        /* Due to how we have to maintain 'count', we need to strictly account for
-        * the firings of the alarm.  Easiest thing is to disarm it, make sure it is
-        * off, reset everything, then rearm it. */
-       while (a->armed) {
-               a->should_stop = TRUE;
-               if (unset_alarm(a->proc->alarmset.tchain, &a->a_waiter)) {
-                       a->armed = FALSE;
-                       break;
-               }
-               /* We didn't find it on the tchain, which means it has left the chain,
-                * but hasn't fired yet.  We need to block til it fired and disarmed
-                * itself */
-               cv_wait(&a->cv);
-       }
-       a->should_stop = FALSE;
+        * the firings of the alarm.  Easiest thing is to disarm it, reset
+        * everything, then rearm it.  Note that if someone is blocked on count = 0,
+        * they may still be blocked until the next time the alarm fires.
+        *
+        * unset waits on the handler, which grabs the cv lock, so we don't grab the
+        * cv lock.  However, we still need to protect ourselves from multiple
+        * setters trying to run this at once.  Unset actually can handle being
+        * called concurrently, but alarm setters can't, nor can it handle the
+        * unsets and sets getting out of sync.  For instance, two unsets followed
+        * by two sets would be a bug.  Likewise, setting the awaiter value while it
+        * is on a tchain is a bug.  The qlock prevents that. */
+       qlock(&a->qlock);
+       unset_alarm(a->proc->alarmset.tchain, &a->a_waiter);
+       cv_lock(&a->cv);
        a->count = 0;
        if (hexval) {
-               a->armed = TRUE;
                set_awaiter_abs(&a->a_waiter, hexval);
                set_alarm(a->proc->alarmset.tchain, &a->a_waiter);
        }
        cv_unlock(&a->cv);
+       qunlock(&a->qlock);
 }
 
 /* Note that in read and write we have an open chan, which means we have an
  * active kref on the p_alarm.  Also note that we make no assumptions about
  * current here - we find the proc (and the tchain) via the ref stored in the
  * proc_alarm. */
-static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
+static size_t alarmwrite(struct chan *c, void *ubuf, size_t n, off64_t unused)
 {
        struct proc_alarm *p_alarm;
 
@@ -579,14 +560,14 @@ struct dev alarmdevtab __devtab = {
        .walk = alarmwalk,
        .stat = alarmstat,
        .open = alarmopen,
-       .create = alarmcreate,
+       .create = devcreate,
        .close = alarmclose,
        .read = alarmread,
        .bread = devbread,
        .write = alarmwrite,
        .bwrite = devbwrite,
-       .remove = alarmremove,
-       .wstat = alarmwstat,
+       .remove = devremove,
+       .wstat = devwstat,
        .power = devpower,
        .chaninfo = alarm_chaninfo,
        .tapfd = alarm_tapfd,