タスク例外処理機能

タスク例外処理機能は、タスクに発生した例外事象に対する処理を、タスクのコンテキストで行うための機能である。

タスク例外ハンドラが起動されるのは、次の条件がすべて揃った時である。

  1. tk_def_tex によるタスク例外ハンドラの登録

  2. tk_ena_tex によるタスク例外の許可

  3. tk_ras_tex によるタスク例外の発生

タスク例外ハンドラは、タスク例外が発生したタスクのコンテキストで、かつタスク生成時に指定した保護レベルで、そのタスクの一部として実行される。また、タスク例外ハンドラ内では、タスク例外に関する状態を除き、通常のタスク部の実行中と同じ状態であり、使用できるシステムコールも同等である。

タスク例外ハンドラは、対象タスクがタスク部を実行しているときにのみ起動される。対象タスクがタスク部以外を実行中のときにタスク例外が発生した場合は、タスク部へ戻ってくるまで待ってタスク例外ハンドラが起動される。準タスク部(拡張SVC)を実行中にタスク例外が発生した場合は、その拡張SVCに対応するブレーク関数が呼び出される。ブレーク関数によって拡張SVCの処理が中止されタスク部へ戻ってくることになる。

発生したタスク例外要求は、タスク例外ハンドラが呼び出された(タスク例外ハンドラが実行を開始した)時点でクリアされる。

タスク例外は、0~31の32種類のタスク例外コードにより指定され、0が最も優先度が高く31が低い。また、タスク例外コード0は特殊な扱いとなる。

タスク例外コード1~31の動作:

  • タスク例外ハンドラはネストして実行されない。タスク例外ハンドラの実行中に発生したタスク例外はペンディングされる。(タスク例外コード0の場合を除く)

  • タスク例外ハンドラからリターンすることで、タスク例外によって割り込まれた位置に復帰する。

  • タスク例外ハンドラからリターンせずに、longjmp() などによりタスク内の任意の位置にジャンプすることもできる。

タスク例外コード0の動作:

  • タスク例外コード1~31のタスク例外ハンドラを実行中でもネストして実行される。タスク例外コード0のタスク例外ハンドラの実行中はネストされない。

  • ユーザスタックポインタをタスク起動時の初期値に設定してから、タスク例外ハンドラが実行される。ただし、ユーザスタックとシステムスタックが分離されていないシステムでは、スタックポインタは初期値に戻されない。

  • タスク例外ハンドラから復帰することは出来ない。必ず tk_ext_tsk または tk_exd_tsk によってタスクを終了しなければならない。

tk_def_tex - タスク例外ハンドラの定義

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_def_tex (ID tskid , CONST T_DTEX *pk_dtex );

パラメータ

ID tskid Task IDタスクID
CONST T_DTEX* pk_dtex Packet to Define Task Exceptionタスク例外ハンドラ定義情報

pk_dtex の内容

