tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kernel condvars: how to use?



> Date: Mon, 11 Dec 2017 11:13:16 -0500 (EST)
> From: Mouse <mouse%Rodents-Montreal.ORG@localhost>
> 
> > If read does
> 
> > 	while (sc->sc_foo < sc->sc_bar)
> > 		cv_wait(&sc->sc_cv, &sc->sc_lock);
> 
> > then whoever changes sc_foo or sc_bar might test whether they changed
> > from sc->sc_foo < sc->sc_bar to !(sc->sc_foo < sc->sc_bar) before
> > they cv_broadcast.
> 
> ...then you have the same test in two places, leaving them vulnerable
> to one but not the other being changed.  (Of course, only some changes
> will break functionality, but that's a separate issue.)
> 
> Furthermore, they and LPT_RF_WAITING are testing/describing different
> things: "is anyone actually waiting?" versus "if anyone does happen to
> be waiting, could this make a difference?".

Correct.

Your responsibility as a user of condvar(9) is to make sure that if
you ever make a difference for a waiter, then you wake.  That's why I
advise either issuing wakeups for any changes to sc_foo/bar, or if
you're going to conditionalize them to avoid unnecessary wakeups, then
conditionalizing them only on changes to sc_foo/bar that transition
from a state that blocks waiters to a state that doesn't block
waiters.

On the other side, condvar(9) handles skipping some potentially
expensive logic if there isn't actually anyone waiting.  You shouldn't
worry about testing for the presence of waiters unless you actually
observe a performance impact.  That's why I advise _against_ using
LPT_RF_WAITING.

(One exception: It's OK to KASSERT(!cv_has_waiters(cv)) in cases when
you need to be sure there are no waiters.  Aside: Maybe cv_destroy
should do this itself anyway.)

> > In any case, neither __insn_barrier nor volatile is sufficient in the
> > multiprocessor model,
> 
> Not sufficient, true, but necessary (though, depending on the
> implementations of things like C and mutexes, possibly implicitly
> provided).

mutex_enter/exit guarantees the appropriate memory barriers to make
the mutual exclusion sections for a single lock object appear globally
ordered on all CPUs, in thread context and in interrupt context.


Home | Main Index | Thread Index | Old Index