Lions' 本読み (32)

どうも sched な手続きの理解が微妙。63p にある proc 構造体の p_stat 属性と p_flag 属性の意図するナニを理解できてないのが敗因なのかどうなのか。
状態として定義されているのは以下なんですが

0379 /* 状態コード */
0380
0381 /*      null       0       割り当てられていない */
0382 #define SSLEEP     1  /* 高い優先度でスリープ中 */
0383 #define SWAIT      2  /* 低い優先度でスリープ中 */
0384 #define SRUN       3  /* 実行中 */
0385 #define SIDL       4  /* プロセスは生成処理中である */
0386 #define SZOMB      5  /* プロセスは終了処理中である */
0387 #define SSTOP      6  /* プロセスはトレース処理中である */
0388
0389 /* フラグコード */
0390
0391 #define SLOAD      01  /* コア中 */
0392 #define SSYS       02  /* スケジューリングプロセス */
0393 #define SLOCK      04  /* プロセスはスワップされない */
0394 #define SSWAP      010 /* プロセスはスワップアウト中である */
0395 #define STRC       020 /* プロセスはトレースされている */
0396 #define SWTED      040 /* 別のトレースフラグ */

力技で xref でもごもごしてみます。
ちなみに、#0 なスケジューラは最初に以下な初期設定らしい。

1592    proc[0].p_stat = SRUN;
1593    proc[0].p_flag =| SLOAD|SSYS;

次に出てくるのが newproc な手続きでの初期設定で以下。

1861    rpp->p_stat = SRUN;
1862    rpp->p_flag = SLOAD;

あ、これって定数で xref 引くより属性で確認した方が良いのかな。ちなみに空いた proc 配列の要素を探す時には p_stat が NULL な要素を云々してます。
また、newproc 手続きで malloc で領域確保できなくてカレントプロセスをスワップアウトする処理では SIDL になって SRUN になるナニが見れます。

1902    if(a2 == NULL) {
1903            rip->p_stat = SIDL;
1904            rpp->p_addr = a1;
1905            savu(u.u_ssav);
1906            xswap(rpp, 0, 0);
1907            rpp->p_flag =| SSWAP;
1908            rip->p_stat = SRUN;

sched な手続きでは_実行可能状態で最も長い時間スワップアウトされていたプロセス_の探索な条件分岐が以下なのか。

1961    if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 &&
1962        rp->p_time > n) {

p_time が何を表現しているのか、はちょっとタイム。同じ sched 手続きで_安易にコアを見つけようとする_ナニが以下。

1992    if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&
1993        (rp->p_stat == SWAIT || rp->p_stat == SSTOP))

1992 な記述は p_flag 属性 (の末端 3bits) が SLOAD しか上がってない、という事で良いのかな。なんとなく安易に、てのが理解できる条件式ですね。
あるいは_コア中に最も長く存在したプロセス_的な記述が以下なのか。

2007    if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&
2008       (rp->p_stat==SRUN || rp->p_stat==SSLEEP) &&
2009        rp->p_time > n)

ちょっと意味合いが異るのが分かります。
次は sleep 手続きで、p_stat は SWAIT になる模様。

2077            rp->p_stat = SWAIT;

2090 でも同様な記述。
そして setrun では SRUN が設定。

2140   rp->p_stat = SRUN;

次は swtch における_最も優先度の高い実行可能プロセスをサーチする_条件式

2208           if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) {

SRUN で SLOAD じゃない、というナニ。
もう少し頑張ります。p_flag は次回以降なカンジ。exit では状態が以下に変更されている模様。

3243   q->p_stat = SZOMB;

で、親プロセスを見つけて SSTOP な状態なら setrun してますね。ちょい謎。

3250           for(p = &proc[0]; p < &proc[NPROC]; p++)
3251           if(q->p_pid == p->ppid) {
3252                   p->p_ppid = 1;
3253                   if (p->p_stat == SSTOP)
3254                           setrun(p);

このあたり、別途きちんと見たいのですが、SZOMB なナニを始末するのが wait らしい。

3280           if(p->p_stat == SZOMB) {
3281                   u.u_ar0[R0] = p->p_pid;
3282                   bp = bread(swapdev, f=p->p_addr);
3283                   mfree(swapmap, 1, f);
3284                   p->p_stat = NULL;

初期化されてますね。ちなみに wait では p_stat が SSTOP な要素についても云々してますがスルーします。
fork では proc 配列を線形探索して p_stat が NULL のものを云々、な処理をしてます。ここでも無かった場合のナニが気になります。

3328           if(p2->p_stat == NULL)
3329                   goto found;
3330   u.u_error = EAGAIN;
3331   goto out;

次に出てくるのは clock の sched なナニな模様。

3810   for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
3811   if (pp->p_stat) {

これ、348p で記述されている_現存するすべてのプロセスに対して次の処理をする_というあたりのナニなのかなと。
て、次に出てくる以下は何だ。psignal 手続きです。

3973   if(rp->p_stat > PUSER)
3974           rp->p_stat = PUSER;
3975   if(rp->p_stat == SWAIT)
3976           setrun(rp);

PUSER て定義は以下だな。

0160 #define PUSER     100

普通に考えてそうなるはずはないんですがスルー。後は

  • stop 手続きで SSTOP な状態になっている
  • ptrace 手続きで SSTOP な状態のものが処理対象の候補になっている

というカンジ。

sched 手続き

で runout と runin な状態というのが読めるのかどうなのか。そろそろ色々な意味で限界なのでクタバります。