如果使用 cv_wait(9F) 根据某个条件将线程阻塞,但该条件不发生,则该线程将永远等待。要避免这种情况,请使用 cv_timedwait(9F),它取决于执行唤醒的其他线程。cv_timedwait() 采取绝对等待时间作为参数。如果时间已到但未发生事件,则 cv_timedwait() 将返回 -1。如果满足条件,则 cv_timedwait() 将返回一个正值。
cv_timedwait(9F) 要求自上次重新引导系统以来的绝对等待时间(以时钟周期表示)。通过使用 ddi_get_lbolt(9F) 检索当前值可确定该等待时间。驱动程序通常具有的是最大等待秒数或微秒数,因此需要使用 drv_usectohz(9F) 将该值转换为时钟周期,然后与 ddi_get_lbolt(9F) 的值相加。
以下示例说明如何使用 cv_timedwait(9F) 最多等待五秒钟便访问设备,然后向调用方返回 EIO。
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 signaled. */ /* tidy up and exit */ mutex_exit(&xsp->mu); return (EIO); } } xsp->busy = 1; mutex_exit(&xsp->mu);
虽然设备驱动程序写入器通常首选使用 cv_timedwait(9F) 而不是 cv_wait(9F),但是有时选用 cv_wait(9F) 会更好。例如,如果驱动程序基于以下条件等待,则使用 cv_wait(9F) 更合适:
内部驱动程序状态发生变化,在此情况下状态变化可能要求执行一些命令或设置要经过的时间
驱动程序的某些部分必须单线程执行
已在管理可能超时的情况,如 "A" 取决于 "B",同时 "B" 使用 cv_timedwait(9F)