Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_timeout.c
Show First 20 Lines • Show All 1,149 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
callout_schedule(struct callout *c, int to_ticks) | callout_schedule(struct callout *c, int to_ticks) | ||||
{ | { | ||||
return callout_reset_on(c, to_ticks, c->c_func, c->c_arg, c->c_cpu); | return callout_reset_on(c, to_ticks, c->c_func, c->c_arg, c->c_cpu); | ||||
} | } | ||||
int | int | ||||
_callout_stop_safe(struct callout *c, int safe, void (*drain)(void *)) | _callout_stop_safe(struct callout *c, int flags, void (*drain)(void *)) | ||||
{ | { | ||||
struct callout_cpu *cc, *old_cc; | struct callout_cpu *cc, *old_cc; | ||||
struct lock_class *class; | struct lock_class *class; | ||||
int direct, sq_locked, use_lock; | int direct, sq_locked, use_lock; | ||||
int not_on_a_list; | int not_on_a_list; | ||||
if (safe) | if ((flags & CS_DRAIN) != 0) | ||||
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, c->c_lock, | WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, c->c_lock, | ||||
"calling %s", __func__); | "calling %s", __func__); | ||||
/* | /* | ||||
* Some old subsystems don't hold Giant while running a callout_stop(), | * Some old subsystems don't hold Giant while running a callout_stop(), | ||||
* so just discard this check for the moment. | * so just discard this check for the moment. | ||||
*/ | */ | ||||
if (!safe && c->c_lock != NULL) { | if ((flags & CS_DRAIN) == 0 && c->c_lock != NULL) { | ||||
if (c->c_lock == &Giant.lock_object) | if (c->c_lock == &Giant.lock_object) | ||||
use_lock = mtx_owned(&Giant); | use_lock = mtx_owned(&Giant); | ||||
else { | else { | ||||
use_lock = 1; | use_lock = 1; | ||||
class = LOCK_CLASS(c->c_lock); | class = LOCK_CLASS(c->c_lock); | ||||
class->lc_assert(c->c_lock, LA_XLOCKED); | class->lc_assert(c->c_lock, LA_XLOCKED); | ||||
} | } | ||||
} else | } else | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | if (cc_exec_curr(cc, direct) != c) { | ||||
CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p", | CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p", | ||||
c, c->c_func, c->c_arg); | c, c->c_func, c->c_arg); | ||||
CC_UNLOCK(cc); | CC_UNLOCK(cc); | ||||
if (sq_locked) | if (sq_locked) | ||||
sleepq_release(&cc_exec_waiting(cc, direct)); | sleepq_release(&cc_exec_waiting(cc, direct)); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (safe) { | if ((flags & CS_DRAIN) != 0) { | ||||
/* | /* | ||||
* The current callout is running (or just | * The current callout is running (or just | ||||
* about to run) and blocking is allowed, so | * about to run) and blocking is allowed, so | ||||
* just wait for the current invocation to | * just wait for the current invocation to | ||||
* finish. | * finish. | ||||
*/ | */ | ||||
while (cc_exec_curr(cc, direct) == c) { | while (cc_exec_curr(cc, direct) == c) { | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | #ifdef SMP | ||||
cc_migration_arg(cc, direct) = NULL; | cc_migration_arg(cc, direct) = NULL; | ||||
#endif | #endif | ||||
CTR3(KTR_CALLOUT, "postponing stop %p func %p arg %p", | CTR3(KTR_CALLOUT, "postponing stop %p func %p arg %p", | ||||
c, c->c_func, c->c_arg); | c, c->c_func, c->c_arg); | ||||
if (drain) { | if (drain) { | ||||
cc_exec_drain(cc, direct) = drain; | cc_exec_drain(cc, direct) = drain; | ||||
} | } | ||||
CC_UNLOCK(cc); | CC_UNLOCK(cc); | ||||
return (0); | return ((flags & CS_MIGRBLOCK) != 0); | ||||
} | } | ||||
CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p", | CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p", | ||||
c, c->c_func, c->c_arg); | c, c->c_func, c->c_arg); | ||||
if (drain) { | if (drain) { | ||||
cc_exec_drain(cc, direct) = drain; | cc_exec_drain(cc, direct) = drain; | ||||
} | } | ||||
CC_UNLOCK(cc); | CC_UNLOCK(cc); | ||||
KASSERT(!sq_locked, ("sleepqueue chain still locked")); | KASSERT(!sq_locked, ("sleepqueue chain still locked")); | ||||
▲ Show 20 Lines • Show All 236 Lines • Show Last 20 Lines |