On Fri, Jun 09, 2006 at 03:24:00PM -0400, Peter Memishian wrote:
> 
>  > Whether this is good or bad, this is the official requirement. A quote 
> from 
>  > the condvar(9F):
>  > 
>  >      cv_signal() signals the  condition  and  wakes  one  blocked
>  >      thread.  All  blocked  threads  can  be unblocked by calling
>  >      cv_broadcast(). You  must  acquire  the  mutex  passed  into
>  >      cv_wait() before calling cv_signal() or cv_broadcast().
> 
> Further, cond_signal(3C) states:
> 
>      The cond_broadcast() function unblocks all threads that  are
>      blocked on the condition variable pointed to by cvp.
> 
>      If no threads are blocked on the  condition  variable,  then
>      cond_signal() and cond_broadcast() have no effect.
> 
>      Both functions should be called under the protection of  the
>      same  mutex  that  is used with the condition variable being
>      signaled. Otherwise, the condition variable may be  signaled
>      between the test of the associated condition and blocking in
>      cond_wait(). This can cause an infinite wait.
> 
> ... but that rationale looks bogus to me.  In particular, the thread
> heading into cond_wait() must have already tested the condition under the
> lock and concluded it was false in order to decide to cond_wait().  Since
> any thread changing state that would affect the condition must also be
> holding the lock, there is no way for the state (and thus the outcome of
> the test) to change beween the test and the cond_wait(), and thus any
> cond_signal() sent during that window would end up being spurious anyway.
> 
> Please feel free to prove me wrong :-)

If I remember correctly, the main problems you can run into with signaling
after dropping the lock is that there can be destruction races:

        thread 1                                Thread 2

        mutex_exit(&obj->mutex)
                -------------------------->
                                                mutex_enter(&obj->mutex)
                                                set up object for destruction
                                                mutex_exit(&obj->mutex)
                                                kmem_free(obj);
                <--------------------------
        cv_signal(&obj->cv);

I agree that the argument in cond_signal(3C) is bogus;  the standard states
that "signaling under the lock can make scheduling more deterministic", but
it doesn't require anyone to do so.  See pthread_cond_signal(3C):

     The pthread_cond_signal() or pthread_cond_broadcast()  func-
     tions  may be called by a thread whether or not it currently
     owns the mutex that threads calling  pthread_cond_wait()  or
     pthread_cond_timedwait()  have associated with the condition
     variable  during  their  waits;  however,   if   predictable
     scheduling  behavior  is required, then that mutex is locked
     by   the    thread    calling    pthread_cond_signal()    or
     pthread_cond_broadcast().

Cheers,
- jonathan

-- 
Jonathan Adams, Solaris Kernel Development

Reply via email to