Remove the alarm-with-no-func use case
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 14 Jul 2016 14:54:04 +0000 (10:54 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 19 Jul 2016 15:43:10 +0000 (11:43 -0400)
The old version allowed you to just block on a semaphore if you passed '0'
for the function.  No one was using it, and it complicated the
implementation.  Its functionality has been superceded by functions like
kthread_usleep().

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/alarm.h
kern/src/alarm.c

index 2b62360..b0bb52c 100644 (file)
@@ -5,8 +5,7 @@
  * Alarms.  This includes various ways to sleep for a while or defer work on a
  * specific timer.  These can be per-core, global or whatever.  Deferred work
  * is a function pointer which runs in interrupt context when the alarm goes off
  * Alarms.  This includes various ways to sleep for a while or defer work on a
  * specific timer.  These can be per-core, global or whatever.  Deferred work
  * is a function pointer which runs in interrupt context when the alarm goes off
- * (picture running the ksched then).  The other style is to block/sleep on the
- * awaiter after the alarm is set.
+ * (picture running the ksched then).
  *
  * Like with most systems, you won't wake up til after the time you specify (for
  * now).  This might change, esp if we tweak things to coalesce alarms.
  *
  * Like with most systems, you won't wake up til after the time you specify (for
  * now).  This might change, esp if we tweak things to coalesce alarms.
  *
  * Quick howto, using the pcpu tchains:
  *     struct timer_chain *tchain = &per_cpu_info[core_id()].tchain;
  *
  * Quick howto, using the pcpu tchains:
  *     struct timer_chain *tchain = &per_cpu_info[core_id()].tchain;
- * 1) To block your kthread on an alarm:
- *     struct alarm_waiter a_waiter;
- *     init_awaiter(&a_waiter, 0); // or init_awaiter_irq() for IRQ ctx alarms
- *     set_awaiter_rel(&a_waiter, USEC);
- *     set_alarm(tchain, &a_waiter);
- *     sleep_on_awaiter(&a_waiter);
- * 2) To set a handler to run on an alarm:
+ * To block your kthread on an alarm:
  *     struct alarm_waiter *waiter = kmalloc(sizeof(struct alarm_waiter), 0);
  *     struct alarm_waiter *waiter = kmalloc(sizeof(struct alarm_waiter), 0);
- *     init_awaiter(waiter, HANDLER);
+ *     struct alarm_waiter a_waiter;   // or use the stack
+ *
+ *     init_awaiter(waiter, HANDLER); // or init_awaiter_irq() for IRQ ctx alarms
  *     set_awaiter_rel(waiter, USEC);
  *     set_alarm(tchain, waiter);
  *     set_awaiter_rel(waiter, USEC);
  *     set_alarm(tchain, waiter);
+ *
  * If you want the HANDLER to run again, do this at the end of it:
  *     set_awaiter_rel(waiter, USEC);  // or whenever you want it to fire
  *     set_alarm(tchain, waiter);
  * If you want the HANDLER to run again, do this at the end of it:
  *     set_awaiter_rel(waiter, USEC);  // or whenever you want it to fire
  *     set_alarm(tchain, waiter);
@@ -60,9 +56,7 @@
  * Don't forget to manage your memory at some (safe) point:
  *     kfree(waiter);
  * In the future, we might have a slab for these.  You can get it from wherever
  * Don't forget to manage your memory at some (safe) point:
  *     kfree(waiter);
  * In the future, we might have a slab for these.  You can get it from wherever
- * you want, just don't use the stack for handler style, since you'll usually
- * return and pop up the stack after setting the alarm.
- * */
+ * you want, just be careful if you use the stack. */
 
 #pragma once
 
 
 #pragma once
 
 #include <sys/queue.h>
 #include <kthread.h>
 
 #include <sys/queue.h>
 #include <kthread.h>
 
