Lions' 本読み (89)
#台風そん なエントリ日曜日版です。なかなか体調が回復してないようで着手は夕方近くだったりしてます。明日は体調的に出社できるのかどうなのか。
それは良いとして今回は 14 章の xswap 云々の掘削を。
渡す引数は手続きのコメントに記述があるんですが引用は略。ただ、一番目の引数についてはプロセス構造体配列要素へのポインタとなっていて、これと繋がっているユーザ構造体なデータ領域一式 (データセグメント) がスワップアウト対象となります。テキストセグメントはここではスルーされているのもポイント。
呼び出し元は以下の手続きの以下の箇所です。
- 1906 newproc
- 2024 sched
- 2285 expand
- 4478 xalloc
一番上の newproc 手続きから呼び出された場合のみ ff (free flag?) なる引数に 0 が渡される形になっていますが、これはおそらく coremap に確保されていないので解放することはできない、というのが理由だと思われます。
以下に newproc の関連箇所の一部を引用。
1893 n = rip->p_size; /* p_size 属性はデータセグメントのサイズ */ /* rip は親プロセスのプロセス構造体のポインタ */ 1894 a1 = rip->p_addr; 1896 a2 = malloc(coremap, n); 1902 if(a2 == NULL) { 1903 rip->p_stat = SIDL; /* 親プロセスの状態は SIDL */ 1904 rpp->p_addr = a1; /* データセグメントは親子共有 */ 1905 savu(u.u_ssav); 1906 xswap(rpp, 0, 0); 1907 rpp->p_flag =| SSWAP; 1908 rpp->p_stat = SRUN; 1909 }
確かに上の実装を見るに解放しちゃうと親プロセスにご迷惑がかかります。
逆にそれ以外の場合であれば coremap から領域を確保している、が前提のはずなのでスワップアウトするのであれば領域の解放が必須ですね。
4382 if(ff) 4383 mfree(coremap, os, rp->p_addr);
あと三番目の引数ですが例えば expand 手続きから呼び出されるケイスが良い例なのでしょうか。この手続きはデータセグメントのサイズを拡張する手続きになってます。実装を順に見て行きますと
2273 p = u.u_procp; 2274 u = p->p_size; 2275 p->p_size = newsize; 2276 a1 = p->p_addr;
プロセス構造体のポインタを確保してデータセグメントのサイズを退避して引数で受けとった新たなサイズを設定しています。で、現状のデータセグメントの先頭アドレスを a1 に退避しておいて (一部略してます) 以下
2282 a2 = malloc(coremap, newsize);
別場所に newsize な領域を確保にいってます。成功した場合は退避した a1 から a2 に中身をコピーして a1 を解放して sureg して終了してます (ざっくりですが)。問題は領域確保に失敗した場合の処理です。以下。
2283 if(a2 == NULL) { 2284 savu(u.u_ssav); 2285 xswap(p, 1, n); 2286 p->p_flag =| SSWAP; 2287 swtch(); 2288 /* リターンしない */ 2289 }
xswap 手続きに n を渡してます。これがどーゆーことなのかというと xswap の中で解放する領域サイズを以下なカンジで計算してて
4374 if(os == 0) 4375 os = rp->p_size;
デフォルトだと渡したプロセス構造体オブジェクトの p_size 属性の値になってしまう形になってます。expand から xswap を呼び出す場合、上に引用した通りでスデに新しい領域のサイズが設定されてしまっているので、明示的に拡張前のものを渡してさしあげる必要がある、という事な模様。
だんだん慣れてきたカンジ
なのでエントリを改めて xalloc についても調べてエントリ入れれるよう努力してみます。