ATR texatr Task Exception Attributeタスク例外ハンドラ属性
FP texhdr Task Exception Handlerタスク例外ハンドラアドレス
──(以下に実装独自に他の情報を追加してもよい)──

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_NOMEM メモリ不足(管理ブロック用の領域が確保できない)
E_ID 不正ID番号(tskid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(tskid のタスクが存在しない)
E_OBJ オブジェクトの状態が不正(tskid のタスクは TA_RNG0 属性)
E_RSATR 予約属性(texatr が不正あるいは利用できない)
E_PAR パラメータエラー(pk_dtex が不正あるいは利用できない)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tskid で指定したタスクに対するタスク例外ハンドラを定義する。タスク例外ハンドラはタスクに対して1つのみ定義可能で、すでに定義されていた場合は、後から定義した関数が有効となる。pk_dtexNULL の時は定義を解除する。

タスク例外ハンドラを定義または解除すると、ペンディングされているタスク例外要求はクリアされ、すべてのタスク例外は禁止状態となる。

texatr は、下位側がシステム属性を表し、上位側が実装独自属性を表す。texatr のシステム属性には、現在のバージョンでは割当てがなく、システム属性は使われていない。

タスク例外ハンドラは、下記のような形式になる。

void texhdr( INT texcd )
{
        /*
                タスク例外の処理
        */

        /* タスク例外ハンドラの終了 */
        if ( texcd == 0 ) {
                tk_ext_tsk() または tk_exd_tsk();
        } else {
                tk_end_tex();
                return または longjmp();
        }
}

タスク例外ハンドラは、TA_ASM 属性相当のみで高級言語対応ルーチンを経由しての呼出は行われない。したがって、タスク例外ハンドラのエントリー部分はアセンブリ言語で作成する必要がある。カーネル提供者は、上記のC言語のタスク例外ハンドラを呼び出すためのエントリールーチンのアセンブリ言語のソースコードを提供しなければならない。つまり、高級言語対応ルーチンに相当するソースコードを提供しなければならない。

タスク生成時の保護レベルが TA_RNG0 のタスクに対して、タスク例外を使用することはできない。

補足事項

タスク生成時にはタスク例外ハンドラは定義されておらず、タスク例外も禁止されている。

タスクが休止状態(DORMANT)に戻る時には自動的にタスク例外ハンドラは解除され、タスク例外は禁止される。また、ペンディングされていたタスク例外はクリアされる。ただし、休止状態(DORMANT)であるときに、タスク例外ハンドラを定義することはできる。

タスク例外は、tk_ras_tex によって発生するソフトウェア的なもので、CPUの例外と直接の関連はない。

tk_ena_tex - タスク例外の許可

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_ena_tex (ID tskid , UINT texptn );

パラメータ

ID tskid Task IDタスクID
UINT texptn Task Exception Patternタスク例外パターン

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(tskid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(tskid のタスクが存在しない、タスク例外ハンドラが定義されていない)
E_PAR パラメータエラー(texptn が不正あるいは利用できない)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tskid のタスクへのタスク例外の発生を許可する。

texptn は、タスク例外コードを1<<タスク例外コードのビット値として、論理和(OR)した値である。

tk_ena_tex は、texptn で指定したタスク例外を許可する。 現在のタスク例外の許可状態を texmask とすると次のようになる。

許可:texmask |= texptn

texptn の全ビットを0とした場合は、texmask に対して何の操作も行わないことになる。ただし、この場合でもエラーとはならない。

タスク例外ハンドラが定義されていないタスクのタスク例外を許可することはできない。

休止状態(DORMANT)のタスクに対しても適用される。

tk_dis_tex - タスク例外の禁止

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_dis_tex (ID tskid , UINT texptn );

パラメータ

ID tskid Task IDタスクID
UINT texptn Task Exception Patternタスク例外パターン

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(tskid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(tskid のタスクが存在しない、タスク例外ハンドラが定義されていない)
E_PAR パラメータエラー(texptn が不正あるいは利用できない)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tskid のタスクへのタスク例外の発生を禁止する。

texptn は、タスク例外コードを1<<タスク例外コードのビット値として、論理和(OR)した値である。

tk_dis_tex は、texptn で指定したタスク例外を禁止する。現在のタスク例外の許可状態を texmask とすると次のようになる。

禁止:texmask &= ~texptn

texptn の全ビットを0とした場合は、texmask に対して何の操作も行わないことになる。ただし、この場合でもエラーとはならない。

禁止されているタスク例外は無視され、ペンディングもされない。ペンディングされているタスク例外がある状態で、そのタスク例外が禁止された場合は、タスク例外要求が捨てられる(ペンディング状態がクリアされる)。

休止状態(DORMANT)のタスクに対しても適用される。

tk_ras_tex - タスク例外を発生

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_ras_tex (ID tskid , INT texcd );

パラメータ

ID tskid Task IDタスクID
INT texcd Task Exception Codeタスク例外コード(0~31)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(tskid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(tskid のタスクが存在しない、タスク例外ハンドラが定義されていない)
E_OBJ オブジェクトの状態が不正(tskid のタスクは休止状態(DORMANT))
E_PAR パラメータエラー(texcd が不正あるいは利用できない)
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tskid のタスクに対して texcd のタスク例外を発生させる。ただし、tskid のタスクにおいて texcd のタスク例外が許可されていない場合は、発生させたタスク例外は無視され、ペンディングもされない。この場合でも、本システムコールには E_OK が返される。

tskid のタスクがタスク例外ハンドラの実行中であれば、タスク例外はペンディングされる。ペンディングされる場合、対象タスクが拡張SVCの実行中であってもブレーク関数は実行されない。

ただし、texcd=0の場合は、対象タスクが例外ハンドラを実行中であってもペンディングされない。対象タスクが、タスク例外コード1~31の例外に対するタスク例外ハンドラの実行中であればタスク例外は受け付けられ、拡張SVC実行中であればブレーク関数が呼び出される。対象タスクが、タスク例外コード0の例外に対するタスク例外ハンドラを実行中の場合は、タスク例外の発生は無視される。

tskidTSK_SELF=0によって自タスクの指定を行うことができる。

タスク独立部から発行することはできない。(E_CTX)

補足事項

対象タスクが拡張SVCを実行中の場合には、その拡張SVCに対応するブレーク関数が、tk_ras_tex の発行タスクの準タスク部として実行される。すなわち、ブレーク関数の実行されるコンテキストは、tk_ras_tex の発行タスクを要求タスクとする準タスク部である。

したがって、このような場合、ブレーク関数の実行が終わるまで tk_ras_tex から戻ってこない。このため、タスク独立部から tk_ras_tex を発行することはできない仕様になっている。

また、ブレーク関数実行中に tk_ras_tex を呼び出したタスクに発生したタスク例外は、ブレーク関数の終了まで保留される。

tk_end_tex - タスク例外ハンドラの終了

C言語インタフェース

#include <tk/tkernel.h>

INT texcd = tk_end_tex (BOOL enatex );

パラメータ

BOOL enatex Enable Task Exceptionタスク例外ハンドラ呼出の許可

リターンパラメータ

INT texcd Task Exception Code発生している例外コード(0~31)
またはError Codeエラーコード

エラーコード

E_CTX コンテキストエラー(タスク例外ハンドラ以外またはタスク例外コード0(検出は実装依存))

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

タスク例外ハンドラを終了し、新たなタスク例外ハンドラの呼出を許可する。ペンディングされているタスク例外がある場合は、その内の最も優先度の高いタスク例外コードを戻値に返す。ペンディングされているタスク例外がなければ0を返す。

enatexFALSE の場合、ペンディングされているタスク例外があると新たなタスク例外ハンドラの呼出は許可されない。この場合、tk_end_tex から戻った時点で、戻値に返された texcd の例外ハンドラを実行している状態になっている。ペンディングされているタスク例外がない場合は新たなタスク例外ハンドラの呼出が許可される。

enatexTRUE の場合は、ペンディングされているタスク例外の有無に関係なく、新たなタスク例外ハンドラの呼出を許可する。ペンディングされているタスク例外があっても、タスク例外ハンドラを終了した状態になる。

タスク例外ハンドラの終了は tk_end_tex を呼び出すこと以外にはない。タスク例外ハンドラが起動されてから tk_end_tex を呼び出すまでがタスク例外ハンドラの実行中となる。tk_end_tex を呼び出さずにタスク例外ハンドラからリターンしたとしても、リターン先はまだタスク例外ハンドラの実行中となる。同様に、tk_end_tex を呼び出さずに longjmp によりタスク例外ハンドラから抜けたとしても、そのジャンプ先はタスク例外ハンドラの実行中である。

タスク例外がペンディングされている状態で tk_end_tex を呼び出すことにより、ペンディングされていたタスク例外が新たに受け付けられる。この時、tk_end_tex を拡張SVCハンドラ内から呼び出した場合でも、tk_end_tex を呼び出した拡張SVCハンドラに対するブレーク関数は呼び出されない。拡張SVCをネストして呼び出していた場合は、拡張SVCのネストが1段浅くなるときに戻先の拡張SVCに対応するブレーク関数が呼び出される。タスク例外ハンドラが呼び出されるのは、タスク部に戻ってからとなる。

タスク例外コード0の場合、タスク例外ハンドラを終了することはできないため、tk_end_tex を発行することはできない。必ず tk_ext_tsk または tk_exd_tsk でタスクを終了しなければならない。タスク例外コード0を処理中に tk_end_tex を発行した場合の動作は不定(実装依存)である。

タスク例外ハンドラ以外から発行することはできない。タスク例外ハンドラ以外から発行した場合の動作は不定(実装依存)である。

補足事項

tk_end_tex(TRUE) とすると、ペンディングされたタスク例外がある場合、tk_end_tex の直後にさらにタスク例外ハンドラが呼び出されることになる。そのため、スタックが戻されないままにタスク例外ハンドラが呼び出されることとなり、スタックオーバーフローの可能性がある。

通常は tk_end_tex(FALSE)を利用し、次のようにタスク例外が残っている間繰り返し処理するようにするとよい。

void texhdr( INT texcd )
{
	if ( texcd == 0 ){
		/*
			タスク例外0用の処理
		*/
		tk_exd_tsk();
	}

	do {
		/*
			タスク例外1~31用の処理
		*/
	} while ( (texcd = tk_end_tex(FALSE)) > 0 );
}

厳密には、tk_end_tex で0が返されループを終了してから texhdr を抜けるまでの間にタスク例外が発生した場合には、スタックが戻されずに texhdr に再入する可能性はある。しかし、タスク例外はソフトウェア的なものであり、タスクの実行と無関係に発生することは通常ないため、実用上は問題ないと思われる。

tk_ref_tex - タスク例外の状態参照

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_ref_tex (ID tskid , T_RTEX *pk_rtex );

パラメータ

ID tskid Task IDタスクID
T_RTEX* pk_rtex Packet to Refer Task Exception Statusタスク例外状態を返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード

pk_rtex の内容

UINT pendtex Pending Task Exception発生しているタスク例外
UINT texmask Task Exception Mask許可されているタスク例外
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_OK 正常終了
E_ID 不正ID番号(tskid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(tskid のタスクが存在しない)
E_PAR パラメータエラー(pk_rtex が不正)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tskid で示された対象タスクのタスク例外の状態を参照する。

pendtex は現在発生しているタスク例外を示す。タスク例外の発生からタスク例外ハンドラが呼び出されるまでの間、pendtex に示される。

texmask は許可されているタスク例外を示す。

pendtex, texmask とも、1<<タスク例外コードのビット値として表した値である。

tskidTSK_SELF=0によって自タスクの指定を行うことができる。ただし、タスク独立部から発行したシステムコールで tskidTSK_SELF=0を指定した場合には、E_ID のエラーとなる。