Question about cv_signal(9) (never mind)
John Baldwin
jhb at FreeBSD.org
Mon Jun 14 19:02:48 GMT 2004
On Monday 14 June 2004 02:53 pm, John Polstra wrote:
> On 14-Jun-2004 John Baldwin wrote:
> > On Saturday 12 June 2004 08:12 pm, John Polstra wrote:
> >> On 12-Jun-2004 John Polstra wrote:
> >> > [Why does a caller to cv_signal(9) have to hold the associated mutex?]
> >>
> >> Never mind. I understand now. It allows the implementation to
> >> avoid doing any locking internally. That seems perfectly
> >> reasonable, and I withdraw my question.
> >
> > To be honest, it's also largely there to try to keep people from writing
> > code that can lose wakeups. The count optimization came later. If the
> > optimization of dropping the lock is more important and we think that
> > people really won't make the mistake of not using locks when they should
> > to avoid the lost wakeups then we could drop the count optimization and
> > allow cv_signal() to not require the lock perhaps.
>
> It seems to me that some sort of mutual exclusion is needed when
> manipulating the cv structure and the associated sleep queue. If
> the user doesn't provide it then the implementation will have to
> provide it internally. So unless there is a cheaper kind of mutual
> exclusion that can be used inside the implementation, your current
> solution seems the best to me.
>
> I had never thought through the need for some kind of mutual
> exclusion, and the papers that describe the optimization I mentioned
> simply ignore it and its performance implications.
Well, the sleep queue is not protected by the data lock, it is protected by a
spin lock associated with the hash table bucket that the condition variable's
address hashes to. Specifically, note that sleepq_lookup() locks the
associated spin lock and returns with it locked where as sleepq_release(),
etc. unlocks the spin lock. The sleepq is locked inside sleepq_signal() and
sleepq_wakeup(). If you don't implement the count optimization, then
cv_signal() just calls sleepq_signal() and cv_wakeup() just calls
sleepq_wakeup() with no need for any locking of the cv structure itself. See
rev 1.47 of kern_condvar.c and the current implementations of wakeup() and
wakeup_one() for example. The other member of struct condvar is static in
that it is only set during initialization and doesn't need any locking.
--
John Baldwin <jhb at FreeBSD.org> <>< http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve" = http://www.FreeBSD.org
More information about the freebsd-smp
mailing list