> 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.

But the above code is wrong for a more fundamental reason: it's never OK
to access fields of a structure after you've dropped your reference to it.
(And indeed, adding mutex_enter()/mutex_exit() around the cv_signal()
would do nothing to improve the correctness of the above code ;-)

I assert that from a correctness standpoint, it never matters if you hold
the lock while doing a cv_signal() or cv_broadcast().  I agree that there
may be performance issues, but it would be nice to see some hard data
since (as previously covered) I can see advantages to not holding the lock
as well.

-- 
meem

Reply via email to