From: Matthew Dillon Date: Tue, 8 Nov 2011 08:29:51 +0000 (-0800) Subject: kernel - Add callout_stop_sync() X-Git-Tag: v3.0.0~706 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/c5b9d2a5dc3047fc20e0a12e1a1de7a4aa424db2 kernel - Add callout_stop_sync() * Add a synchronous version of callout_stop() which ensure that the callout function has completed operation (if it was running) before returning. --- diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 5ca8f2df73..8eed720f19 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -399,6 +399,9 @@ callout_reset(struct callout *c, int to_ticks, void (*ftn)(void *), * * WARNING! This function can return while it's c_func is still running * in the callout thread, a secondary check may be needed. + * Use callout_stop_sync() to wait for any callout function to + * complete before returning, being sure that no deadlock is + * possible if you do. */ int callout_stop(struct callout *c) @@ -487,6 +490,30 @@ callout_stop(struct callout *c) return (1); } +/* + * Issue a callout_stop() and ensure that any callout race completes + * before returning. Does NOT de-initialized the callout. + */ +void +callout_stop_sync(struct callout *c) +{ + softclock_pcpu_t sc; + + if (c->c_flags & CALLOUT_DID_INIT) { + callout_stop(c); +#ifdef SMP + sc = &softclock_pcpu_ary[c->c_gd->gd_cpuid]; +#else + sc = &softclock_pcpu_ary[0]; +#endif + if (sc->running == c) { + while (sc->running == c) + tsleep(&sc->running, 0, "crace", 1); + } + KKASSERT((c->c_flags & (CALLOUT_PENDING|CALLOUT_ACTIVE)) == 0); + } +} + /* * Terminate a callout * diff --git a/sys/sys/callout.h b/sys/sys/callout.h index b279a5fede..a74d1ca9f4 100644 --- a/sys/sys/callout.h +++ b/sys/sys/callout.h @@ -94,6 +94,7 @@ void callout_init (struct callout *); void callout_init_mp (struct callout *); void callout_reset (struct callout *, int, void (*)(void *), void *); int callout_stop (struct callout *); +void callout_stop_sync (struct callout *); void callout_terminate (struct callout *); #endif