tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: How to destroy a condvar(9) with waiters?



   Date: Mon, 28 Dec 2015 14:35:14 +0100
   From: Stephan <stephanwib%googlemail.com@localhost>

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


Home | Main Index | Thread Index | Old Index