Date: Thu, 4 Jul 2002 11:53:26 -0500 From: Jonathan Lemon <jlemon@flugsvamp.com> To: Bruce Evans <bde@zeta.org.au> Cc: Jonathan Lemon <jlemon@flugsvamp.com>, bsddiy@yahoo.com, current@freebsd.org Subject: Re: Timeout and SMP race Message-ID: <20020704115326.R1020@prism.flugsvamp.com> In-Reply-To: <20020705022155.L475-100000@gamplex.bde.org> References: <200207041530.g64FUwE48481@prism.flugsvamp.com> <20020705022155.L475-100000@gamplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Jul 05, 2002 at 02:38:08AM +1000, Bruce Evans wrote: > On Thu, 4 Jul 2002, Jonathan Lemon wrote: > > > In article <local.mail.freebsd-current/20020704132044.7338.qmail@web20909.mail.yahoo.com> you write: > > >in RELENG_4, when one calls callout_stop() (not nested in softclock execute > > >path > > >, I am not talking about this case), after it returns, he can believe that the > > >callout is truely stopped, however in CURRENT, this assumption is false, now we > > > > > >must care if callout_stop() truely stopped the callout when it returned, this > > >is all difference I see, we bring in this race which not exists in RELENG_4, > > >see what hacking code put in kern_condvar.c and kern_synch.c in CURRENT source, > > > > I don't believe this is true. There is a corresponding race in -stable, > > where the spl() level is dropped before performing the callout, thus > > allowing either a call to callout_stop() or callout_reset() to come in > > immediately before the callout is actually made. > > I think Giant locking everything prevents problems in RELENG_4, at least > when callout_stop() is called in process context (if it is called in > interrupt context then it could easily be interrupting a callout even in > the UP case). In the network stack at least, callout_stop() is called in interrupt context, so this case actually happens, and has to be handled. > The race window extends from when the ipl or lock is dropped across the > whole callout until the ipl or lock is regained. (The ipl is only dropped > to splstatclock(); this prevents interruption by timeouts but not by > other interrupts. In -current there is nothing much to prevent softclock() > itself being called concurrently, but in theory softclock()'s internal > locking should prevent problems.) > > > The callout function is responsible for checking to see if it has lost > > the race, and perform the appropriate action. This is done with the > > CALLOUT_PENDING and CALLOUT_ACTIVE flags: > > > > > s = splnet(); > > if (callout_pending(tp->tt_delack) || !callout_active(tp->tt_delack)) { > > splx(s); > > return; > > } > > callout_deactivate(tp->tt_delack); > > I think David is objecting to this complicating all callers that do the > check and breaking all that don't. The callers in kern_synch.c and > kern_condvar.c have an mi_switch() and other complications to handle > this sinc they can't just return. I believe I had this conversation with Justin Gibbs earlier; he told me that the callout consumers (network, cam) had to be aware of the race and handle this if it matters. I don't particularly like complicating the callout handlers as illustrated above, though, so if a better scheme is possible, that would be nice. I originally wanted something equivalent to an atomic spl downgrade (splhigh -> splnet), so the timeout code could obtain the target ipl/lock that the callout handler wanted before dropping splhigh(), but was told this would unnecessarily complicate things. > > If 'CALLOUT_PENDING' is set, then we lost a race with callout_reset(), > > and should not perform the callout. If 'CALLOUT_ACTIVE' is clear, then > > we lost a race with callout_stop(). > > > > Either way, on both -current and -stable, you cannot assume that the > > timer callback is completely gone immediately after calling callout_stop(). > > tsleep() seems to assume this in RELENG_4. tsleep() is only called from process context, and appears to be safe because p->wchan has already been cleared by a previous call to unsleep(). The races only matter if you actually care about them. -- Jonathan To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020704115326.R1020>