-/* These structures allow code to block or defer work for a certain amount of
- * time.  Timer chains (like off a per-core timer) are made of lists/trees of
- * these.
- *
- * If you have a func pointer, that handler will run when the alarm goes off.
- * If you don't have a func pointer, you sleep on the semaphore and block your
- * kthread.  In the latter case, you ought to allocate space for them on the
- * stack of the thread you're about to block on. */
+/* These structures allow code to defer work for a certain amount of time.
+ * Timer chains (like off a per-core timer) are made of lists/trees of these. */
 struct alarm_waiter {
        uint64_t                                        wake_up_time;   /* ugh, this is a TSC for now */
        union {
                void (*func) (struct alarm_waiter *waiter);
                void (*func_irq) (struct alarm_waiter *waiter,
                                  struct hw_trapframe *hw_tf);
 struct alarm_waiter {
        uint64_t                                        wake_up_time;   /* ugh, this is a TSC for now */
        union {
                void (*func) (struct alarm_waiter *waiter);
                void (*func_irq) (struct alarm_waiter *waiter,
                                  struct hw_trapframe *hw_tf);
-               struct semaphore                        sem;            /* kthread will sleep on this */
        };
        void                                            *data;
        TAILQ_ENTRY(alarm_waiter)       next;
        bool                                            on_tchain;
        bool                                            irq_ok;
        bool                                            holds_tchain_lock;
        };
        void                                            *data;
        TAILQ_ENTRY(alarm_waiter)       next;
        bool                                            on_tchain;
        bool                                            irq_ok;
        bool                                            holds_tchain_lock;
-       bool                                            has_func;
 };
 TAILQ_HEAD(awaiters_tailq, alarm_waiter);              /* ideally not a LL */
 
 };
 TAILQ_HEAD(awaiters_tailq, alarm_waiter);              /* ideally not a LL */
 
@@ -129,8 +115,6 @@ bool reset_alarm_abs(struct timer_chain *tchain, struct alarm_waiter *waiter,
 bool reset_alarm_rel(struct timer_chain *tchain, struct alarm_waiter *waiter,
                      uint64_t usleep);
 
 bool reset_alarm_rel(struct timer_chain *tchain, struct alarm_waiter *waiter,
                      uint64_t usleep);
 
-/* Blocks on the alarm waiter */
-int sleep_on_awaiter(struct alarm_waiter *waiter);
 /* Interrupt handlers need to call this.  Don't call it directly. */
 void __trigger_tchain(struct timer_chain *tchain, struct hw_trapframe *hw_tf);
 /* Sets the timer chain interrupt according to the next timer in the chain. */
 /* Interrupt handlers need to call this.  Don't call it directly. */
 void __trigger_tchain(struct timer_chain *tchain, struct hw_trapframe *hw_tf);
 /* Sets the timer chain interrupt according to the next timer in the chain. */
index 1fbf7d2..df1efba 100644 (file)
@@ -2,10 +2,9 @@
  * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  *
  * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  *
- * Alarms.  This includes various ways to sleep for a while or defer work on a
- * specific timer.  These can be per-core, global or whatever.  Like with most
- * systems, you won't wake up til after the time you specify. (for now, this
- * might change).
+ * Alarms.  This includes ways to defer work on a specific timer.  These can be
+ * per-core, global or whatever.  Like with most systems, you won't wake up til
+ * after the time you specify. (for now, this might change).
  *
  * TODO:
  *     - have a kernel sense of time, instead of just the TSC or whatever timer the
  *
  * TODO:
  *     - have a kernel sense of time, instead of just the TSC or whatever timer the
@@ -46,23 +45,19 @@ void init_timer_chain(struct timer_chain *tchain,
        reset_tchain_times(tchain);
 }
 
        reset_tchain_times(tchain);
 }
 
-/* Initializes a new awaiter.  Pass 0 for the function if you want it to be a
- * kthread-alarm, and sleep on it after you set the alarm later. */
 static void __init_awaiter(struct alarm_waiter *waiter)
 {
        waiter->wake_up_time = ALARM_POISON_TIME;
        waiter->on_tchain = FALSE;
        waiter->holds_tchain_lock = FALSE;
 static void __init_awaiter(struct alarm_waiter *waiter)
 {
        waiter->wake_up_time = ALARM_POISON_TIME;
        waiter->on_tchain = FALSE;
        waiter->holds_tchain_lock = FALSE;
-       if (!waiter->has_func)
-               sem_init_irqsave(&waiter->sem, 0);
 }
 
 void init_awaiter(struct alarm_waiter *waiter,
                   void (*func) (struct alarm_waiter *awaiter))
 {
        waiter->irq_ok = FALSE;
 }
 
 void init_awaiter(struct alarm_waiter *waiter,
                   void (*func) (struct alarm_waiter *awaiter))
 {
        waiter->irq_ok = FALSE;
-       waiter->has_func = func ? TRUE : FALSE;
-       waiter->func = func;                    /* if !func, this is a harmless zeroing */
+       assert(func);
+       waiter->func = func;
        __init_awaiter(waiter);
 }
 
        __init_awaiter(waiter);
 }
 
