Mac OS Xのカーネル Xnuのメモ書き

WaitQueue


ブロックしたプロセスをつないでおくキュー。
ブロックする要因毎にキューがある。


[WaitQueueの例]
◎スケジューラのWaitQueue
sched_prim.c::wait_queues[]

スケジューラがブロックさせたプロセスが繋がれる。
sched_prim.cからassert_wait()でこのキューに繋ぐ。

配列のインデクスはeventのハッシュ値。たくさんのプロセスが繋がれるのでばらけるようになっている。


◎セマフォのWaitQueue
struct semaphore::wait_queue

セマフォ取得待ちでブロックしたプロセスがつながれる


Linuxなんかも同じでBlockDevice構造体にI/O待ちのWaitQがあったりした。Xnuもそんな感じでブロック要因毎に存在する。


図1 WaitQueueの構造

[関連関数]
wait_queue_assert_wait(wq, event, interruptible, deadline)
カレントプロレスを指定WaitQueueに入れる。
プロセスを止める手順としてはthread_block()の前にこの関数をよんでプロセスをWaitQueueに入れておく。

wait_queue_wakeup_one(wq, event, result)
指定WaitQueueの指定eventのプロセスを1つだけ起動する。

wait_queue_wakeup_all(wq, event, result)
指定WaitQueueの指定eventのプロセスを全て起動する。


[イベントとは]
WaitQueueに繋いだプロセスを後でWakeupする際に、Queue内のどのプロセスを起こすか指定する識別子のようなもの。WaitQueueに入れるときに何らかの値を仕込んでおく。

イベントとはいっても何か既定のdefine値があるわけではない。eventの実態はvoid *でただの値。Wakeupする時に起こしたいプロセスを識別できればなんでもよい。通常はそのプロセスに何か関連するデータのポインタ値(&thread->wake_activeとか)をeventとすることで値をユニークなものにし、プロセスを指定するようにしている。


セマフォなどでは、セマフォ解放時にそのセマフォ待ちでブロックしていた全てのプロセスをWakeupするので、eventとしては固定値(SEMAPHORE_EVENT)を使用している(semaphore_wait_internal()参照)。
セマフォ解放時にwait_queue_wakeup64_all_locked(&semaphore->wait_queue,SEMAPHORE_EVENT,略...) とすることで、当該セマフォのWaitQueue(semaphore->wait_queue)につまれていたセマフォ待ちのプロセスを全て起こしている。


最終更新 2006/05/25 14:32:36 - kztomita
(2006/05/22 23:10:09 作成)
添付ファイル
waitqueue.png - kztomita


最近更新したページ