Change #alarm cancel method
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 12 Apr 2016 22:13:42 +0000 (18:13 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 Apr 2016 14:29:13 +0000 (10:29 -0400)
Writing into a ctl is convenient, but its hard to get the status back out.
When you read ctl, you get the directory ID, not actual status.  We could
have a status variable that you parse, but that's a pain.

It's simpler to just have 0 > Qtimer mean "turn off the alarm".  That's
what this commit does, as well as removing the "cancel" command from Qctl.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/alarm.c
tests/alarm.c
user/benchutil/alarm.c
user/benchutil/include/benchutil/alarm.h
user/benchutil/pvcalarm.c

index 5e1907e..a917937 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (c) 2013 The Regents of the University of California
+ * Copyright (c) 2016 Google Inc.
  * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  *
  * look at current's alarmset when it is time to gen or open a file.
  *
  * To use, first open #alarm/clone, and that gives you an alarm directory aN,
- * where N is ID of the alarm.
+ * where N is ID of the alarm.  The FD you get from clone points to 'ctl.'
  *
- * ctl takes one command: "cancel", to stop an alarm.  timer takes just the
- * value (in absolute tsc time) to fire the alarm.  To find out about the timer
- * firing, put an FD tap on the timer for FDTAP_FILT_WRITTEN.
+ * 'ctl' takes no commands.  You can read it to get the ID.  That's it.
+ *
+ * 'timer' takes the hex string value (in absolute tsc time) to fire the alarm.
+ * Writing 0 disables the alarm.  You can read 'timer' to get the next time it
+ * will fire, in TSC time.  0 means it is disabled.  To find out about the timer
+ * firing, put an FD tap on 'timer' for FDTAP_FILT_WRITTEN.
  *
  * 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
@@ -108,6 +112,7 @@ static void proc_alarm_handler(struct alarm_waiter *a_waiter)
 {
        struct proc_alarm *a = container_of(a_waiter, struct proc_alarm, a_waiter);
 
+       a_waiter->wake_up_time = 0;
        alarm_fire_taps(a, FDTAP_FILT_WRITTEN);
 }
 
@@ -362,33 +367,15 @@ static long alarmread(struct chan *c, void *ubuf, long n, int64_t offset)
  * proc_alarm. */
 static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
 {
-       ERRSTACK(1);
        char num64[NUMSIZE64];
-       struct cmdbuf *cb;
        struct proc_alarm *p_alarm;
        uint64_t hexval;
 
        switch (TYPE(c->qid)) {
                case Qtopdir:
                case Qalarmdir:
-                       error(EPERM, ERROR_FIXME);
                case Qctl:
-                       p_alarm = QID2A(c->qid);
-                       cb = parsecmd(ubuf, n);
-                       if (waserror()) {
-                               kfree(cb);
-                               nexterror();
-                       }
-                       if (cb->nf < 1)
-                               error(EFAIL, "short control request");
-                       if (!strcmp(cb->f[0], "cancel")) {
-                               unset_alarm(p_alarm->proc->alarmset.tchain, &p_alarm->a_waiter);
-                       } else {
-                               error(EFAIL, "%s: not implemented", cb->f[0]);
-                       }
-                       kfree(cb);
-                       poperror();
-                       break;
+                       error(EPERM, ERROR_FIXME);
                case Qtimer:
                        /* want to give strtoul a null-terminated buf (can't handle random
                         * user strings) */
@@ -401,10 +388,15 @@ static long alarmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                        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);
+                       if (hexval) {
+                               /* 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);
+                       } else {
+                               unset_alarm(p_alarm->proc->alarmset.tchain, &p_alarm->a_waiter);
+                               p_alarm->a_waiter.wake_up_time = 0;
+                       }
                        break;
                default:
                        panic("Bad QID %p in devalarm", c->qid.path);
index 68b310d..14c5f23 100644 (file)
@@ -61,7 +61,7 @@ int main(int argc, char **argv)
                perror("Failed to set timer");
                exit(-1);
        }
-       if (devalarm_disable(ctlfd)) {
+       if (devalarm_disable(timerfd)) {
                perror("Failed to cancel timer");
                exit(-1);
        }
index f740877..746940a 100644 (file)
@@ -38,6 +38,7 @@
 #include <parlib/uthread.h>
 #include <parlib/spinlock.h>
 #include <parlib/timing.h>
+#include <sys/plan9_helpers.h>
 
 /* Helper to get your own alarm.   If you don't care about a return value, pass
  * 0 and it'll be ignored.  The alarm is built, but has no evq or timer set. */
@@ -89,13 +90,7 @@ int devalarm_set_evq(int timerfd, struct event_queue *ev_q, int alarmid)
 
 int devalarm_set_time(int timerfd, uint64_t tsc_time)
 {
-       int ret;
-       char buf[20];
-       ret = snprintf(buf, sizeof(buf), "%llx", tsc_time);
-       ret = write(timerfd, buf, ret);
-       if (ret <= 0)
-               return -1;
-       return 0;
+       return write_hex_to_fd(timerfd, tsc_time);
 }
 
 int devalarm_get_id(struct event_msg *ev_msg)
@@ -105,12 +100,9 @@ int devalarm_get_id(struct event_msg *ev_msg)
        return (int)(long)ev_msg->ev_arg3;
 }
 
-int devalarm_disable(int ctlfd)
+int devalarm_disable(int timerfd)
 {
-       int ret = write(ctlfd, "cancel", sizeof("cancel"));
-       if (ret <= 0)
-               return -1;
-       return 0;
+       return write_hex_to_fd(timerfd, 0);
 }
 
 /* Helpers, basically renamed kernel interfaces, with the *tchain. */
@@ -276,7 +268,7 @@ static void reset_tchain_interrupt(struct timer_chain *tchain)
        if (TAILQ_EMPTY(&tchain->waiters)) {
                /* Turn it off */
                printd("Turning alarm off\n");
-               if (devalarm_disable(tchain->ctlfd)) {
+               if (devalarm_disable(tchain->timerfd)) {
                        printf("Useralarm: unable to disarm alarm!\n");
                        return;
                }
index e032693..ef51f26 100644 (file)
@@ -44,7 +44,7 @@ int devalarm_get_fds(int *ctlfd_r, int *timerfd_r, int *alarmid_r);
 int devalarm_set_evq(int timerfd, struct event_queue *ev_q, int alarmid);
 int devalarm_set_time(int timerfd, uint64_t tsc_time);
 int devalarm_get_id(struct event_msg *ev_msg);
-int devalarm_disable(int ctlfd);
+int devalarm_disable(int timerfd);
 
 /* Alarm service */
 
index 7affaa9..62c403b 100644 (file)
@@ -97,7 +97,7 @@ static void start_pvcalarm(struct pvcalarm_data *pvcalarm_data, uint64_t offset)
 /* Stop the pvc alarm associated with pvcalarm_data */
 static void stop_pvcalarm(struct pvcalarm_data *pvcalarm_data)
 {
-       if (devalarm_disable(pvcalarm_data->ctlfd)) {
+       if (devalarm_disable(pvcalarm_data->timerfd)) {
                printf("Useralarm: unable to disarm alarm!\n");
                return;
        }