T-Kernelでは、C言語を標準的な高級言語として使用することにしており、C言語からシステムコールを実行する場合のインタフェース方法を標準化している。
一方、アセンブリ言語のインタフェース方法は実装定義とする。アセンブリ言語でプログラムを作成する場合でも、C言語のインタフェースを利用して呼び出す方法を推奨する。これにより、アセンブリ言語で作成したプログラムも同一CPUであればOSが変わっても移植性が確保できる。
システムコールインタフェースでは、次のような共通原則を設けている。
システムコールはすべてC言語の関数として定義される。
関数としての戻値は、0または正の値が正常終了、負の値がエラーコードとなる。
システムコールインタフェースの処理部分(システムコールを表す関数の中から、実際にT-Kernelの機能を呼び出す部分)は、アセンブリ言語で書かれたライブラリとして実装される。これをインタフェースライブラリと呼ぶ。移植性への配慮から、インタフェースライブラリの実装には、C言語のマクロやインライン関数、インラインアセンブラなどを用いない。
システムコールのC言語インタフェースのうち、パケットやポインタを使ってパラメータを渡すものについては、T-Kernelがポインタ参照先のパラメータを書き換えないことを明示するために、CONSTという修飾子を付けている。
CONSTは、C言語の const
修飾子を意図したものであるが、const
修飾子に未対応のプログラムが混在した場合に、#defineのマクロ機能を使ってコンパイラのチェックを無効化できるように、const
と類似した別名を使っている。
具体的なCONSTの使い方は以下のようになる。なお、詳細は開発環境に依存する。
共通のインクルードファイルに次の記述を含める。
/* TKERNEL_CHECK_CONST の定義がある場合に const のチェックを有効化 */ #ifdef TKERNEL_CHECK_CONST #define CONST const #else #define CONST #endif
プログラム中の関数定義やシステムコールの定義は、CONSTを用いて記述する。
Makefile 内の指定で const
を有効化する。(推奨)
T-Kernel 2.0以降では、プログラム中にCONSTを明示し、const
のチェックを有効にして運用することを強く推奨する。
T-Kernel 1.0との差異 | |
---|---|
システムコールのC言語インタフェースにCONSTを追加し、 |
次のシステムコールは、タスク独立部およびディスパッチ禁止状態から発行できる。
システムコール名称 | 説明 |
---|---|
tk_sta_tsk | タスク起動 |
tk_wup_tsk | 他タスクの起床 |
tk_rel_wai | 他タスクの待ち状態解除 |
tk_sus_tsk | 他タスクを強制待ち状態へ移行 |
tk_sig_sem | セマフォ資源返却 |
tk_set_flg | イベントフラグのセット |
tk_sig_tev | タスクイベントの送信 |
tk_rot_rdq | タスクの優先順位の回転 |
tk_get_tid | 実行状態タスクのタスクID参照 |
tk_sta_cyc | 周期ハンドラの動作開始 |
tk_stp_cyc | 周期ハンドラの動作停止 |
tk_sta_alm | アラームハンドラの動作開始 |
tk_sta_alm_u | アラームハンドラの動作開始(マイクロ秒単位) |
tk_stp_alm | アラームハンドラの動作停止 |
tk_ref_tsk | タスク状態参照 |
tk_ref_tsk_u | タスク状態参照(マイクロ秒単位) |
tk_ref_cyc | 周期ハンドラ状態参照 |
tk_ref_cyc_u | 周期ハンドラ状態参照(マイクロ秒単位) |
tk_ref_alm | アラームハンドラ状態参照 |
tk_ref_alm_u | アラームハンドラ状態参照(マイクロ秒単位) |
tk_ref_sys | システム状態参照 |
tk_ret_int | 割込みハンドラから復帰(アセンブリ言語で記述された割込みハンドラからのみ発行可能) |
上記以外のシステムコールがタスク独立部およびディスパッチ禁止状態から発行できるか否かは実装依存である。
システムコールを呼び出すことのできる保護レベルを制限することができる。この場合、指定した保護レベルより低い保護レベルで動作しているタスク(タスク部)からシステムコールを発行した場合に、E_OACV エラーとする。
拡張SVCの呼出は制限されない。
例えば、保護レベル1より低い保護レベルからのシステムコールの呼出を禁止した場合、保護レベル2,3で実行しているタスクからはシステムコールは発行できなくなる。つまり、保護レベル2,3で動作しているタスクは、拡張SVCしか発行できないということになり、サブシステムの機能のみを使ってプログラムすることになる。
これは、T-KernelをT-Kernel Extensionと組み合わせる場合、T-Kernel Extensionの仕様に基づくタスクからT-Kernelの機能を直接操作させないために使用する。T-Kernelをマイクロカーネルとして使用するための機能である。
システムコール呼出制限をする保護レベルは、システム構成情報管理機能により設定する。システム構成情報管理機能については、システム構成情報管理機能項T-Kernel/SMの機能章を参照のこと。
システムコールへ渡すパラメータのいくつかは、パケット形式になっている。このパケット形式のパラメータには、システムコールへ情報を渡す入力パラメータとなるもの(T_CTSKなど)とシステムコールから情報を返される出力パラメータとなるもの(T_RTSKなど)がある。
これらパケット形式のパラメータには、実装独自の情報を追加することができる。ただし、標準仕様で定義されているデータの型および順序を変更してはならず、削除してもいけない。実装独自の情報を追加する場合は、標準仕様で定義されているものの後ろに追加しなければならない。
システムコールへの入力パラメータとなるパケット(T_CTSKなど)では、実装独自で追加された情報が未初期化(メモリの内容が不定)のまま、システムコールを呼び出した場合でも正常に動作するようにしなければならない。
通常は、追加した情報に有効な値が入っていることを示すフラグを標準仕様に含まれている属性フラグの実装独自領域に定義する。そのフラグがセットされている(1)場合にのみ追加した情報を使用し、セットされていない(0)場合にはその追加情報は未初期化(メモリの内容が不定)であるとして、デフォルト値を適用する。
これは、標準仕様の範囲内で作成されたプログラムを、再コンパイルのみで実装独自の機能拡張を行われたOS上で動作させるための規定である。
機能コードは、システムコールを識別するために、各システムコールに割り付けられる番号である。
システムコールの機能コードは特に定めない。すべて実装定義とする。
拡張SVCの機能コードについては、tk_def_ssy を参照。
システムコールの返値は原則として符号付きの整数で、エラーが発生した場合には負の値のエラーコード、処理を正常に終了した場合は E_OK(=0)または正の値とする。正常終了した場合の返値の意味はシステムコール毎に規定する。この原則の例外として、呼び出されるとリターンすることのないシステムコールがある。リターンすることのないシステムコールは、C言語インタフェースでは返値を持たないもの(すなわちvoid型の関数)として宣言する。
エラーコードは、メインエラーコードとサブエラーコードで構成される。エラーコードの下位16ビットがサブエラーコード、残りの上位ビットがメインエラーコードとなる。メインエラーコードは、検出の必要性や発生状況などにより、エラークラスに分類される。T-Kernel/OSではサブエラーコードは使用せず、常に0となる。
#define MERCD(er) ( (ER)(er) >> 16 ) /* メインエラーコード */ #define SERCD(er) ( (H)(er) ) /* サブエラーコード */ #define ERCD(mer, ser) ( (ER)(mer) << 16 | (ER)(UH)(ser) )
待ち状態に入る可能性のあるシステムコールには、タイムアウトの機能を持たせる。タイムアウトは、指定された時間が経過しても処理が完了しない場合に、処理をキャンセルしてシステムコールからリターンするものである(この時、システムコールは E_TMOUT エラーを返す)。
そのため、「システムコールがエラーコードを返した場合には、システムコールを呼び出したことによる副作用はない」という原則より、タイムアウトした場合には、システムコールを呼び出したことで、システムの状態は変化していないのが原則である。ただし、システムコールの機能上、処理のキャンセル時に元の状態に戻せない場合は例外とし、システムコールの説明でその旨を明示する。
タイムアウト時間を0に設定すると、システムコールの中で待ち状態に入るべき状況になっても、待ち状態には入らない。そのため、タイムアウト時間を0としたシステムコール呼出では、待ち状態に入る可能性がない。タイムアウト時間を0としたシステムコール呼出を、ポーリングと呼ぶ。すなわち、ポーリングを行うシステムコールでは、待ち状態に入る可能性がない。
各システムコールの説明では、タイムアウトがない(言い換えると、永久待ちの)場合の振舞いを説明するのを原則とする。システムコールの説明で「待ち状態に入る」ないしは「待ち状態に移行させる」と記述されている場合でも、タイムアウト時間を指定した場合には、指定時間経過後に待ち状態が解除され、メインエラーコードを E_TMOUT としてシステムコールからリターンする。また、ポーリングの場合には、待ち状態に入らずにメインエラーコードを E_TMOUT としてシステムコールからリターンする。
タイムアウト指定(TMO型およびTMO_U型)は、正の値でタイムアウト時間、TMO_POL(=0)でポーリング、TMO_FEVR(=-1)で永久待ちを指定する。タイムアウト時間が指定された場合、タイムアウトの処理は、システムコールが呼び出されてから、指定された以上の時間が経過した後に行うことを保証しなければならない。
補足事項 | |
---|---|
ポーリングを行うシステムコールでは待ち状態に入らないため、それを呼び出したタスクの優先順位は変化しない。 一般的な実装においては、タイムアウト時間に1が指定されると、システムコールが呼び出されてから2回めのタイマ割込み(「タイムティック」と呼ぶ場合がある)でタイムアウト処理を行う。タイムアウト時間に0を指定することはできないため(0は TMO_POL に割り付けられている)、このような実装では、システムコールが呼び出された後の最初のタイマ割込みでタイムアウトすることはない。 |
イベントの発生する時刻を、システムコールを呼び出した時刻などからの相対値で指定する場合には、相対時間(RELTIM型またはRELTIM_U型)を用いる。相対時間を用いてイベントの発生時刻が指定された場合、イベントの処理は、基準となる時刻から指定された以上の時間が経過した後に行うことを保証しなければならない。イベントの発生間隔など、イベントの発生する時刻以外を指定する場合にも、相対時間(RELTIM型またはRELTIM_U型)を用いる。その場合、指定された相対時間の解釈方法は、それぞれの場合毎に定める。時刻を絶対値で指定する場合には、システム時刻(SYSTIM型またはSYSTIM_U型)を用いる。T-Kernelには現在のシステム時刻を設定する機能が用意されているが、この機能を用いてシステム時刻を変更した場合にも、相対時間を用いて指定されたイベントが発生する実世界の時刻(これを実時刻と呼ぶ)は変化しない。言い換えると、相対時間を用いて指定されたイベントが発生するシステム時刻は変化することになる。
基準時間1ミリ秒、64ビットの符号付整数
typedef struct systim { W hi; /* 上位32ビット */ UW lo; /* 下位32ビット */ } SYSTIM;
基準時間1マイクロ秒、64ビットの符号付整数
typedef D SYSTIM_U; /* 64ビット */
基準時間1ミリ秒、32ビットの符号なし整数(UW)
typedef UW RELTIM;
基準時間1マイクロ秒、64ビットの符号なし整数(UD)
typedef UD RELTIM_U; /* 64ビットでマイクロ秒単位の相対時間 */
基準時間1ミリ秒、32ビットの符号付整数(W)
typedef W TMO;
TMO_FEVR=(-1)で永久待ちを指定できる。
基準時間1マイクロ秒、64ビットの符号付整数(D)
typedef D TMO_U; /* 64ビットでマイクロ秒単位のタイムアウト */
TMO_FEVR=(-1)で永久待ちを指定できる。
補足事項 | |
---|---|
RELTIM, RELTIM_U, TMO, TMO_Uで指定された時間は、指定された時間以上経過した後にタイムアウト等が起こることを保証しなければならない。例えば、タイマ割込み間隔が1ミリ秒で、タイムアウト時間として1ミリ秒が指定された場合、システムコール呼出後の2回目のタイマ割込みでタイムアウトする。(1回目のタイマ割込みでは1ミリ秒未満である。) |
T-Kernelの時間管理機能における実際の時間分解能は、「標準システム構成情報項T-Kernel/SMの機能章」の「タイマ割込み間隔」(TTimPeriod)によって指定される。「タイマ割込み間隔」(TTimPeriod)のデフォルトは10ミリ秒である。実際に設定可能な範囲や動作可能な範囲は実装依存である。
「タイマ割込み間隔」を短くすると、タイマ割込みによるシステムのオーバーヘッドが増大するほか、タイマに供給されるクロックやハードウェアの制限により、時計の誤差が大きくなる場合がある。