GAIO CLUB

2023年10月10日

【第14回】マルチタスクと割り込み

静的解析/コンパイラ技術
いまさら聞けない静的解析/コンパイラ技術
複数のタスクが並列動作する場合、競合に注意する必要があります。シングルタスクであっても割り込み処理との競合があります。

共有変数

プログラムは機械語をひとつずつ実行しているので、ある瞬間で一度に2つ以上の変数をアクセスすることはできません。しかし、2つのタスクが動いている場合には、ある瞬間に2つの変数をアクセスできます。
その2つのアクセスが運悪く同じ変数をアクセスし、どちらか、または両方が変数への代入の場合、困ったことが起きるかもしれません。
共有変数
そもそも、2つのタスクが同じタイミングで同じ変数をアクセスすることは想定内なのか検証が必要です。
そして、上の図の2つの式がほぼ同時に動いた場合、変数aは3種類の値になる可能性があります。

変数aの値が2だった場合、右の式が先に動けば15になります。左が先に動けば10になります。
そして、同時に動くと7になります。細かくなりますが、SH3のアセンブリ言語で見てみます。
共有変数
もっと困ったことになるのは、変数のサイズが大きな場合です。
1つの機械語でアクセスが終了する型をアトミック型と呼びますが、そうではないもの、たとえば4バイトを超える構造体では、機械語の代入が複数回発生します。もし、2つのタスクが同時に代入すると、構造体のメンバ変数は両タスクの代入値が混ざった値になってしまう可能性があります。この問題を防ぐためには、排他制御や割り込み禁止処理が必要です。

共有関数

複数のタスクや割り込み処理が同じ関数を呼出すとき、その関数がアクセスする静的変数(グローバルを含む)は共有変数になります。
共有関数
赤字の変数は共有変数なので、使用時には注意する必要があります。
スタックの回でお話ししたように、オート変数や引数はスタックを使用するので、共有になりません。

リエントラント関数

複数のタスクや割り込み処理から呼び出される共有関数が静的変数を使用すると、その変数は共有変数になるわけですが、静的変数を使用しない構造にすることで共有変数は無くなり、共有関数はリエントラント(再入可能)と呼ばれる関数になります。

再入可能というのは、「再び入っても大丈夫」という意味ですが、分かりにくいですね。
たとえば、ある関数が動作している時に割り込みが発生し、割り込み処理が動き、割り込み処理関数がある関数を呼出すと、ある関数に再び入ってしまいます。このような動きをしても、問題なく動作するということです。
リエントラント関数
上の図は、Task_Aに呼び出されたAru_functionの途中で割り込みが発生し、割り込み処理関数のInterrupt_1から再びAru_functionが呼び出されていることを示しています。
この一連の処理の中で、Aru_functionだけを見ると ① ② ③の順で動作します。途中で一旦止まり、後から動いた処理に追い抜かれ、止まっていたところから処理を継続します。
Aru_functionが静的変数を使用しないのであれば、この関数は追い抜かれた処理の影響を受けず、リエントラントであると言えます。
もし、の部分で静的変数に値を保存し、の部分でその変数を参照していると、で参照する値はの処理が保存した値を参照するので、追い抜かれた処理の影響を受ける可能性があります。
リエントラント関数は、Aru_functionが呼び出す子関数も含め全てリエントラントでなければなりません。

割り込み処理関数

組み込みソフトでは割り込み処理が普通にあります。
C言語の文法に割り込み処理関数の指定はありませんが、組み込み向けのCコンパイラには、割り込み関数を指定するための仕様があると思います。
たとえば、GAIO製Cコンパイラでは、#pragma interrupt や __interrupt キーワードを使って割り込み関数を指定する仕様でした。
__interrupt void intr_func(void)
{
	/* 割り込み処理 */
}
割り込み処理関数であるにもかかわらず、割り込み関数の指定を忘れると正常に動作しません。
というのは、割り込み処理関数の出入り口処理は普通の関数とは異なるからです。
普通の関数は呼び出しの手順を踏んで呼び出されますが、割り込み関数は動作中の関数を強制的に止めて動くので、割り込み処理終了時には止められた関数の停止箇所に戻り、処理を継続させなければなりません。
そのために、普通の関数では退避する必要のないレジスタも退避・復元し、割り込み処理からのリターン時には、停止箇所に戻るために普通の関数とは異なる特別なリターン命令を使用します。

筆者紹介

浅野 昌尚(あさの まさなお)

ガイオ・テクノロジー株式会社

開発2部 QTXグループ

1980年代から30年以上にわたり汎用構造のCコンパイラ開発に従事し、その間に8ビットマイコンからRISC・VLIW・画像処理プロセッサまで、さまざまなCPU向けのクロスCコンパイラを開発。

人気のコラム

最新のコラム