Linux Kernel(2.6)の実装に関するメモ書き

排他制御関連


Rev.4を表示中。最新版はこちら

割り込み禁止

cli()で割り込み禁止状態にする。マルチプロセッサ環境においては意味がないので、もう使うことはない。代わりにspin_lock_irqsave()(スピンロックでプロセッサ間で排他制御を行いつつ割り込み禁止)を使用する。

CONFIG_SMP定義の有無によって異なる。

CONFIG_SMP未定義時
cli命令実行するだけ


CONFIG_SMP定義時
定義がない

マルチプロセッサでは割り込み禁止だけでは排他制御はできない。spinlockによるプロセッサ間の排他も必要。このためにspin_lock_irqsave()が用意されており、cli()は意味がなくなったため消された。

2.4では全CPUで割り込みを禁止していた。
(RemoteCPUでは割り込みハンドラ実行を遅延させている)


プロセッサ間の排他制御(スピンロック)


spin_lock()
SpinLock取得
取得できるまでSpin

spin_lock_irqsave()
LocalCPUについてcliで割り込み禁止にしてSpinLock取得

割り込みハンドラからもlockを取ろうとする場合は、DeadLock防止のため、こちらを使用する。

LocalCPUについて割り込み禁止しておかないと通常ContextでSpinLock取得した後、割り込みが発生して同じSpinLockを取ろうとした時、DeadLockする。他のCPUの割り込みは禁止にする必要はない。


セマフォ

lock_kernel()
カーネルセマフォ(kernel_sem)を取得。
down()によりセマフォが取れなければTASK_UNINTERRUPTIBLE状態でSleepする。


プリエンプションの抑止

preempt_disable()
current_thread_info()->preempt_countをインクリメントしてプリエンプションを抑止

プリエンプト処理は例外/割り込みからカーネルモードにもどる時(entry.S::resume_kernel)にTIF_NEED_RESCHEDが立っていたらプロセスを切り替えることでおこなっているが、preempt_countが0でなければプロセス切り替えが発生しないようにしている。

spin_lockxxx()をするとpreempt_disable()も実行され、暗黙でプリエンプションは不可とされる。

最終更新 2006/06/22 17:19:20 - kztomita
(2006/03/27 12:57:59 作成)


リンク
最近更新したページ
検索