kernel - Fix race in callout_stop_sync()
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 20 Jan 2012 18:23:06 +0000 (10:23 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 20 Jan 2012 18:23:06 +0000 (10:23 -0800)
* When callout_stop_sync() races a timeout callback which re-arms the
  callout it can hit an assertion.  The assertion is incorrect.  Instead
  of asserting we have to loop up and try again.

sys/kern/kern_timeout.c

index 8daf221..6f52491 100644 (file)
@@ -499,7 +499,7 @@ callout_stop_sync(struct callout *c)
 {
        softclock_pcpu_t sc;
 
-       if (c->c_flags & CALLOUT_DID_INIT) {
+       while (c->c_flags & CALLOUT_DID_INIT) {
                callout_stop(c);
 #ifdef SMP
                if (c->c_gd) {
@@ -516,7 +516,9 @@ callout_stop_sync(struct callout *c)
                                tsleep(&sc->running, 0, "crace", 1);
                }
 #endif
-               KKASSERT((c->c_flags & (CALLOUT_PENDING|CALLOUT_ACTIVE)) == 0);
+               if ((c->c_flags & (CALLOUT_PENDING | CALLOUT_ACTIVE)) == 0)
+                       break;
+               kprintf("Warning: %s: callout race\n", curthread->td_comm);
        }
 }