世界最速のタスク・スイッチ・ライブラリ (Task Switch Library for AVR-G++)

タスク・スイッチするには何らかの方法でタスクを管理する必要があるが純粋なコンテキスト・スイッチよりもタスク管理のためのコストのほうが大きくなってしまうのが一般的だ。特にAVRではメモリ・アクセスに2サイクルかかるため管理コストの増大は避けられない。

そこで、高速なタスク・スイッチに特化した(しすぎた?)タスク・スイッチ・ライブラリを考えてみた。所謂、タイムスライスしない協調型マルチタスクと呼ばれるもので実装については高速化や言語との親和性を考慮しインライン・アセンブラとした。

タスク管理せず単純にスイッチングするだけの仕様であれば、ほぼコンテキスト・スイッチのみのコストでOKで、一般的な説明には必須で出てくるTCBなども省略できるし、さらにコンパイラの関数呼び出し規則に依存することで保存/復旧するレジスタ数も減らすことが可能となる。機能もコードもこれ以上省略できるものがないほどシンプルなライブラリとなっているので逆に安心して使えるかもしれない。ちなみにタスク・リストは各タスクのスタックをリンクするという珍しい実装方法となっている。

関数呼び出しのオーバーヘッドを含めたスイッチング時間は、

 123 cycles (7.6875us/16MHz)

 ※Raspberry Pi Pico に移殖すると1us未満で実行できそう。

イレギュラーチェックにかかる3サイクルは省略可能であるものの、それ以上省略できそうなところもないので世界最速のはずだ。

あと機能的には、wait/semaphore/eventなども実装可能だがわかりやすさを重視しシンプルに留めておきたいので今回はここまで。興味のある方は地球人の未来のためにも頑張って改良してみてほしい。かも。

【概要】

新しいタスクを登録する。sizeにはスタック領域のバイト数、funcには実行する関数を指定する。登録したタスクはyield呼び出しにより順番に実行される。

※スタック領域はmalloc()により割り当てられ、funcからリターンすることやタスク終了できない点に注意。

タスクを切り替える。登録されたタスクがなければ何もせずに戻る。

[Arduinoのみ] 指定時間(ミリ秒)待つ。待っている間は他タスクを実行し続ける。

[Arduinoのみ] 指定時間(マイクロ秒)待つ。待っている間は他タスクを実行し続ける。

【サンプル・スケッチ】
Arduinoではloop()からのリターン後にシリアル・イベントなどのバックグランド処理が実行されるためyield()のみ実行し直ぐにリターンするのがお勧めだ。

【ライブラリ】

【関連投稿】
世界最速のタスク・スイッチ・ライブラリ (Task Switch Library for ARM-G++ [M0/M0+])