それでは、Tockの解決法はどういうものだったのか。以下に挙げてみよう。
何というかなかなかドラスチックな解決法である(図6)。現時点でのTockはシングルスレッドモデルなので、イベントは特定の1スレッドにしか通知されない。このため、疑似マルチタスクはともかく、いわゆるマルチスレッドモデルのプログラミングは書き直す必要がある。
ではTockの実装はどうなっているのか。それをまとめたのがこちら(図7)。カーネルそのものはRustで記述され、Trustな環境にある。その上に仮想のデバイスドライバが載るが、これはカプセル化される形で提供され、ユーザープログラム領域とは分離される。Process Schedulerはプリエンプティブ(非協調的)な構成になってはいるが、ただいわゆるコンカレントモデルをフルに実装しているわけではない。またプロセスの数もそれほど多く実行することは考慮していない(内蔵SRAMが最大64KBの、Microchipの「SAM4L」で最大8スロット程度、としている)。このあたりは先にも書いたがメモリとのご相談である。
そのメモリサイズに関して言えば、例えば「SOSP 2017」の際に行われたLevy氏による講演での数字はこんな感じ(図8)。
ROMサイズ、つまりコードサイズはそこそこであるが、RAMサイズの方はかなり低めに抑えられている(RAMサイズが小さいRTOS「TinyOS」は本連載でまだ紹介していないが、何せ開発がほぼ止まっているというか終わっているので、紹介の順序はだいぶ後になりそうだ)。アプリケーションから見たアドレス空間は図9のようになっている。
フラッシュ空間はRead+Execute、SRAM(と仮にあればデータフラッシュメモリ)はRead+Writeとして扱われ、プロセスごとに分離される(図10)。
ついでに割り込み(Interrupt)周りを記しておくと、こんな感じになっている(図11)。カーネルにはIRQ Dispatchと、これに連動したProcess Schedulerが実装されているが、このうちタイマーのSysCallやTimer Driver、Virtual Alarmなどは全てカプセル化されている。このカプセル化されたオブジェクトは、一切イベント(というか、割り込み)は生成しない形になっている。これはオーバーヘッド削減につながり、またメモリ削減にもつながる、というのがLevy氏の説明だ。イベントを生成すると、実態としては割り込みにならざるを得ないからISRが無駄に動くことになる。ISRが動くというのは、その前後でContext Switchingが発生するということなので、これのオーバーヘッドがしゃれにならない(Context Switchingは340サイクルほどと説明されている。48MHz動作で7μsほど、という説明なので、これもSAM4Lの数字であろう)。
もう1つのメモリ削減だが、オブジェクト間での通信をイベントベースでやる場合、FIFOでも何でもいいのだが、何かしらのキューが必要になる。ところがTockの場合は、キューの数をOSのビルド時に静的に決定する方式となっているので、処理が間に合わないとキューにメッセージを入れられずにドロップすることになってしまい、安定動作が難しくなる。これを防ぐために、何でもかんでもイベントにするわけではなく、同期式の呼び出しをメインにすることでオーバーヘッドを削減するという方式だ。
Copyright © ITmedia, Inc. All Rights Reserved.