排他制御関連
Rev.18を表示中。最新版はこちら。
BSD family 互換の割り込み禁止関数 [Legacy]
osfmk/kern/spl.h- splhigh() 全H/W割り込み禁止
- splsched() スケジューラのS/W割り込み禁止
- splclock() S/Wタイマ割り込み禁止
- splx(x) 指定割り込みレベルに設定
- spllo() 割り込み許可状態にする
ユニプロセッサのシステムでプロセスコンテキストと割り込みコンテキストの間で排他制御をするのに使われていた。
splhigh,sched,clock()は本当は各IPL(Ineterrupt Priority Level)に応じた割り込みを禁止するものだが、xnuではH/W割り込みを禁止にしているだけでどの関数も同じレベルとなる。これらは、ml_set_interrupts_enabled(FALSE)でH/W割り込みを禁止にしている(i386だとcliインストラクションで割り込み禁止)。
これらの関数は割り込みを禁止するだけなので、マルチプロセッサ環境においては役に立たない。Xnuのコード上には残っているが、新たなコードでは使わないこと(というか使っても意味がない)。排他制御を行う場合はSpinlockなどを使用すること。
splhigh,sched,clock()は本当は各IPL(Ineterrupt Priority Level)に応じた割り込みを禁止するものだが、xnuではH/W割り込みを禁止にしているだけでどの関数も同じレベルとなる。これらは、ml_set_interrupts_enabled(FALSE)でH/W割り込みを禁止にしている(i386だとcliインストラクションで割り込み禁止)。
これらの関数は割り込みを禁止するだけなので、マルチプロセッサ環境においては役に立たない。Xnuのコード上には残っているが、新たなコードでは使わないこと(というか使っても意味がない)。排他制御を行う場合はSpinlockなどを使用すること。
スピンロック
スピンロックはロックが取れるまでループ(スピン)を繰りかえして、プロセッサ間で排他制御を行なう。ロックが取られていた場合は、ロックが取れるまでループする。コンテキストがブロックしないのでCPU時間を無駄にしがち。割り込みハンドラの中などブロック不可能な時以外はmutexを使用するのがよい。kern/simple_lock.h
simple_lock()
spin lock。ロックが取れるまでループする。
マクロで実体はusimple_lock()
usimple_lock()はhw_lock_to()でロックを取ろうとする。ロックがとれたらsimple_unlock()でロック解除するまでPreemption禁止になる。これは、ロックを取っている間に別プロセスに切り替わってしまうと、新プロセスが同じロックを取ろうとした場合にデッドロックが発生するため。また、同じ理由でロックを取っている最中はプロセスをブロックさせる処理はしてはいけない。
割り込み処理の中からもロックを取る処理がある場合は、割り込みも禁止にしないとデッドロックが発生するが、これは個別にml_set_interrupts_enabled(FALSE)してやる必要がある?