> 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