(第34回)タイマ割り込みを実装する

2009/01/18

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

前回の続きで,割り込みまわりを改造していきたい.今回はタイマ割り込みだ.

タイマ処理についてなのだが,現状では各スレッドが kz_timer() システムコールに よって自由にタイマ設定できる.KOZOSの内部では,タイマキューを検索して適切な 位置にタイマ登録し,タイマキューの先頭に対して getitimer() で SIGALRM を かけている.実際のハードウエアでは,SIGALRM はリアルタイムクロック(RTC)からの タイマ割り込みということになる.

このようなタイマキューの使いかたは,タイマ処理をしたい場合の定石の書き方だ. タイマキューを使うことで,ひとつしかないタイマ資源(KOZOSの場合は,SIGALRMに よるシグナル)でいくつものタイマをかけることができる.

ただしこれはリアルタイムOSとして考えると,あまり良い方法ではない. タイマ設定時に必ずタイマキューの検索が入ってしまうため, リアルタイム性を確保できないからだ.

で,リアルタイムOSではどのようにするかなのだけど,ちょっといろいろ考えたの だけど,本当に厳密なタイマ処理をしたい場合には,タイマキューのような仕組みは NGだ.しかし,各スレッドがちょっと数秒単位でのタイマをかけたい場合には, 厳密なタイミングやリアルタイム性が必要ではない場合も多い.

ということで結論としては,厳密なリアルタイム性が必要なタイマは, ハードウエアが持っているRTCをそのまま使うしかない.たとえばハードウエアが 4つのRTCを持っているならば,タイマ資源を4つのみに限定して,タイマを必要と するスレッドは,RTCを直接利用しまえば,リアルタイム性を確保できる.

ただしこれでは,タイマは4つまでしか利用できないので,他のスレッドがすでに タイマを利用していると,もうタイマを使うことはできなくなってしまう. ということで,4つのうちのひとつだけはタイマキューを実装して, 精度を必要としないスレッドは,タイマキューのほうのタイマを利用すれば, タイマはいくらでも使うことができることになる.

この場合,厳密なリアルタイム性を持つタイマとして,3つのタイマ資源を利用 できる.またそれとは別に,あまり厳密でない(そしてリアルタイム性も無い)タイマを (こちらはキュー管理しているので,論理上は無限に)利用できることになる.

ついでにタイマキューの処理はリアルタイム性を確保できない (タイマキューの検索があるので).このためタイマキューの処理は専用の スレッドに任せてしまうのがいいと思う.

結局どのような構造になるかというと,たとえばタイマ資源としてRTCを4つ搭載して いるようなハードウエアならば,以下のような感じだ.

  1. 4つのタイマ資源(RTC)のうち,3つは一般スレッド用に解放する. このためユーザスレッドは,リアルタイム性のある(厳密なタイミングで動作できる) タイマを全体で3つまで利用できる.
  2. 4つのRTCの残りのひとつは,タイマ管理スレッドが利用する. タイマ管理スレッドはタイマキューを持ち,,RTCを利用してタイマ動作することで, ユーザスレッドにタイマサービスを提供する.
  3. 厳密なタイミングを必要とする場合は,上記1のタイマ資源を利用する. これは有限の資源なので,あるスレッドがすでに利用していたら,他のスレッドは 利用できないことになる.
  4. 厳密なタイミングを必要としない(数ミリ秒ずれても構わない)場合は,上記2の タイマサービスを利用する.タイマ登録は,タイマ管理スレッドにメッセージを 投げることで依頼する(タイマ満了でメッセージが返ってくる). タイマ管理スレッドはタイマキューの検索を行うためその動作にリアルタイム性は 無いが,スレッド化してあるのでOSのリアルタイム性への影響は無い.
つまり,リアルタイム性を確保できない部分(タイマキューの処理)はタイマ管理 スレッドに任せてOSの外に出すことで,OSのリアルタイム性に悪影響が出ないように している.

ひとつのタイマで汎用的なタイマサービスを実現したい場合,タイマをキュー管理 することでリアルタイム性が無くなってしまうことは避けられない. このため,リアルタイム性と厳密さが必要な処理に関しては,専用のRTCを割り当てる のが正しい考えだ.

で,extintr.c にタイマ割り込み処理を実装してみた. ソースは以下のような感じ.

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

ついでにコンソール処理での w コマンドによる出力処理でレジスタの検索を 忘れていたバグを修正.(以下)

       case 'w': /* 出力 */
+       irp = intrreg_search(id);
        write(irp->write_fd, &p[1], size - 1);
        break;

タイマ割り込みの処理を図にするとこんな感じ. ちなみに従来の clock スレッドを,新設したタイマを利用するように修正してある.

(タイマ設定と動作時)

  サービススレッド     extintr        子プロセス
(clockスレッドなど)
         |                |                |
         |             kz_recv()待ち   select()待ち
         |                |                |
      kz_send()=========>|                |
         |             kz_recv()           |
         |             write()----------->|
      kz_recv()待ち       |              read()
         |                |                |
         |                |             select()
         |                |                |
         |                |           (タイマ満了)
         |                |                |
         |                |<------------write()
         |                |<======------SIGHUP
         |             kz_recv()(※1)     |
         |              read()             |
         |                |                |
         |<===========kz_send()        select()待ち
      kz_recv()           |                |
         |             kz_recv()待ち       |
         |                |                |

---> は,ソケットによる接続や通信
===> は,KOZOSのメッセージ送信

※1 kz_setsig() システムコールにより,シグナル受信は
     メッセージによりextintrに通知される.
extintr.c の処理には,タイマ処理が追加してある. 前回実装したソケット通信処理(コンソール処理)に対して, 同じような感じでタイマ処理が追加されている. (タイマとコンソールを別の子プロセス&別スレッドにしてもよかったのだが, 将来的にタイマとコンソールをひとつの処理で割り込みマスクできるように, extintr.c にまとめてある)

まあ具体的な処理は,前回追加したコンソールの処理とだいたい同じだ. extintrスレッドと子プロセスの間でソケットを張り, ソケット経由でタイマの起動を依頼すると,子プロセスがタイマ動作して満了時には ソケットに通知し,SIGHUPを上げてくる.で,extintr は SIGHUP を受信したら ソケットを調べ,タイマ満了している場合には当該スレッドにメッセージを送信する.

あと clock.c は,従来はKOZOSのタイマサービスを利用していたが, extintr が持つタイマを利用するように修正してある.

extintr がタイマ実装されたことで,KOZOSのタイマサービス(kz_timer())は不要に なる.まあこの処理はリアルタイム性が無いのでOSの中に残しておくのはまずいので, そのうち削除しよう.あーそれと,汎用的なタイマサービスのためにタイマ管理 スレッドを実装する必要があるなあ(KOZOSのタイマ処理をもとにすればいいだろう). まあこれは後ほど.

実行結果は以下.いちおう,ちゃんとタイマ動作しているようだ. telnetによる接続も問題ないみたい.

hiroaki@teapot:~/kozos34>% ./koz 
Mon Jan 19 00:30:13 2009
Mon Jan 19 00:30:14 2009
Mon Jan 19 00:30:15 2009
Mon Jan 19 00:30:16 2009
Mon Jan 19 00:30:17 2009
...

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