第 4 章 µITRON4.0 仕様の機能 81
4.3 タスク例外処理機能
タスク例外処理機能は,タスクに発生した例外事象の処理を,タスクのコンテ キストで行うための機能である.タスク例外処理ルーチンを定義する機能,タ スク例外処理を要求する機能,タスク例外処理を禁止/許可する機能,タスク 例外処理に関する状態を参照する機能が含まれる.
タスク例外処理を要求するサービスコールが呼び出され,タスクに対してタス ク例外処理が要求されると,タスクが実行中の処理を中断し,タスク例外処理 ルーチンを起動する.タスク例外処理ルーチンは,タスクと同じコンテキスト で実行する.タスク例外処理ルーチンからリターンすると,中断した処理の実 行を継続する.アプリケーションは,タスク毎に一つのタスク例外処理ルーチ ンを登録することができる.タスクの生成直後は,タスク例外処理ルーチンは 登録されていない.
タスクに対してタスク例外処理を要求する場合には,要求する例外処理の種類 をあらわすタスク例外要因を指定する.カーネルは,タスク毎に,要求された がまだ処理されていないタスク例外要因を管理する.これを,保留例外要因と 呼ぶ.保留例外要因は,処理されていない例外処理要求がない時には 0となっ ている.処理されていない例外処理要求があるタスクに対して,再度タスク例 外処理が要求された場合には,タスクの保留例外要因を,新たに要求された例 外処理のタスク例外要因とのビット毎の論理和に更新する.保留例外要因は,
タスクの起動時に 0にクリアする.
タスクは,タスク例外処理禁止状態かタスク例外処理許可状態かのいずれかの 状態をとる.タスク例外処理禁止状態に移行することを「タスク例外処理を禁 止する」,タスク例外処理許可状態に移行することを「タスク例外処理を許可 する」ともいう.タスクの実行開始直後は,タスク例外処理禁止状態とする.
実装定義で,拡張サービスコールルーチンの起動によりタスク例外処理を禁止 し,そこからのリターンにより起動前の状態に戻すことができる.このような 実装では,拡張サービスコールルーチン内でタスク例外処理を許可してはなら ないため,拡張サービスコールルーチンから ena_texが呼び出された場合には E_CTXエラーを返す.
タスク例外処理許可状態であり,保留例外要因が 0でなく,タスクが実行状態 であり,非タスクコンテキストまたは CPU例外ハンドラが実行されていないと いう 4つの条件が揃うと,タスク例外処理ルーチンを起動する.起動するタス ク例外処理ルーチンには,起動時の保留例外要因( texptn)とタスクの拡張情 報( exinf)をパラメータとして渡す.またこの時,タスクをタスク例外処理 禁止状態に移行させ,保留例外要因を 0にクリアする.
タスク例外処理ルーチンからリターンすると,タスク例外処理ルーチンを起動 する前に実行していた処理の実行を継続する.この時,タスクをタスク例外処 理許可状態に移行させる.ここで,保留例外要因が 0でない場合には,再びタ スク例外処理ルーチンを起動する.
タスク例外処理機能では,次のデータ型を用いる.
TEXPTN タスク例外要因のビットパターン(符号無し整数)
タスク例外処理ルーチンの C言語による記述形式は次の通りとする.
void texrtn ( TEXPTN texptn, VP_INT exinf ) {
タスク例外処理ルーチン本体 }
タスク例外処理機能に関連して,次のカーネル構成定数を定義する.
TBIT_TEXPTN タスク例外要因のビット数( TEXPTNの有効ビッ
ト数)
タスク例外処理ルーチン定義情報およびタスク例外処理状態のパケット形式 として,次のデータ型を定義する.
typedef struct t_dtex {
ATR texatr ; /* タスク例外処理ルーチン属性 */
FP texrtn ; /* タスク例外処理ルーチンの起動番
地 */
/* 実装独自に他のフィールドを追加してもよい */
} T_DTEX ;
typedef struct t_rtex {
STAT texstat ; /* タスク例外処理の状態 */
TEXPTN pndptn ; /* 保留例外要因 */
/* 実装独自に他のフィールドを追加してもよい */
} T_RTEX ;
タスク例外処理機能の各サービスコールの機能コードは次の通りである.
TFN_DEF_TEX –0x1b def_texの機能コード TFN_RAS_TEX –0x1c ras_texの機能コード TFN_IRAS_TEX –0x74 iras_texの機能コード TFN_DIS_TEX –0x1d dis_texの機能コード TFN_ENA_TEX –0x1e ena_texの機能コード TFN_SNS_TEX –0x1f sns_texの機能コード TFN_REF_TEX –0x20 ref_texの機能コード
【スタンダードプロファイル】
スタンダードプロファイルでは,タスク例外処理ルーチンを動的に定義する機 能( def_tex),タスク例外処理の状態を参照する機能( ref_tex)を除いて,タ スク例外処理機能をサポートしなければならない.
スタンダードプロファイルでは,タスク例外処理機能で用いるデータ型の有効 ビット数を次の通りに定める.
TEXPTN 16ビット以上
したがって, TBIT_TEXPTNは 16以上でなければならない.
【補足説明】
この仕様の範囲内では, CPUロック状態でタスク例外処理ルーチンを起動すべ き条件が揃うことはない.それに対して,ディスパッチ禁止状態でタスク例外 処理ルーチンを起動すべき条件が揃うことはあり,その場合には,タスク例外 処理ルーチンを起動しなければならない.
タスク例外処理ルーチンを実行するコンテキストと状態については,次のよう に整理できる.
• タスク例外処理ルーチンは,タスクと同じコンテキストで実行する( 3.5.1節 参照).タスク例外処理ルーチンを実行するコンテキストは,タスクコンテ キストに分類される.
• タスク例外処理ルーチンの起動と,そこからのリターンによって, CPUロッ ク/ロック解除状態とディスパッチ禁止/許可状態は変化しない( 3.5.4節と
3.5.5節を参照).ただし, CPUロック状態でタスク例外処理ルーチンを起動
するかどうかは規定されない.
タスク例外処理禁止/許可状態が変化する状況は,次のように整理できる.
• タスク起動時には,タスク例外処理禁止状態とする.
• タスク例外処理ルーチンの起動時に,タスク例外処理禁止状態とし,タスク 例外処理ルーチンからのリターン時に,タスク例外処理許可状態に戻す.
• dis_texが呼び出されると,タスク例外処理禁止状態とし, ena_texが呼び 出されると,タスク例外処理許可状態とする.
• def_texによりタスク例外処理ルーチンの定義が解除されると,タスク例外
処理禁止状態とする.
タスク例外処理ルーチンはタスクと同じコンテキストで実行するため, C言語 の標準ライブラリ関数の longjmpを用いて,タスク例外処理ルーチンから大域 脱出することができる.この場合カーネルは,タスク例外処理ルーチンが終了 したことを検知できないため,タスク例外処理許可状態には戻さない.タスク 例外処理許可状態に戻したい場合には,アプリケーションで ena_texを呼び出 して,タスク例外処理を許可する必要がある.また,タスク例外処理ルーチン からの大域脱出を用いる場合,グローバルなデータ構造の一貫性が失われる間 は,タスク例外処理を禁止する必要がある(仕様決定の理由を参照).
タスク例外処理ルーチンからリターンした直後に再びタスク例外処理ルーチ ンを起動する場合,タスク例外処理ルーチンの実行開始直後のスタックポイン タの値が,最初に起動した時の値と同じでなければならない.つまり,タスク 例外処理ルーチンの再起動により,スタック上に無駄な領域が残ってはならな い.さもないと,タスク例外処理ルーチンの連続起動によって使用されるス タック領域の上限サイズを押さえることができなくなる.
µITRON4.0仕様では,タスク例外要因毎に例外をマスクする機能は用意してい ないが,仕様に規定された機能を用いて,アプリケーションで同等の機能を実 現することができる.具体的には,タスク毎のタスク例外処理マスクをアプリ
ケーションで管理し,タスク例外処理ルーチンの先頭で,渡された例外要因が マスクされているかどうかを調べる.マスクされていた場合には,その例外要 因でタスク例外処理ルーチンが起動された旨を記録して,すぐにリターンする
(実際には,マスクされた例外要因とマスクされていない例外要因が重なった 場合に対応する必要がある).後でタスク例外処理マスクを解除する時点で,
マスクを解除する例外要因でタスク例外処理ルーチンが起動された記録があ るか調べ,記録がある場合にはその時点でタスク例外処理ルーチンを呼び出 す.
タスク例外処理ルーチンを起動する時にタスク例外処理を禁止するため,その ままでは,タスク例外処理ルーチンは多重起動されない.タスク例外処理ルー チンが複雑になる場合(特に,内部で待ち状態になる場合)には,タスク例外 処理ルーチンの実行中に発生した例外により,タスク例外処理ルーチンを多重 に起動したいケースが考えられる.このような場合には,タスク例外処理ルー チン内で ena_texを呼び出してタスク例外処理を許可することで,タスク例外 処理ルーチンの多重起動を実現することができる.この時,タスク例外処理 ルーチンが無際限に多重起動することを防ぐための仕組みが必要である.例え ば,上述のタスク例外要因毎にマスクする方法を併用し,処理中の例外要因を マスクする方法などが考えられる.
また,タスク例外処理ルーチンを起動する時にタスク例外処理を禁止するた め,タスク例外処理ルーチン中で CPU例外が発生した場合, CPU例外ハンドラ からタスク例外処理を要求しても, CPU例外ハンドラからリターンすると元の 処理が継続してしまう.この時, CPU例外ハンドラ内で CPU例外を発生させた 要因が取り除かれないと,リターン直後に再度 CPU例外が発生し, CPU例外の 発生を無際限に繰り返すおそれがある.同様のことは,タスク例外処理禁止状 態で発生した CPU例外すべてにあてはまる.
そこで,基本的には, CPU例外ハンドラからタスク例外処理を要求する場合に は,タスク例外処理を禁止している間は CPU例外が発生しないようにすること が必要である.ただし,ソフトウェアのバグやハードウェアの誤動作で CPU例 外の発生が避けられない場合もあり,このような場合にも CPU例外が無際限に 発生するのを避けるには, CPU例外ハンドラ中で CPU例外を発生させたタスク のタスク例外処理禁止状態を参照し,禁止状態であった場合には特別な処理を 行う必要がある.また,必要なら上記の方法でタスク例外処理ルーチンの多重 起動を可能にするなどして,タスク例外処理を禁止する区間を短く押さえるこ とも必要であろう.
アプリケーションとカーネルでスタックを切り替える実装では,タスク例外処 理ルーチンの多重起動を可能にするために,カーネルスタックまたはタスク制 御ブロック( TCB; Task Control Block)に保存した情報をアプリケーションス タックに移動させる必要が生ずる場合が多い.例えば,タスクがプリエンプト されている状態でタスク例外処理が要求され,次にそのタスクが実行状態と なった時点でタスク例外処理ルーチンを起動する場合には,プリエンプト直前 の状態(一般的には,カーネルスタックか TCBに保存されている)をアプリ