ページフォルトハンドラ
9vx上で動作するPlan9プロセスは、ホストOSのプロセスと1対1対応している訳ではない。これはホストOSでpsしてみれば、9vxという1つのプロセスしか見えない(Plan9プロセスは見えない)ことからもわかる。
9vxの内部実装は基本的に「1 CPU = 1スレッド(pthread)」になっている。そして、1つのkproc(カーネルスレッド)が1つのCPUに張りつくという都合、(kprocが生成されるたび、動的にCPU数が増加し)最終的に7 CPUシステムとなる。もちろんここ言うCPUは「仮想」CPUである。cpu0がメイン、cpu1でx11、cpu2でtimer、cpu3〜6でioカーネルスレッドが動作している。/dev/sysstatの出力からも想像がつくが、vxプロセスの実行、システムコール処理、ページフォルトなどの処理はすべてcpu0で実行するようだ。
/dev/sysstatの見方は左から順にcpu id、コンテキストスイッチ回数、割込み回数、システムコール回数、ページフォルト、TLBフォルト、TLBパージ、ロードアベレージ、アイドル時間、割込み処理時間。
% cat /dev/sysstat 0 28603 0 69259 164066 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 3 495 0 0 0 0 0 0 0 0 4 181 0 0 0 0 0 0 0 0 5 8650 0 0 0 0 0 0 0 0 6 5180 0 0 0 0 0 0 0 0
ページフォルト(存在しないメモリへのアクセス)はSIGSEGVとして処理される。SIGSEGVはPlan9 VXカーネルの実行中もしくはPlan9ユーザプロセス(vx32インスタンス)のどちらでも起こり得る。前者は基本的にpanicで、後者だと代替シグナルスタックを使ってvx32_sighandlerを実行する。この関数は以前も軽く触れたが、SIGSEGVの場合はトラップ番号をVXTRAP_PAGEFAULTに設定してvxemu_sighandlerを呼ぶ。その結果、vxproc_runの実行を中断し、faultでページフォルト処理を実行後、(touser内でループになっているので)vxproc_runの実行を再開する。