spin lock による排他制御

spin lock は単純な排他制御機能です。排他制御をしたい一連の処理の前後に spin_lock*(), spin_unlock*() 関数を置いて使います。排他制御をしている時間が短い場合、効率的に使用できます。排他制御を獲得するまで状態変数を操作し続け(特殊な読み書き手順を続け)ます。排他制御時間が長いか、頻度が高い場合、状態変数を操作する時間が長くなり、本来行うべき演算のための時間を失います。使い分けと詳細なドキュメントは Documentation/locking/spinlocks.txt, Documentation/DocBook/kernel-locking/index.html にあります。

spin lock の種類

spin lock には次のような種類があります。排他制御を必要とするコンテキストに応じて使い分けてください。/Documentation/DocBook/kernel-locking/cheatsheet.html に早見表があります。

lockunlockハードウエア割り込み[*3]softirq[*3]プリエンプション[*3]
spin_lock_irqsave()spin_unlock_irqrestore()退避 - 復旧
禁止 - 許可
禁止 - 許可[*1]禁止 - 許可[*2]
spin_lock_irq()spin_unlock_irq()禁止 - 許可禁止 - 許可[*1]禁止 - 許可[*2]
spin_lock()spin_unlock()そのままそのまま禁止 - 許可[*2]
spin_lock_bh()spin_unlock_bh()そのまま禁止 - 許可[*2]禁止 - 許可[*2]

[*1] ハードウエア割り込み禁止に連動しています。

[*2] カウンタを up/down しています。カウンタが初期値(多くの場合 0)より大きければ禁止、初期値に一致すれば許可となります。

[*3] {割り込み|softirq|プリエンプション} の禁止/許可はローカル CPU (spin lock 関数を実行した CPU)が対象です。

どのコンテキストでも使える spin_lock_irqsave() と spin_unlock_irqrestore()

数多く有る spin lock のうちどのコンテキストでも使える spin_lock_irqsave(), spin_unlock_irqrestore() を主に使っています。spin_lock_irqsave() spin_unlock_irqrestore() は状況によってはしなくても良い割り込み許可フラグの保存・復帰を無条件にします。無駄な処理かもしれません。それでも、実行時間の無駄よりは、spin_lock_irqsave(), spin_unlock_irqrestore() を呼び出した元のコンテキストが何か留意しながらコードを書くより安全な方法を選んでいます。

spin_lock_irqsave()

spin_lock_irqsave() を呼び出し、関数から戻ってくると次の様な状態になっています。

spin_unlock_restore()

spin_unlock_irqrestore() を呼び出し、関数から戻ってくると次の様な状態になっています。

spin_lock_irqsave() と spin_unlock_irqrestore() の注意点

spin_lock_irqsave(), spin_unlock_irqrestore() の注意点を列挙します。


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS