main() はカーネルが管理するヒープ領域とシステムプロセス proc[0] の設定を 行った後、newproc() により proc[1] を生成する。 newproc() を呼び出したコンテキスト(proc[0]) は 0 を返すので、
if (newproc()) { /* ... */ } sched();
を実行すると sched() に入る。sched() では実行可能状態(SRAN)だが、 ロードされていないプロセスを探索するが、見つからないので sleep() する。 sleep() により、コンテキスト切り替え swtch() が発生して proc[1] が実行される。 swtch() では newproc() で proc[1] を生成する際に savu により保存した pc, r5 を retu により復帰させることでコンテキストを proc[1] に切り替えている。 また、swtch() からの return 1 にて上記の if (newproc()) の呼び出しから 戻り値 1 でリターンする。
いくつかのアセンブラコードの解析
copyseg は第一引数で指定したセグメントから第二引数で指定したセグメントへ 1 block 分のデータをコピーする。
_copyseg: mov PS,-(sp) ; PS を push (-2) mov UISA0,-(sp) ; UISA0 を push (-4) mov UISA1,-(sp) ; UISA1 を push (-6) mov $30340,PS ; 現モード = カーネル、前モード = ユーザ mov 10(sp),UISA0 ; 第一引数を UISA0 に設定 mov 12(sp),UISA1 ; 第二引数を UISA1 に設定 mov UISD0,-(sp) ; UISD0 を push mov UISD1,-(sp) ; UISD1 を push mov $6,UISD0 ; UISD0 を read/write に設定 mov $6,UISD1 ; UISD1 を read/write に設定 mov r2,-(sp) ; r2 を push clr r0 ; r0 は VA=0(APF=0) 番地を指す mov $8192.,r1 ; r1 は VA=8192(APF=1) 番地を指す mov $32.,r2 ; コピーするカウンタ(1block分) 1: mfpi (r0)+ ; r0(UISD0) からスタックに push mtpi (r1)+ ; スタックから pop して r1(UISD1) へ移動 sob r2,1b ; r2 に設定した回数まで繰り返し mov (sp)+,r2 ; 以下、スタックから pop して元の値を復帰 mov (sp)+,UISD1 mov (sp)+,UISD0 mov (sp)+,UISA1 mov (sp)+,UISA0 mov (sp)+,PS rts pc
clearseg は 0 番地から 32 word を 0 クリアする。 このとき仮想アドレスは UISA0 を通して物理アドレスに変換される。 物理アドレスへの対応は引数で指定した値を UISA0 の PAF に設定することで決定する。
_clearseg: mov PS,-(sp) mov UISA0,-(sp) mov $30340,PS ; 現モード = カーネル、前モード = ユーザ mov 6(sp),UISA0 ; 引数に指定した PAF を UISA0 に設定する mov UISD0,-(sp) mov $6,UISD0 ; 対応する UISD0 は read/write 設定 clr r0 mov $32.,r1 1: clr -(sp) ; 次の mpti がスタックから pop した値を使用するため 0 を先に push しておく mtpi (r0)+ sob r1,1b ; -1 した結果が 0 でなければ 2 word 前に分岐 mov (sp)+,UISD0 mov (sp)+,UISA0 mov (sp)+,PS rts pc
saveu は user 構造体のメンバ ursav[2] にカレントスタックポインタと 環境ポインタ(r5)を保存する。引数は ursav へのポインタを与える。
_savu: bis $340,PS ; プロセッサ優先度を 7(最高) に設定 mov (sp)+,r1 ; リターンアドレスを pop mov (sp),r0 ; 引数で指定した user 構造体のメンバ u_rsav mov sp,(r0)+ ; カレントプロセスのスタックポインタを u_rsav[0] mov r5,(r0)+ ; に保存し、r5 を u_rsav[1] に保存 bic $340,PS ; プロセッサ優先度を 0(最低) に設定 jmp (r1) ; 呼び出し元に戻る
_retu: bis $340,PS ; プロセッサ優先度を 7(最高) に設定 mov (sp)+,r1 ; リターンアドレスを pop mov (sp),KISA6 ; KISA6 を引数で指定した物理アドレスに切り替える mov $_u,r0 ; 構造体 u の先頭アドレスを取得 1: mov (r0)+,sp ; u_rsav[0] からスタックポインタを復帰 mov (r0)+,r5 ; u_rsav[1] から環境ポインタ(r5)を復帰 bic $340,ps ; プロセッサ優先度を 0(最低) に設定 jmp (r1) ; 呼び出し元に戻る