同期データ転送とは異なり、ドライバは非同期要求の完了を待機しません。代わりに、ドライバはその要求をキューに追加します。キューの先頭は、現在の転送である場合があります。キューの先頭はまた、Example 16–5 に示すように、アクティブな要求を保持するための状態構造体の別のフィールドである場合もあります。
キューが最初に空である場合は、ハードウェアがビジー状態ではないため、strategy(9E) は復帰する前に転送を開始します。それ以外の場合、空でないキューで転送が完了すると、割り込みルーチンは新しい転送を開始します。Example 16–5 では、新しい転送を開始するかどうかの判定を便宜上、別のルーチンで行なっています。
ドライバは、buf(9S) 構造体の av_forw メンバーと av_back メンバーを使用して転送要求のリストを管理できます。1 つのポインタを使用して片方向リンクリストを管理することも、両方のポインタを一緒に使用して両方向リンクリストを構築することもできます。デバイスのハードウェア仕様によって、デバイスのパフォーマンスを最適化するために (ポリシーの挿入などの) どのタイプのリスト管理を使用するかが指定されます。転送リストはデバイスごとのリストであるため、このリストの先頭と最後尾は状態構造体に格納されます。
次の例は、転送リストなどのドライバの共有データにアクセスできる複数のスレッドを示しています。共有データを識別し、mutex を使用してそのデータを保護する必要があります。mutex のロックの詳細については、Chapter 3, Multithreadingを参照してください。
使用例 16-5 ブロックドライバに対するデータ転送要求のキューへの登録static int xxstrategy(struct buf *bp) { struct xxstate *xsp; minor_t instance; instance = getminor(bp->b_edev); xsp = ddi_get_soft_state(statep, instance); /* ... */ /* validate transfer request */ /* ... */ /* * Add the request to the end of the queue. Depending on the device, a sorting * algorithm, such as disksort(9F) can be used if it improves the * performance of the device. */ mutex_enter(&xsp->mu); bp->av_forw = NULL; if (xsp->list_head) { /* Non-empty transfer list */ xsp->list_tail->av_forw = bp; xsp->list_tail = bp; } else { /* Empty Transfer list */ xsp->list_head = bp; xsp->list_tail = bp; } mutex_exit(&xsp->mu); /* Start the transfer if possible */ (void) xxstart((caddr_t)xsp); return (0); }