UNIX 6th code reading - クロック割り込み

初めての方はこちらを参照 http://d.hatena.ne.jp/takahirox/20101024/1287923014

はじめに

今回は第11章です。クロック割り込みが起きたときの処理を見ていきます。

クロック割り込み時に行われる処理

  • ディスプレイレジスタの更新(PDP11/40ではno op)
  • 時刻・時間に関する処理
    • 時刻を表すレジスタをインクリメント
    • 時間を指定して寝ているプロセスを起こす
    • プロセス優先度の再計算
    • 4秒ごとに実行プロセスを見直し
    • スワッピング処理を1秒に1回行う
    • などなど

callout

calloutはcallo構造体の配列です。

calloは「指定時間後(c_time)に指定した関数(*c_func(c_arg))が実行される」ことを示します。

クロック割り込み時に時間の来たcalloを実行します。

calloutを絵にするとこんな感じです。

calloはc_time順で並びます。つまり実行順で並んでいます(calloを追加するときはtimeout関数を使う。timeout関数はcalloが実行順になるようにcalloutに追加する)。実行されたcalloはcalloutから取り除かれます。

calloのc_timeは絶対値ではなく、一つ前のcalloからの相対値が入ります。

メモ

clock
  • 3725 : 引数の意味は前回のエントリ参照
  • 3734 : クロックの初期化。115の意味はKW11-P/Lのマニュアル参照
  • 3740 : displayはPDP11/40ではno op
  • 3748-3749 : callout配列に何もcalloがなければoutへ飛ぶ。calloutの先頭を調べれば何かしらcalloを持っているかどうかわかる
  • 3750-3753 : c_time>0の中で一番先頭にあるcalloのc_timeをデクリメント
  • 3759-3760 : 割り込まれたプロセスのPSを調べる。プロセッサ優先度が0でなければリターン
  • 3766 : プロセッサ優先度を5に設定し割り込みを抑制
  • 3767-3780 : callout配列中にc_time<=0のcalloが存在すれば
    • 3768-3772 : callout配列中のc_time<=0のcalloに対し、各calloのfunc( arg )を実行
    • 3773-3779 : c_time>0のcalloを前方へシフト(後方にあるcalloがシフトしたcalloと重複するような?)
  • 3788-3791 : 割り込まれたプロセスがユーザーモードで実行されていたら
    • 3789 : u_time(ユーザープロセスがCPUを使用した時間?)をインクリメント
    • 3790-3791 : Lions本参照。今度詳細を追うかも
  • 3792-3793 : 割り込まれたプロセスがカーネルモードで実行されていたら
    • 3793 : s_time(カーネルプロセスがCPUを使用した時間?)をインクリメント
  • 3794 : 実行中のプロセス(割り込まれたプロセス)を取得
  • 3795-3796 : Lions本参照。p_cpuはpriの計算に使用される
  • 3797-3830 : lboltをインクリメント。lboltがHZ(60)以上なら。つまり1秒以上経ったなら。
    • 3798-3799 : 割り込まれたプロセスのプロセッサ優先度が0でなければリターンする
    • 3800 : lboltをHZ(60)マイナスする
    • 3801-3802 : 1970年からの秒数を示すレジスタをインクリメント
    • 3803 : プロセッサ優先度を1に設定。Lions本によると、ここからの処理は少し時間を喰うので割り込み抑制をゆるくするらしい。3759, 3798を見ればわかるように、クロック処理(のうちクリティカルな箇所)は重なって実行されない
    • 3804-3805 : 時間が来たら、起きる時間を指定して寝ているプロセスを起こす
    • 3806-3809 : 4秒ごとに(? クロック割り込み4回ごとに)runrunフラグを立てる(=実行プロセス切り替えの要求)。lboltをwakeup。lboltって?
    • 3810-3819 : 存在する全てのプロセスに対し処理
      • 3812-3813 : p_timeをインクリメント(ただしmax127)。p_timeはプロセスがコアに何秒常駐しているか、もしくは、スワップ領域に何秒追い出されているかを示す
      • 3814-3816 : p_cpuをSCHMAGマイナス(ただしmin0)。p_cpuはpriの計算に使用される
      • 3817-3818 : プロセス優先度が基準値以下になったらpriを再計算
    • 3820-3823 : runinフラグ(スケジューラ再実行要求フラグ)が立っていたらスケジューラ(proc#0)を起こす
    • 3824-3829 : 割り込まれたプロセスがユーザーモードならば
      • 3825 : スタックに積んでおいたr0をu.u_ar0に移す(r0は何を意味する?)
      • 3826-3827 : シグナルが発生していたら処理をする
      • 3828 : 実行中のプロセス優先度を再計算する
timeout

引数で与えられたfunc(arg)がtim/HZ秒後に実行されるようcalloutを調整する。

  • 3855-3858 : callout中のcalloに対する相対値となるようにtimを調整。配列のポインタ(p1)は新しいcalloが追加される場所まで進む
  • 3860-3868 : 新しく追加されるcalloの後方のcalloを一つ後ろへシフト
  • 3869-3871 : 新しいcalloを追加(追加というよりも設定?)

その他メモ

  • toutについて調べる
  • 使用しているクロックの種類によって3797行からの内容が実行されるタイミングが変わるのだけれども問題ないのか?
    • 時刻を示すtimeは大丈夫?
    • 60Hzならば1秒(=60/60), 50MHzならば1.2秒(=60/50)間隔
    • クロック割り込みはプロセッサ優先度によっては抑制されるし、必ず上記感覚で割り込み処理が行われるとも限らない
    • 時刻は別のユニットで管理している? timeはOS内の処理に使うだけ?

終わりに

Lions本読書会#4の予習がなんとか終えられました。

今回はコードメモが中心になってしまったので、もう少しわかりやすい概念図などを読書会後に追加するかもしれません。余裕があればクロックコントローラについても触れるかも?

次回は12章を予定しています。また内容が重くなってきそうな予感です。