Thanks for your explanation. There are 2 condvars for the object - as far as I understand should one refcount be enough to make sure there are no waiters left on both, correct?
2015-12-28 15:33 GMT+01:00 Taylor R Campbell <campbell+netbsd-tech-k...@mumble.net>: > Date: Mon, 28 Dec 2015 14:35:14 +0100 > From: Stephan <stephan...@googlemail.com> > > given there is an object with the following > > -an interlock (mutex) > -a condvar(9) > -a "state" variable which can be set to something like state_deleted > > [...] > > How can I safely destroy the condvar and interlock mutex? > > In addition to the state, add a reference count to your objects: > increment and decrement it in the waiter code, and wait for it to > drain to zero in the destroyer code. Changing the state to deleted > tells waiters they need to stop; changing the reference count from > nonzero to zero tells the destroyer that the waiters have all stopped. > The destroyer will not wake until the last waiter notifies it and > releases the lock. > > > /* Waiter: bump reference count, wait, drop reference count. */ > if (port->kp_refcnt == UINT_MAX) { > error = EBUSY; > goto fail; > } > port->kp_refcnt++; > while (!ready(port)) { > error = cv_timedwait_sig(&port->kp_rdcv, &port->kp_interlock, > mstohz(timeout)); > if (error || (port->kp_state == state_deleted)) > break; > } > if (--port->kp_refcnt == 0) > cv_broadcast(&port->kp_rdcv); > > > /* Destroyer: remove from list, mark deleted, wait for waiters to drain. */ > mutex_enter(&port_list_lock); > LIST_REMOVE(port, kp_list); > mutex_exit(&port_list_lock); > > mutex_enter(&port->kp_interlock); > port->kp_state = state_deleted; > cv_broadcast(&port->kp_rdcv); > while (port->kp_refcnt != 0) > cv_wait(&port->kp_rdcv, &port->kp_interlock); > mutex_exit(&port->kp_interlock); > > /* Destroyer now has exclusive reference to port. */ > mutex_destroy(&port->kp_interlock); > cv_destroy(&port->kp_rdcv); > ... > kmem_free(port, sizeof(*port)); > > > (You can use a different condvar to notify the destroyer if you like, > but there's not much benefit to that -- it takes extra space and only > avoids a negligible number of spurious wakeups, which you have to deal > with anyway.)