Index: kern_timeout.c =================================================================== --- kern_timeout.c +++ kern_timeout.c @@ -1050,7 +1050,7 @@ */ if (c->c_lock != NULL && !cc_exec_cancel(cc, direct)) cancelled = cc_exec_cancel(cc, direct) = true; - if (cc_exec_waiting(cc, direct)) { + if (cc_exec_waiting(cc, direct) || cc_exec_drain(cc, direct)) { /* * Someone has called callout_drain to kill this * callout. Don't reschedule. @@ -1167,6 +1167,7 @@ struct lock_class *class; int direct, sq_locked, use_lock; int cancelled, not_on_a_list; + int active; if ((flags & CS_DRAIN) != 0) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, c->c_lock, @@ -1238,6 +1239,7 @@ /* * If the callout is running, try to stop it or drain it. */ + active = c->c_flags & CALLOUT_ACTIVE; if (cc_exec_curr(cc, direct) == c) { /* * Succeed we to stop it or not, we must clear the @@ -1362,18 +1364,33 @@ cc_exec_drain(cc, direct) = drain; } CC_UNLOCK(cc); - return ((flags & CS_EXECUTING) != 0); + if (flags & CS_EXECUTING) + return((flags & CS_EXECUTING) != 0); + else + return (0); } CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p", c, c->c_func, c->c_arg); + /* We can't stop it */ + cancelled = 0; if (drain) { cc_exec_drain(cc, direct) = drain; } - KASSERT(!sq_locked, ("sleepqueue chain still locked")); - cancelled = ((flags & CS_EXECUTING) != 0); - } else - cancelled = 1; - + if (flags & CS_EXECUTING) { + /* + * XXXRRS I am not sure why this is here + * a special return for the subr_sleep? + */ + cancelled = ((flags & CS_EXECUTING) != 0); + } + CC_UNLOCK(cc); + return (cancelled); + } else { + if (active) + cancelled = 1; + else + cancelled = -1; + } if (sq_locked) sleepq_release(&cc_exec_waiting(cc, direct)); @@ -1381,7 +1398,7 @@ CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p", c, c->c_func, c->c_arg); CC_UNLOCK(cc); - return (0); + return (cancelled); } c->c_iflags &= ~CALLOUT_PENDING;