EN JA
SCHEDULER(9)
SCHEDULER(9) FreeBSD Kernel Developer's Manual SCHEDULER(9)

名称

curpriority_cmp, maybe_resched, resetpriority, roundrobin, roundrobin_interval, sched_setup, schedclock, schedcpu, setrunnable, updatepri実行可能なプロセスのラウンドロビンスケジューリングを実行する

書式

#include < sys/param.h>
#include < sys/proc.h>

int
curpriority_cmp( struct proc *p);

void
maybe_resched( struct thread *td);

void
propagate_priority( struct proc *p);

void
resetpriority( struct ksegrp *kg);

void
roundrobin( void *arg);

int
roundrobin_interval( void);

void
sched_setup( void *dummy);

void
schedclock( struct thread *td);

void
schedcpu( void *arg);

void
setrunnable( struct thread *td);

void
updatepri( struct thread *td);

解説

各プロセスは、 struct proc に格納される 3 つの異なった優先順位 (プライオリティ) があります: p_usrpri, p_nativeprip_priority です。

p_usrpri メンバは、プロセスの評価 CPU 時間とナイス (nice) レベルから計算されたプロセスのユーザ優先順位です。

p_nativepri メンバは propagate_priority() によって使用された保存された優先順位です。プロセスがミューテックスを取得するとき、優先順位は p_nativepri に保存されます。ミューテックスを保持している間に、プロセスの優先順位は、ミューテックスでブロックされている他のプロセスとぶつかるかもしれません。プロセスがミューテックスを解放するとき、その優先順位は p_nativepri に保存された優先順位に復旧されます。

p_priority メンバは、プロセスの実際の優先順位であり、例えば、どのような runqueue(9) を実行するかを決定するために使用されます。

curpriority_cmp() 関数は、プロセス p と現在実行しているプロセスのキャッシュされた優先順位を比較します。現在実行しているプロセスにより高い優先順位があるなら、0 未満を値を返します。現在実行しているプロセスにより低い優先順位があるなら、0 より大きい値を返します。現在のプロセスが p と同じ優先順位があるなら、 curpriority_cmp() は 0 を返します。現在実行しているプロセスのキャッシュされた優先順位は、プロセスが、 tsleep(9) から再開 (レジューム) するか、または userret() でユーザランドに返るとき、更新され、プライベート変数 curpriority に格納されます。

maybe_resched() 関数は、現在のスレッドと td の優先順位を比較します。 td に現在のスレッドより高い優先順位があるなら、コンテキストスイッチが必要で、 KEF_NEEDRESCHED が設定されます。

propagate_priority() は、ブロックされているミューテックス p を所有しているプロセスを調べます。そのプロセスの優先順位は、必要なら、 p の優先順位とぶつかります。プロセスが現在実行しているなら、関数は返ります。プロセスが runqueue(9) にあるなら、プロセスは新しい優先順位のために適切な runqueue(9) に移されます。プロセスがミューテックスでブロックされているなら、問題のミューテックスでブロックされプロセスのリストの位置は、新しい優先順位を反映するために更新されます。そして、関数は、ただ遭遇するミューテックスを所有しているプロセスを使用して手順を繰り返します。プロセスの優先順位は、以前に遭遇したプロセスの優先順位ではなく、元のプロセス p の優先順位とぶつかるだけであることに注意してください。

resetpriority() 関数は、 ( kg_user_pri に格納された) ksegrp kg のユーザ優先順位を再計算して、必要なら、グループの各スレッドの再スケジュールを強制するために maybe_resched() を呼び出します。

roundrobin() 関数は sched_quantum の刻 (きざみ) 毎に再スケジュールを強制するために timeout(9) 関数として使用されます。

The roundrobin_interval() 関数は roundrobin() によって引き起こされる再スケジュールの間にクロックの刻の数を単に返します。したがって、すべては sched_quantum の現在の値を返すことで行われます。

sched_setup() 関数は callout 駆動のスケジューラ関数を始めるために呼び出される SYSINIT(9) です。それは、初めて、 roundrobin() と schedcpu() 関数をただ呼び出します。初期の呼び出しの後に、2 つの関数は、個別の関数の完了のときに再びそれらの callout イベントを登録することによってそれら自体を伝搬します。

schedclock() 関数は、現在実行しているスレッドの ksegrp の優先順位を調整するために statclock() によって呼び出されます。それは、グループの評価された CPU 時間を更新して、次に、 resetpriority() を通して優先順位を調整します。

schedcpu() 関数はすべてのプロセスの優先順位を更新します。最初に、それはプロセスがどれくらい長く様々なプロセスの状態になっているかを追跡する統計値を更新します。 2 番目に、CPU の使用のおよそ 90% は 5 * ロードアベレージ (負荷平均) 秒で忘れられるように、現在のプロセスのための評価された CPU 時間を更新します。例えば、ロードアベレージが 2.00 であるなら、プロセスのための評価された CPU 時間の少なくとも 90% はプロセスが最後の 10 秒に持っていた CPU 時間の量に基づくべきです。次に、プロセスの優先順位を再計算して、必要なら、適切な runqueue(9) にそれを移します。 3 番目に ps(1)top(1) のようなユーティリティで使用した %CPU の見積りを更新するので、 CPU の使用の 95% は 60 秒で忘れられます。いったん、すべてのプロセスの優先順位が更新されると、 schedcpu() は、ロードアベレージを含む他の様々な統計値を更新するために vmmeter() を呼び出します。最後に、それ自体が再び hz クロックの刻で実行するようにスケジュールします。

setrunnable() 関数は、実行可能となるようにプロセスの状態を変更するために使用されます。必要なら、プロセスが runqueue(9) に置かれ、スワッパプロセスは、プロセスがスワップアウトされているなら、プロセスをスワップするために起こされ、伝えます。プロセスが schedcpu() の少なくとも 1 つの実行のためにスリープしているなら、 updatepri() が、プロセスの優先順位を調整するために使用されます。

updatepri() 関数は、スリープしているプロセスの優先順位を調整するためにに使用されます。それは、プロセスがスリープしている、それぞれの schedcpu() イベントのためのプロセスの評価された CPU 時間を以前にさかのぼって減少します。最後に、それは、プロセスの優先順位を調整するために resetpriority() を呼び出します。

バグ

curpriority 変数は実際には CPU 毎にあるべきです。さらに、 maybe_resched() は、それぞれの CPU のものと chk の優先順位を比較して、次に、必要なら、再スケジュールを引き起こすために最も低い優先順位があるプロセッサに IPI を送るべきです。

優先順位の伝播は、壊れていて、その結果、デフォルトで無効となっています。 p_nativepri 変数は、プロセスが最初の試みでスリープミューテックスを取得しない場合にだけ更新されます。また、プロセスがこのように 1 つ以上のスリープミューテックスを取得して、優先順位が中間でぶつかるなら、 p_nativepri は上書きされます。

November 3, 2000 FreeBSD