(第38回)割り込みに優先度をつける(後編)

2009/01/26

あなたは 人目のお客様です.

いよいよ,割り込みに優先度づけをすることで,KOZOSを完全にリアルタイムOS化する. まあ僕的に「完全なリアルタイムOS」ってなものがどんなものかまだいまいちよく 理解できていないところがあるのだが,とりあえずこれでリアルタイムOSと言えるの ではないか...というところまで持っていってみよう.

割り込みの優先度づけなのだけど,前回実装した kz_precall() システムコールに より,スレッドのディスパッチの直前に特定の関数が呼ばれるように登録しておいて, で,その関数内部で優先度の低い割り込みをマスクすることで実装する. これにより,ある割り込みが入ってその処理スレッドが動作している最中に, 別の優先度が低い割り込みが入ることはなくなり,割り込みに優先度をつけて, 完全にリアルタイムOS化することができる.

実はこの優先度づけの実装の前段階として,第36回,第37回で準備を行ってきたので, 今回の実装はそれほど難しくはない.ソースは以下のような感じ.

(2009/04/10 ライセンスに関する文書として,KL-01とLICENSEを追加. 詳しくは第43回を参照)

変更点については diff.txt を参照してほしいのだが,まず,割り込みのマスク/ マスク解除用のサービス関数として mask, unmask という関数ポインタを struct interrupts に追加している.これはそれぞれ割り込みをマスク/マスク解除 するためのサービス関数になる. で,タイマ割り込みとコンソール割り込み用のマスク/マスク解除関数として, timer_mask(), timer_unmask(), cons_mask(), cons_unmask() を追加している. 内容は,制御ソケットを使って子プロセスに割り込みのマスク要求を出すだけだ. これはKOZOSを実機で動作させる場合には,割り込みマスクレジスタを直接操作する という実装になる.

さらに,kz_precall() で登録する割り込みマスク処理関数として,preproc() を 追加している.内容は,自分より優先度の高い割り込みは unmask() を呼び出して マスク解除し,優先度の低い割り込みは mask() を呼び出して割り込みマスクを しているだけだ.

あと kz_precall() によって,スレッドごとにマスク処理関数が呼ばれるように してある.extintr の場合は全マスク,その他のスレッドの場合はマスク無し になるように手を入れている.ここまでが extintr.c の修正内容だ.

main.c は,スレッドの優先度を割り込み優先度に合わせて調整した. 前回説明したが,現状で利用されている割り込みの優先度は,以下のように なっている. (これは extintr.c の extintr_intr_regist() の呼び出しで決定されている)

で,上から順に clock.c, command.c, timerd.c で利用されている. なので clock スレッドを優先度10,commandスレッドを優先度11,timerdスレッドを 優先度12として優先度の順番をそろえた.あとそれ以外のスレッドは割り込みとは 関係が無いので,優先度を20番代にして低くしておいた.

thread.c は,kz_precall() でデフォルトの関数を登録できるように改造した. これにより,kz_precall() でディスパッチ前のコールバック関数を登録していない スレッドの場合に,デフォルトのコールバック関数を呼び出させることができる. これは優先度の低い一般スレッドがディスパッチされる際に,すべての割り込みの マスクを解除するために利用する.

最後に,timerd.c をちょろっと修正.

で,動作させてみたところ,とりあえずタイマとコンソールは従来通り動いた. ただ,たまに動作が停止して固まってしまうようなんだよね...うーん原因不明.


メールは kozos(アットマーク)kozos.jp まで