Oracle® Solaris 11.2 デバイスドライバの記述

印刷ビューの終了

更新: 2014 年 9 月
 
 

スレッド同期における条件変数

条件変数はスレッド同期の標準的な形式です。条件変数は mutex と組み合わせて使用するように設計されています。mutex を関連付けて使用することにより、条件を原子的にチェックできることが保証されます。また、条件の変更や、条件が変更されたことのシグナルを取りこぼさずに、関連付けられた条件変数でスレッドをブロックできることも保証されます。

condvar(9F) 関数には次のものがあります。

cv_broadcast(9F)

条件変数で待機しているすべてのスレッドにシグナルを送信します。

cv_destroy(9F)

条件変数を破棄します。

cv_init(9F)

条件変数を初期化します。

cv_signal(9F)

条件変数で待機している 1 つのスレッドにシグナルを送信します。

cv_timedwait(9F)

条件、タイムアウト、またはシグナルを待機します。Threads Unable to Receive Signalsを参照してください。

cv_timedwait_sig(9F)

条件またはタイムアウトを待機します。

cv_wait(9F)

条件を待機します。

cv_wait_sig(9F)

条件を待機します。シグナルを受信した場合は 0 を返します。Threads Unable to Receive Signalsを参照してください。

条件変数の初期化

条件ごとに kcondvar_t 型の条件変数を宣言します。条件変数は通常、ドライバのソフト状態構造体で宣言されます。それぞれの条件変数を初期化するには、cv_init(9F) を使用します。条件変数は通常、mutex と同様に attach(9E) の時点で初期化されます。条件変数の初期化の一般的な例を次に示します。

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

条件変数の初期化のより完全な例については、Chapter 6, Driver Autoconfigurationを参照してください。

条件の待機

条件変数を使用するには、条件を待機するコードパスで次の手順に従います。

  1. 条件をガードしている mutex を取得します。

  2. 条件を評価します。

  3. 評価結果でスレッドの再開が許可されない場合、cv_wait(9F) を使用して、その条件で現在のスレッドをブロックします。cv_wait(9F) 関数はスレッドをブロックする前に mutex を解放し、戻る前に mutex を再取得します。cv_wait(9F) から戻ったら、評価を繰り返します。

  4. 評価によりスレッドの再開が許可されたら、条件を新しい値に設定します。たとえば、デバイスフラグをビジーに設定します。

  5. mutex を解放します。

条件のシグナル送信

条件のシグナルを送信するには、コードパスで次の手順に従います。

  1. 条件をガードしている mutex を取得します。

  2. 条件を設定します。

  3. cv_broadcast(9F) を使用して、ブロックされているスレッドにシグナルを送信します。

  4. mutex を解放します。

次の例では、mutex と条件変数に加えてビジーフラグを使用します。転送を開始する前に、デバイスがビジー状態でなくなるまで read(9E) ルーチンを強制的に待機させます。

使用例 3-1  mutex と条件変数の使用
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);
}