Don't touch the waiter after waking
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 3 Jun 2011 18:57:54 +0000 (11:57 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:04 +0000 (17:36 -0700)
If the kthread runs on another core, it'll unwind its stack and
dealloc/clobber the waiter you just woke up.  Like many other places in
the code, once you wake / unlock / unblock something, don't touch it
again.

kern/src/alarm.c

index 68936bc..0d24522 100644 (file)
@@ -105,7 +105,9 @@ static void wake_awaiter(struct alarm_waiter *waiter)
                sleeper = __up_sem(&waiter->sem);
                if (sleeper)
                        kthread_runnable(sleeper);
                sleeper = __up_sem(&waiter->sem);
                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 +126,9 @@ void trigger_tchain(struct timer_chain *tchain)
                if (i->wake_up_time <= now) {
                        changed_list = TRUE;
                        TAILQ_REMOVE(&tchain->waiters, i, next);
                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). */
                        wake_awaiter(i);
                } else {
                        break;
                        wake_awaiter(i);
                } else {
                        break;