On Fri, Jun 09, 2006 at 04:16:08PM -0400, Bill Sommerfeld wrote:
> On Fri, 2006-06-09 at 15:52, Jonathan Adams wrote:
> 
> > 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);
> 
> this code may already have a race in the absence of *other*
> synchronization to prevent reording like:
> 
>               -------------------------->
>                                               mutex_enter(&obj->mutex)
>                                               set up object for destruction
>                                               mutex_exit(&obj->mutex)
>               <--------------------------
>       mutex_enter(&obj->mutex)
>       ...
>       mutex_exit(&obj->mutex)                 kmem_free(obj);
>       cv_signal(&obj->cv);
> 
> aka "an object cannot synchronize its own destruction."

Of course;  I think my example still stands, though.  For example:

        int dropped_ref = 0;

        mutex_enter(&obj->mutex);
        if (--obj->ref == 0)
                dropped_ref = 1;
        mutex_exit(&obj->mutex);
                ------------------------->
                                                mutex_enter(&global);
                                                obj = obj_lookup_and_remove();
                                                mutex_exit(&global);

                                                mutex_enter(&obj->mutex);
                                                while (obj->ref > 0)
                                                        cv_wait(&obj->cv,
                                                            &obj->mutex);
                                                mutex_exit(&obj->mutex);
                                                kmem_free(obj);
                <-------------------------
        if (dropped_ref)
                cv_signal(&obj->cv);


If the signal was underneath the lock, there wouldn't be a race.

Cheers,
- jonathan


-- 
Jonathan Adams, Solaris Kernel Development

Reply via email to