プリエンプション
Rev.3を表示中。最新版はこちら。
CONFIG_PREEMPTを定義しておくと、プロセスコンテキストでカーネル内のコードを実行している時でも他のプロセスに切りかわることができる。CONFIG_PREEMPTがなければLinux 2.4と同様に明示的に自分からSleepしてCPUを手放さない限り切り替わらない。
通常Unixはユーザモードのみプリエンプティブでカーネルモードではノンプリエンプティブだが、CONFIG_PREEMPTを有効にするとカーネルモードでもプリエンプティブになる。
preempt_disable()
プリエンプションを禁止にする。
inc_preempt_count()でthread_info.preempt_countをインクリメントしている。
preempt_enable()
プリエンプションを許可する。
プリエンプションが必要であればついでにプリエンプションも行なわれる。
プリエンプションが必要であればついでにプリエンプションも行なわれる。
dec_preempt_count()でpreemption_countをデクリメント後、preempt_check_resched()を呼んでプリエンプションが必要なら(TIF_NEED_RESCHED立っていたら)プリエンプションを実行している。
preempt_schedule() - preempt_enable()から呼ばれる
preempt_countが0でなければ(PreemptDisable中。割り込み中)何もしない
current_thread_info()->preempt_count = PREEMPT_ACTIVE;
Preemptにより切替えられたことを示すフラグを設定。
これを設定しておくとschedule()で切替えてもプロセスはRunqueueに残される。
schedule() - Preempt
current_thread_info()->preempt_count = 0;
フラグを元に戻す
preempt_schedule_irq() - 割り込みコンテキストからプリエンプトする場合こちらが使用される
(割り込み/例外からカーネルモードにもどる際、呼ばれる)
entry.S::resume_kernel: - 割り込みや例外からカーネルモードに戻る時に呼ばれる
preempt_countが0でなければPreemptDisable中なので
resotre_allを呼んで割り込み/例外から復帰。(復帰先はカーネルモード)
TIF_NEED_RESCHEDが立っていたらpreempt_schedule_irq()をコールしてPreempt
thread_info.preempt_count
bits 0-7 are the preemption count (max preemption depth: 256)
bits 8-15 are the softirq count (max # of softirqs: 256)
bits 16-23 are the hardirq count (max # of hardirqs: 256)
( bit 26 is the PREEMPT_ACTIVE flag. )
PREEMPT_MASK: 0x000000ff
SOFTIRQ_MASK: 0x0000ff00
HARDIRQ_MASK: 0x00ff0000
bits 8-15 are the softirq count (max # of softirqs: 256)
bits 16-23 are the hardirq count (max # of hardirqs: 256)
( bit 26 is the PREEMPT_ACTIVE flag. )
PREEMPT_MASK: 0x000000ff
SOFTIRQ_MASK: 0x0000ff00
HARDIRQ_MASK: 0x00ff0000
H/W割り込み処理時
S/W割り込み処理時
do_IRQ()でH/W割り込みの処理を開始するときにirq_enter()でHARDIRQ_MASKの部分が加算される。
S/W割り込み処理時
__do_softirq()でS/W割り込みの処理を開始するときにlocal_bh_disable()でSOFTIRQ_MASKの部分が加算される。
in_interrupt()で割り込み処理中かチェックするときも
current_thread_info()->preempt_countの
(HARDIRQ_MASK | SOFTIRQ_MASK)部分をチェックしている。
current_thread_info()->preempt_countの
(HARDIRQ_MASK | SOFTIRQ_MASK)部分をチェックしている。