parlib: Fix potential alarm corruption
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 Jun 2018 21:21:33 +0000 (17:21 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 Jun 2018 21:23:57 +0000 (17:23 -0400)
The user-level alarm service is based off an older version of
kern/src/alarm.c.  That had commit f46e3e7984fb ("Fixes tchain
corruption"), but the fix never propagated to the user-level side.

There are a bunch of other differences between the kernel and user version,
which could be addressed.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/parlib/alarm.c

index bb5a536..e790b96 100644 (file)
@@ -279,8 +279,6 @@ static void reset_tchain_interrupt(struct timer_chain *tchain)
 /* When an awaiter's time has come, this gets called. */
 static void wake_awaiter(struct alarm_waiter *waiter)
 {
-       waiter->on_tchain = FALSE;
-       cmb();  /* enforce the on_tchain write before the handlers */
        waiter->func(waiter);
 }
 
@@ -298,7 +296,9 @@ static void __trigger_tchain(struct timer_chain *tchain)
                /* TODO: Could also do something in cases where we're close to now */
                if (i->wake_up_time <= now) {
                        changed_list = TRUE;
+                       i->on_tchain = FALSE;
                        TAILQ_REMOVE(&tchain->waiters, i, next);
+                       cmb();  /* enforce waking after removal */
                        /* 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 */
@@ -331,6 +331,7 @@ static bool __insert_awaiter(struct timer_chain *tchain,
        struct alarm_waiter *i, *temp;
        /* This will fail if you don't set a time */
        assert(waiter->wake_up_time != ALARM_POISON_TIME);
+       assert(!waiter->on_tchain);
        waiter->on_tchain = TRUE;
        /* Either the list is empty, or not. */
        if (TAILQ_EMPTY(&tchain->waiters)) {
@@ -409,6 +410,7 @@ static bool __remove_awaiter(struct timer_chain *tchain,
                tchain->latest_time = (temp) ? temp->wake_up_time : ALARM_POISON_TIME;
        }
        TAILQ_REMOVE(&tchain->waiters, waiter, next);
+       waiter->on_tchain = FALSE;
        return reset_int;
 }