WaitQueue
Sleep,Blockするプロセスをつないでおくリスト。Sleep要因によってそれぞれWaitQueueがある。WaitQueueにつないだプロセスは、wake_upxxx()でWaitQueueを指定することで、RUNNING状態に戻る。WaitQueueは使わなくてもBlockは可能。
[関連ルーチン]
init_waitqueue_head()
add_wait_queue()
add_wait_queue_exclusive()
DECLARE_WAITQUEUE()
DEFINE_WAIT()
wake_up()
wake_up_all()
wait_on_bit(*word, bit, *action, mode)
wait_on_bit_lock(*word, bit, *action, mode)
wake_up_bit(*word, bit)
[関連ページ]
プロセスのBlockとWakeup
WaitQueueの構造
wait_queue_head_t +-----------+ | lock | wait_queue_t | task_list | ----> +---------+ ----> +---------+ +-----------+ | | | | | func | | | | | | |
[関連ルーチン]
init_waitqueue_head()
WaitQueue(wait_queue_head)を初期化する。
add_wait_queue()
指定WaitQueueにエントリを追加する。
add_wait_queue_exclusive()
指定WaitQueueに排他モード(*1)でエントリを追加する。エントリのflagsにはWQ_FLAG_EXCLUSIVEがセットされる。排他モードのエントリはWakeup時にWakeupする個数を指定できる。
(*1)
排他モードはWakeupするプロセス数を指定したい場合に使う。例えばセマフォでのブロック処理で使われている(__up(),__down())。セマフォを解放して、セマフォ待ちのプロセスをWakeupする際、全ての待ちプロセスをWakeupしても、セマフォはどれか1つのプロセスしか取れず、それ以外のプロセスは結局ブロックしてしまい無駄になってしまう。このため、__down()でブロックする際は排他モードでWaitQueueに積み、__up()でWakeupする際は、wake_up()でプロセスを1つだけWakeupさせている。
DECLARE_WAITQUEUE()
WaitQueueに積むエントリ(wait_queue_t)を初期化する。
DEFINE_WAIT()
WaitQueueに積むエントリ(wait_queue_t)を初期化する。
DECLARE_WAITQUEUE()との違いはWakeupすると、WaitQueueから自動的にエントリが削除される点。Wakeup時のハンドラにautoremove_wake_function()が設定されていて、ここでエントリ悪削除する。
DECLARE_WAITQUEUE()との違いはWakeupすると、WaitQueueから自動的にエントリが削除される点。Wakeup時のハンドラにautoremove_wake_function()が設定されていて、ここでエントリ悪削除する。
wake_up()
指定WaitQueueの全Non ExclusiveプロセスとExclusiveプロセス1つ(*2)をWakeupする。
Wakeupしただけでは、WaitQueueから削除されないので注意(DEFINE_WAIT()でエントリを作った場合は除く)。
(*2) __wake_up_commonを見ると、Exclusiveプロセスを指定数Wakeupしたらループをbreakしているので全てのNon ExclusiveプロセスがWakeupされないように見える。しかし、WaitQueueに積む際、Non Exclusiveプロセスはキューの先頭から、Exclusiveプロセスはキューの末尾から積むようにしているので、Non Exclusiveプロセスはキューの前の方に集まっており全てのNon ExclusiveプロセスがWakeupされている。
Wakeupしただけでは、WaitQueueから削除されないので注意(DEFINE_WAIT()でエントリを作った場合は除く)。
(*2) __wake_up_commonを見ると、Exclusiveプロセスを指定数Wakeupしたらループをbreakしているので全てのNon ExclusiveプロセスがWakeupされないように見える。しかし、WaitQueueに積む際、Non Exclusiveプロセスはキューの先頭から、Exclusiveプロセスはキューの末尾から積むようにしているので、Non Exclusiveプロセスはキューの前の方に集まっており全てのNon ExclusiveプロセスがWakeupされている。
wake_up_all()
指定WaitQueueの全プロセスをWakeupする。
wait_on_bit(*word, bit, *action, mode)
wordが指している領域のbitがクリアされるまでプロセスをブロックさせる。bitが立っていなかった場合は、速やかにリターンする。
ブロック処理はactionで指定される関数で行う。modeはブロック中の割込み可否(TASK_INTERRUPTIBLE/UNINTERRUPTIBLE)を指定する。
起床する時はwake_up_bit()で起こす。
ブロック処理はactionで指定される関数で行う。modeはブロック中の割込み可否(TASK_INTERRUPTIBLE/UNINTERRUPTIBLE)を指定する。
起床する時はwake_up_bit()で起こす。
wait_on_bit()ではWaitQueueを指定しない。Zone毎に汎用WaitQueueのハッシュがあり(zone-> wait_table[ハッシュ値])、bit_waitqueue()でこのハッシュテーブルからWaitQueueを取得している。
wait_on_bit_lock(*word, bit, *action, mode)
wordが指している領域のbitをTest and Setにより取得する。取得できた場合は速やかにリターンするが、取得できなかった場合は、取得できるまでブロックする。
wake_up_bit(*word, bit)
word領域のbitがクリアされるのを待っているプロセスをWakeupする。
bitは事前にクリアしておく必要がある。
bitは事前にクリアしておく必要がある。
[関連ページ]
プロセスのBlockとWakeup