Ensures IRQs are enabled when proc_destroy()ing
[akaros.git] / kern / src / alarm.c
index 01a16c8..b4a00ed 100644 (file)
@@ -68,13 +68,22 @@ void set_awaiter_rel(struct alarm_waiter *waiter, uint64_t usleep)
 {
        uint64_t now, then;
        now = read_tsc();
-       then = now + usleep * (system_timing.tsc_freq / 1000000);
+       then = now + usec2tsc(usleep);
        /* This will go off if we wrap-around the TSC.  It'll never happen for legit
         * values, but this might catch some bugs with large usleeps. */
        assert(now < then);
        set_awaiter_abs(waiter, then);
 }
 
+/* Increment the timer that was already set, so that it goes off usleep usec
+ * from the previous tick.  This is different than 'rel' in that it doesn't care
+ * about when 'now' is. */
+void set_awaiter_inc(struct alarm_waiter *waiter, uint64_t usleep)
+{
+       assert(waiter->wake_up_time != ALARM_POISON_TIME);
+       waiter->wake_up_time += usec2tsc(usleep);
+}
+
 /* Helper, makes sure the interrupt is turned on at the right time.  Most of the
  * heavy lifting is in the timer-source specific function pointer. */
 static void reset_tchain_interrupt(struct timer_chain *tchain)
@@ -102,10 +111,12 @@ static void wake_awaiter(struct alarm_waiter *waiter)
        } else {
                /* Might encaps this */
                struct kthread *sleeper;
-               sleeper = __up_sem(&waiter->sem);
+               sleeper = __up_sem(&waiter->sem, TRUE);
                if (sleeper)
                        kthread_runnable(sleeper);
-               assert(TAILQ_EMPTY(&waiter->sem.waiters));
+               /* Don't touch the sleeper or waiter after making the kthread runnable,
+                * since it could be in use on another core (and the waiter can be
+                * clobbered as the kthread unwinds its stack). */
        }
 }
 
@@ -124,6 +135,9 @@ void trigger_tchain(struct timer_chain *tchain)
                if (i->wake_up_time <= now) {
                        changed_list = TRUE;
                        TAILQ_REMOVE(&tchain->waiters, i, next);
+                       /* Don't touch the waiter after waking it, since it could be in use
+                        * on another core (and the waiter can be clobbered as the kthread
+                        * unwinds its stack).  Or it could be kfreed */
                        wake_awaiter(i);
                } else {
                        break;
@@ -252,7 +266,7 @@ void set_pcpu_alarm_interrupt(uint64_t time, struct timer_chain *tchain)
                if (time <= now)
                        rel_usec = 1;
                else
-                       rel_usec = (time - now) / (system_timing.tsc_freq / 1000000);
+                       rel_usec = tsc2usec(time - now);
                rel_usec = MAX(rel_usec, 1);
                printd("Setting alarm for %llu, it is now %llu, rel_time %llu "
                       "tchain %08p\n", time, now, rel_usec, pcpui_tchain);
@@ -278,7 +292,10 @@ void print_chain(struct timer_chain *tchain)
               tchain->earliest_time,
               tchain->latest_time);
        TAILQ_FOREACH(i, &tchain->waiters, next) {
-               printk("\tWaiter %08p, time: %llu\n", i, i->wake_up_time);
+               struct kthread *kthread = TAILQ_FIRST(&i->sem.waiters);
+               printk("\tWaiter %08p, time: %llu, kthread: %08p (%08p)\n", i,
+                      i->wake_up_time, kthread, (kthread ? kthread->proc : 0));
+
        }
 }