Writing Device Drivers

cv_timedwait(9F)

If a thread blocks on a condition with cv_wait(9F), and that condition does not occur, it may wait forever. One way to prevent this is to establish a callback with timeout(9F). This callback sets a flag indicating that the condition did not occur normally, and then unblocks the thread. The notified thread then notices that the condition did not occur and can return an error (such as device broken).

A better solution is to use cv_timedwait(9F). An absolute wait time is passed to cv_timedwait(9F), which returns -1 if the time is reached and the event has not occurred. It returns nonzero otherwise. This saves a lot of work setting up separate timeout(9F) routines and avoids having threads get stuck in the driver.

cv_timedwait(9F) requires an absolute wait time expressed in clock ticks since the system was last rebooted. This can be determined by retrieving the current value with ddi_get_lbolt(9F). The driver usually has a maximum number of seconds or microseconds to wait, so this value is converted to clock ticks with drv_usectohz(9F) and added to the value from ddi_get_lbolt(9F).

Example 4-3 shows how to use cv_timedwait(9F) to wait up to five seconds to access the device before returning EIO to the caller.


Example 4-3 Using cv_timedwait(9F)

	clock_t			cur_ticks, to;
	mutex_enter(&xsp->mu);
	while (xsp->busy) {
			cur_ticks = ddi_get_lbolt();
			to = cur_ticks + drv_usectohz(5000000); /* 5 seconds from now */
			if (cv_timedwait(&xsp->cv, &xsp->mu, to) == -1) {
				/*
				 * The timeout time 'to' was reached without the
			 	 * condition being signalled.
			 	 */
				tidy up and exit
				mutex_exit(&xsp->mu);
				return (EIO);
			}
	}
	xsp->busy = 1;
	mutex_exit(&xsp->mu);