编写适用于 Oracle® Solaris 11.2 的设备驱动程序

退出打印视图

更新时间: 2014 年 9 月
 
 

线程同步中的条件变量

条件变量是线程同步的标准形式。这些变量专门用于互斥锁。关联互斥锁可以确保条件的检查是原子操作,并且线程可以基于关联的条件变量阻塞,同时不会忽略对条件的更改或条件已更改的信号。

condvar(9F) 函数包括:

cv_broadcast(9F)

向基于条件变量等待的所有线程发出信号。

cv_destroy(9F)

销毁条件变量。

cv_init(9F)

初始化条件变量。

cv_signal(9F)

向基于条件变量等待的一个线程发出信号。

cv_timedwait(9F)

等待条件、超时或信号。请参见Threads Unable to Receive Signals

cv_timedwait_sig(9F)

等待条件或超时。

cv_wait(9F)

等待条件。

cv_wait_sig(9F)

等待条件或在收到信号时返回零。请参见Threads Unable to Receive Signals

初始化条件变量

针对每个条件声明一个 kcondvar_t 类型的条件变量。通常,条件变量是驱动程序定义的数据结构中的一个变量。使用 cv_init(9F) 可初始化每个条件变量。与互斥锁类似,条件变量通常在执行 attach(9E) 时初始化。以下是一个初始化条件变量的典型示例:

cv_init(&xsp->cv, NULL, CV_DRIVER, NULL);

有关条件变量初始化的较完整示例,请参见Chapter 6, Driver Autoconfiguration

等待条件

要使用条件变量,请在等待条件的代码路径中执行以下步骤:

  1. 获取用于保护条件的互斥锁。

  2. 测试条件。

  3. 如果测试结果表明不允许线程继续执行,请使用 cv_wait(9F) 根据条件阻塞当前线程。cv_wait(9F) 函数将在阻塞线程之前释放互斥锁,并在返回之前重新获取互斥锁。从 cv_wait(9F) 返回时,重复该测试。

  4. 测试表明允许线程继续执行后,请将条件设置为其新值。例如,将设备标志设置为繁忙。

  5. 释放互斥锁。

发出条件信号

请在代码路径中执行以下步骤以发出条件信号:

  1. 获取用于保护条件的互斥锁。

  2. 设置条件。

  3. 使用 cv_broadcast(9F) 向阻塞的线程发出信号。

  4. 释放互斥锁。

以下示例使用繁忙标志以及互斥锁和条件变量来强制 read(9E) 例程进行等待,直到设备不再繁忙时为止,然后开始传送。

示例 3-1  使用互斥锁和条件变量
static int
xxread(dev_t dev, struct uio *uiop, cred_t *credp)
{
        struct xxstate *xsp;
        /* ... */
        mutex_enter(&xsp->mu);
        while (xsp->busy)
                cv_wait(&xsp->cv, &xsp->mu);
        xsp->busy = 1;
        mutex_exit(&xsp->mu);
        /* perform the data access */
}

static uint_t
xxintr(caddr_t arg)
{
        struct xxstate *xsp = (struct xxstate *)arg;
        mutex_enter(&xsp->mu);
        xsp->busy = 0;
        cv_broadcast(&xsp->cv);
        mutex_exit(&xsp->mu);
}