@@ -71,8 +66,8 @@ void init_awaiter_irq(struct alarm_waiter *waiter,
                                         struct hw_trapframe *hw_tf))
 {
        waiter->irq_ok = TRUE;
                                         struct hw_trapframe *hw_tf))
 {
        waiter->irq_ok = TRUE;
-       waiter->has_func = func_irq ? TRUE : FALSE;
-       waiter->func_irq = func_irq;    /* if !func, this is a harmless zeroing */
+       assert(func_irq);
+       waiter->func_irq = func_irq;
        __init_awaiter(waiter);
 }
 
        __init_awaiter(waiter);
 }
 
@@ -129,22 +124,16 @@ static void __run_awaiter(uint32_t srcid, long a0, long a1, long a2)
        waiter->func(waiter);
 }
 
        waiter->func(waiter);
 }
 
-/* When an awaiter's time has come, this gets called.  If it was a kthread, it
- * will wake up.  o/w, it will call the func ptr stored in the awaiter. */
 static void wake_awaiter(struct alarm_waiter *waiter,
                          struct hw_trapframe *hw_tf)
 {
 static void wake_awaiter(struct alarm_waiter *waiter,
                          struct hw_trapframe *hw_tf)
 {
-       if (waiter->has_func) {
-               if (waiter->irq_ok) {
-                       waiter->holds_tchain_lock = TRUE;
-                       waiter->func_irq(waiter, hw_tf);
-                       waiter->holds_tchain_lock = FALSE;
-               } else {
-                       send_kernel_message(core_id(), __run_awaiter, (long)waiter,
-                                           0, 0, KMSG_ROUTINE);
-               }
+       if (waiter->irq_ok) {
+               waiter->holds_tchain_lock = TRUE;
+               waiter->func_irq(waiter, hw_tf);
+               waiter->holds_tchain_lock = FALSE;
        } else {
        } else {
-               sem_up(&waiter->sem); /* IRQs are disabled, can call sem_up directly */
+               send_kernel_message(core_id(), __run_awaiter, (long)waiter,
+                                   0, 0, KMSG_ROUTINE);
        }
 }
 
        }
 }
 
@@ -350,20 +339,6 @@ bool reset_alarm_rel(struct timer_chain *tchain, struct alarm_waiter *waiter,
        return ret;
 }
 
        return ret;
 }
 
-/* Attempts to sleep on the alarm.  Could fail if you aren't allowed to kthread
- * (process limit, etc).  Don't call it on a waiter that is an event-handler. */
-int sleep_on_awaiter(struct alarm_waiter *waiter)
-{
-       int8_t irq_state = 0;
-       if (waiter->has_func)
-               panic("Tried blocking on a waiter %p with a func %p!", waiter,
-                     waiter->func);
-       /* Put the kthread to sleep.  TODO: This can fail (or at least it will be
-        * able to in the future) and we'll need to handle that. */
-       sem_down_irqsave(&waiter->sem, &irq_state);
-       return 0;
-}
-
 /* Sets the timer interrupt for the timer chain passed as parameter.
  * The next interrupt will be scheduled at the nearest timer available in the
  * chain.
 /* Sets the timer interrupt for the timer chain passed as parameter.
  * The next interrupt will be scheduled at the nearest timer available in the
  * chain.
@@ -432,23 +407,17 @@ void print_chain(struct timer_chain *tchain)
               tchain->earliest_time,
               tchain->latest_time);
        TAILQ_FOREACH(i, &tchain->waiters, next) {
               tchain->earliest_time,
               tchain->latest_time);
        TAILQ_FOREACH(i, &tchain->waiters, next) {
-               if (i->has_func) {
-                       uintptr_t f;
-                       if (i->irq_ok)
-                               f = (uintptr_t)i->func_irq;
-                       else
-                               f = (uintptr_t)i->func;
-                       char *f_name = get_fn_name(f);
-                       printk("\tWaiter %p, time %llu, func %p (%s)\n", i,
-                              i->wake_up_time, f, f_name);
-                       kfree(f_name);
-                       continue;
-               }
-               struct kthread *kthread = TAILQ_FIRST(&i->sem.waiters);
-               printk("\tWaiter %p, time: %llu, kthread: %p (%p) %s\n", i,
-                      i->wake_up_time, kthread, (kthread ? kthread->proc : 0),
-                      (kthread ? kthread->name : 0));
+               uintptr_t f;
+               char *f_name;
 
 
+               if (i->irq_ok)
+                       f = (uintptr_t)i->func_irq;
+               else
+                       f = (uintptr_t)i->func;
+               f_name = get_fn_name(f);
+               printk("\tWaiter %p, time %llu, func %p (%s)\n", i,
+                      i->wake_up_time, f, f_name);
+               kfree(f_name);
        }
        spin_unlock_irqsave(&tchain->lock);
 }
        }
        spin_unlock_irqsave(&tchain->lock);
 }