実行トレース機能は、デバッガがプログラムの実行をトレースするための機能である。実行トレースはフックルーチンを設定することによって行う。
フックルーチンでは、各種の状態をフックルーチンが呼び出された時点の状態に戻してから、フックルーチンから戻らなければならない。ただし、レジスタに関してはC言語の関数の保存規則にしたがって復帰すればよい。
フックルーチン内では、各種の状態を制限の緩い方へ変更してはいけない。例えば、割込み禁止状態で呼び出された場合は、割込みを許可してはいけない。
フックルーチンは、保護レベル0で呼び出される。
フックルーチンは、フックした時点のスタックをそのまま継承している。したがって、あまり多くスタックを消費するとスタックオーバーフローを引き起こす可能性がある。どの程度のスタックが使用可能であるかは、フックされた時点の状況により異なるため不確定である。フックルーチン内で独自スタックに切り替えれば、より安全である。
hsvc
の内容
なし
システムコールおよび拡張SVCの呼出前後に、フックルーチンを設定する。hsvc
に NULL を指定することによりフックルーチンを解除する。
トレースの対象となるのは、μT-Kernel/OSのシステムコール(tk_~)、および拡張SVCである。ただし、実装によるが、一般に tk_ret_int はトレースの対象とならない。
μT-Kernel/DSのシステムコール(td_~)は、トレースの対象とならない。
フックルーチンは、フック対象となるシステムコールや拡張SVCを呼び出したタスクの準タスク部として実行される。そのため、例えばフックルーチン内での自タスクは、システムコールや拡張SVCを呼び出したタスクと同じである。
システムコール内でタスクディスパッチや割込みが起こる場合があるため、enter()
と leave()
が常にペアで連続して呼び出されるとは限らない。また、システムコールから戻らない場合は、leave()
は呼び出されない。
typedef struct td_calinf { システムコール・拡張SVCの呼出元(アドレス)を特定するための情報で、 スタックのバックトレースを行うための情報が含まれることが望ましい。 内容は実装定義となる。 一般的には、スタックポインタやプログラムカウンタなどのレジスタの値である。 } TD_CALINF;
システムコールまたは拡張SVCを呼び出す直前に呼び出される。
戻値に返された値は、そのまま対応する leave()
に渡される。これにより、enter()
と leave()
のペアの確認や任意の情報の受け渡しを行うことができる。
exinf = enter(fncd, &calinf, ... ) ret = システムコール・拡張SVCの実行 leave(fncd , ret, exinf)
システムコールの場合
パラメータは、システムコールのパラメータと同じとなる。
拡張SVCの場合
パラメータは、拡張SVCハンドラに渡されるパケットの状態となる。
fncd
も拡張SVCハンドラに渡されるものと同一である。
システムコールまたは拡張SVCから戻った直後に呼び出される。
システムコールまたは拡張SVCが呼び出された後(システムコールまたは拡張SVCの実行中)にフックルーチンが設定された場合、enter()
が呼び出されずに leave()
のみ呼び出される場合がある。このような場合、exinf
には NULL が渡される。
逆に、システムコールまたは拡張SVCが呼び出された後フックルーチンが解除された場合、enter()
が呼び出されて、leave()
が呼び出されない場合がある。
hdsp
の内容
なし
タスクディスパッチャに、フックルーチンを設定する。hdsp
に NULLを指定することによりフックルーチンを解除する。
フックルーチンは、ディスパッチ禁止状態で呼び出される。フックルーチンでは、μT-Kernel/OSのシステムコール(tk_~)および拡張SVCを呼び出してはいけない。μT-Kernel/DSのシステムコール(td_~)は呼び出すことができる。
タスクの実行が開始・再開されるときに呼び出される。exec()
が呼び出された時点で、すでに tskid
のタスクはRUNNING状態となっている。ただし、tskid
のタスクのプログラムコードが実行されるのは、exec()
から戻った後である。
タスクが実行を停止した時に呼び出される。tskstat
には、停止後のタスクの状態が示され、以下のいずれかとなる。
TTS_RDY | READY状態 (実行可能状態) |
TTS_WAI | WAITING状態 (待ち状態) |
TTS_SUS | SUSPENDED状態 (強制待ち状態) |
TTS_WAS | WAITING-SUSPENDED状態 (二重待ち状態) |
TTS_DMT | DORMANT状態 (休止状態) |
0 | NON-EXISTENT状態 (未登録状態) |
stop()
が呼び出された時点で、すでに tskid
のタスクは tskstat
で示した状態となっている。
hint
の内容
なし
割込みハンドラの呼出前後に、フックルーチンを設定する。フックルーチンの設定は、例外・割込み要因ごとに独立に行うことはできない。すべての例外・割込み要因で共通のフックルーチンを1つのみ設定できる。
hint
に NULL を指定することによりフックルーチンを解除する。
フックルーチンはタスク独立部(割込みハンドラの一部)として呼び出される。したがって、フックルーチンからはタスク独立部から発行可能なシステムコールのみ呼び出すことができる。
なお、フックルーチンを設定できるのは、tk_def_int で TA_HLNG 属性を指定して定義された割込みハンドラのみである。TA_ASM 属性の割込みハンドラのフックはできない。TA_ASM 属性の割込みハンドラをフックしたい場合は、例外・割込みベクタテーブルを直接操作してフックするなどの方法があるが、それらの方法は実装によって異なる。
enter()
および leave()
に渡される引数は、例外・割込みハンドラに渡される引数と同じものである。実装によっては、intno
以外の情報も渡される場合がある。
フックルーチンは、高級言語対応ルーチンから次のようにして呼び出される。
enter(intno); inthdr(intno); /* 例外・割込みハンドラ */ leave(intno);
enter()
は割込み禁止状態で呼び出されることになる。また、割込みを許可してはいけない。leave()
は、inthdr()
から戻ったときの状態となるため、割込み禁止状態は不確定である。
enter()
では、inthdr()
で得ることのできる情報と同じだけの情報を得ることができる。逆に、inthdr()
で得ることのできない情報は enter()
でも得ることはできない。enter()
および inthdr()
で得ることのできる情報としては、intno
が仕様としては保証されているが、それ以外の情報については実装定義である。なお、leave()
では割込み禁止状態など各種の状態が変化している場合があるため、enter()
や inthdr()
と同じだけの情報を得ることができるとは限らない。