With EARLY_AP_STARTUP enabled, we are seeing crashes in softclock_call_cc()

during bootup. Debugging information shows that softclock_call_cc() is
trying to execute the vt_consdev.vd_timer callout, and the callout
structure contains a NULL c_func.

This appears to be due to a race between vt_upgrade() running
callout_reset() and vt_resume_flush_timer() calling callout_schedule().

Fix the race by ensuring that vd_timer_armed is always set before
attempting to (re)schedule the callout.

Discussed with:	emaste
MFC after:	2 weeks
Sponsored by:	Netflix
Differential Revision:	https://reviews.freebsd.org/D9828
This commit is contained in:
Jonathan T. Looney 2017-06-08 20:47:18 +00:00
parent dc6a41b936
commit dd776f4593

View file

@ -2610,10 +2610,17 @@ vt_upgrade(struct vt_device *vd)
/* Init 25 Hz timer. */
callout_init_mtx(&vd->vd_timer, &vd->vd_lock, 0);
/* Start timer when everything ready. */
/*
* Start timer when everything ready.
* Note that the operations here are purposefully ordered.
* We need to ensure vd_timer_armed is non-zero before we set
* the VDF_ASYNC flag. That prevents this function from
* racing with vt_resume_flush_timer() to update the
* callout structure.
*/
atomic_add_acq_int(&vd->vd_timer_armed, 1);
vd->vd_flags |= VDF_ASYNC;
callout_reset(&vd->vd_timer, hz / VT_TIMERFREQ, vt_timer, vd);
vd->vd_timer_armed = 1;
register_handlers = 1;
}