svn commit: r274493 - head/sys/dev/ath
John Baldwin
jhb at freebsd.org
Fri Nov 14 17:32:21 UTC 2014
On Friday, November 14, 2014 04:26:26 AM Adrian Chadd wrote:
> Author: adrian
> Date: Fri Nov 14 04:26:26 2014
> New Revision: 274493
> URL: https://svnweb.freebsd.org/changeset/base/274493
>
> Log:
> Migrate the callouts from using mutex locks to being mpsafe with
> the locks being held by the callers.
>
> Kill callout_drain() and use callout_stop().
>
> Modified:
> head/sys/dev/ath/if_ath.c
>
> Modified: head/sys/dev/ath/if_ath.c
> ============================================================================
> == --- head/sys/dev/ath/if_ath.c Fri Nov 14 00:25:10 2014 (r274492)
> +++ head/sys/dev/ath/if_ath.c Fri Nov 14 04:26:26 2014 (r274493)
> @@ -669,8 +669,8 @@ ath_attach(u_int16_t devid, struct ath_s
> goto bad;
> }
>
> - callout_init_mtx(&sc->sc_cal_ch, &sc->sc_mtx, 0);
> - callout_init_mtx(&sc->sc_wd_ch, &sc->sc_mtx, 0);
> + callout_init(&sc->sc_cal_ch, 1); /* MPSAFE */
> + callout_init(&sc->sc_wd_ch, 1); /* MPSAFE */
Why did you do this? You probably don't want this. You can use
callout_init_mtx() with callout_stop(), and if you do it closes races
between your callout routine and callout_stop(). If you use callout_init()
instead, then you need to patch your callout routines to now explicitly
check your own private flag after doing ATH_LOCK(). That is, you can
either do:
foo_attach()
{
callout_init_mtx(&sc->timer, &sc->mtx, 0);
}
foo_timeout(void *arg)
{
sc = arg;
mtx_assert(&sc->mtx, MA_OWNED);
/* periodic actions */
callout_schedule() /* or callout_reset */
}
foo_start()
{
mtx_lock(&sc->mtx);
callout_reset(&sc->timer, ...);
}
foo_stop()
{
mtx_lock(&sc->mtx);
callout_stop(&sc->timer);
/* foo_timeout will not execute after this point */
mtx_unlock(&sc->mtx);
}
or you can do this:
foo_attach()
{
callout_init(&sc->timer, CALLOUT_MPSAFE);
}
foo_timeout(void *arg)
{
sc = arg;
mtx_lock(&sc->mtx);
if (sc->stopped) {
mtx_unlock(&sc->mtx);
return;
}
/* periodic actions */
callout_schedule()
mtx_unlock(&sc->mtx);
}
foo_start()
{
mtx_lock(&sc->mtx);
foo->stopped = 0;
callout_reset(&sc->timer, ...);
}
foo_stop()
{
mtx_lock(&sc->mtx);
foo->stopped = 1;
callout_stop(&sc->timer);
/*
* foo_timeout might still execute, but it will see the 'stopped'
* flag and return
*/
mtx_unlock(&sc->mtx);
}
Personally, I find the former (using callout_init_mtx()) a lot simpler to read
and work with. As it is you can now either switch back to using
callout_init_mtx() and undo the changes to ath_calibrate() (but leave all your
other changes in place), or you now need to add a new stopped flag that you
set / clear in the places you do callout_stop() / callout_reset() and add a
new check for the new stopped flag in ath_calibrate().
--
John Baldwin
More information about the svn-src-all
mailing list