μT-Kernelでは、C言語を標準的な高級言語として使用することにしており、C言語からシステムコールを実行する場合のインタフェース方法を標準化している。
一方、アセンブリ言語のインタフェース方法は実装定義とする。アセンブリ言語でプログラムを作成する場合でも、C言語のインタフェースを利用して呼び出す方法を推奨する。これにより、アセンブリ言語で作成したプログラムも同一CPUであればOSが変わっても移植性が確保できる。
システムコールインタフェースでは、次のような共通原則を設けている。
システムコールはすべてC言語の関数として定義される。
関数としての戻値は、0または正の値が正常終了、負の値がエラーコードとなる。
システムコールインタフェースの実装方法は実装依存とする。例えば、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を用いて記述する。
μT-Kernel 3.0以降では、プログラム中にCONSTを明示し、const
のチェックをコンフィギュレーションで有効にして運用することを強く推奨する。
μT-Kernel/OSの次のシステムコールは、タスク独立部およびディスパッチ禁止状態から発行できる。
システムコール名称 | 説明 |
---|---|
tk_sta_tsk | タスク起動 |
tk_ref_tsk | タスク状態参照 |
tk_wup_tsk | 他タスクの起床 |
tk_rel_wai | 他タスクの待ち状態解除 |
tk_sus_tsk | 他タスクを強制待ち状態へ移行 |
tk_sig_tev | タスクイベントの送信 |
tk_sig_sem | セマフォ資源返却 |
tk_set_flg | イベントフラグのセット |
tk_sta_cyc | 周期ハンドラの動作開始 |
tk_stp_cyc | 周期ハンドラの動作停止 |
tk_ref_cyc | 周期ハンドラ状態参照 |
tk_ref_cyc_u | 周期ハンドラ状態参照(マイクロ秒単位) |
tk_sta_alm | アラームハンドラの動作開始 |
tk_sta_alm_u | アラームハンドラの動作開始(マイクロ秒単位) |
tk_stp_alm | アラームハンドラの動作停止 |
tk_ref_alm | アラームハンドラ状態参照 |
tk_ref_alm_u | アラームハンドラ状態参照(マイクロ秒単位) |
tk_ret_int | 割込みハンドラから復帰(アセンブリ言語で記述された割込みハンドラからのみ発行可能) |
tk_rot_rdq | タスクの優先順位の回転 |
tk_get_tid | 実行状態タスクのタスクID参照 |
tk_ref_sys | システム状態参照 |
μT-Kernel/SMの次のAPIは、タスク独立部およびディスパッチ禁止状態から発行できる。
API名称 | 説明 |
---|---|
DI | 外部割込み禁止 |
EI | 外部割込み許可 |
isDI | 外部割込み禁止状態の取得 |
SetCpuIntLevel | CPU内割込みマスクレベルの設定 |
GetCpuIntLevel | CPU内割込みマスクレベルの取得 |
EnableInt | 割込み許可 |
DisableInt | 割込み禁止 |
ClearInt | 割込み発生のクリア |
EndOfInt | 割込みコントローラにEOI発行 |
CheckInt | 割込み発生の検査 |
SetIntMode | 割込みモード設定 |
SetCtrlIntLevel | 割込みコントローラ内割込みマスクレベルの設定 |
GetCtrlIntLevel | 割込みコントローラ内割込みマスクレベルの取得 |
out_b | I/Oポート書込み(バイト) |
out_h | I/Oポート書込み(ハーフワード) |
out_w | I/Oポート書込み(ワード) |
out_d | I/Oポート書込み(ダブルワード) |
in_b | I/Oポート読込み(バイト) |
in_h | I/Oポート読込み(ハーフワード) |
in_w | I/Oポート読込み(ワード) |
in_d | I/Oポート読込み(ダブルワード) |
WaitUsec | 微小待ち(マイクロ秒) |
WaitNsec | 微小待ち(ナノ秒) |
SetOBJNAME | オブジェクト名設定 |
μT-Kernel/DSのすべてのシステムコールは、タスク独立部およびディスパッチ禁止状態から発行できる。
上記以外のシステムコールやAPIがタスク独立部およびディスパッチ禁止状態から発行できるか否かは実装依存である。
システムコールを呼び出すことのできる保護レベルを制限することができる。この場合、指定した保護レベルより低い保護レベルで動作しているタスク(タスク部)からシステムコールを発行した場合に、E_OACV エラーとする。
拡張SVCの呼出は制限されない。
例えば、保護レベル1より低い保護レベルからのシステムコールの呼出を禁止した場合、保護レベル2,3で実行しているタスクからはシステムコールは発行できなくなる。つまり、保護レベル2,3で動作しているタスクは、拡張SVCしか発行できないということになり、サブシステムの機能のみを使ってプログラムすることになる。
この機能は、μT-Kernelをプロセス管理機能などを含むミドルウェアと組み合わせて使用する場合に、ミドルウェアの仕様に基づくタスク(ユーザプロセスなど)からμT-Kernelの機能を直接操作させないために使用する。すなわち、μT-Kernelをマイクロカーネルとして使用するための機能である。この場合、ユーザプロセスのAPIではマイクロカーネルを直接操作することができず、ミドルウェアのみが操作可能となる。
システムコール呼出制限をする保護レベルは、システム構成情報管理機能により設定する。システム構成情報管理機能については、システム構成情報管理機能項μT-Kernel/SMの機能章を参照のこと。
システムコールへ渡すパラメータのいくつかは、パケット形式になっている。このパケット形式のパラメータには、システムコールへ情報を渡す入力パラメータとなるもの(T_CTSKなど)とシステムコールから情報を返される出力パラメータとなるもの(T_RTSKなど)がある。
これらパケット形式のパラメータには、実装独自の情報を追加することができる。ただし、標準仕様で定義されている情報の後ろに追加しなければならない。パラメータの削除については、サービスプロファイルで無効に指定されたものに限って許容され、それ以外のパラメータを削除することは許容されない。なお、標準仕様で定義されているデータの型および順序を変更してはならない。
システムコールへの入力パラメータとなるパケット(T_CTSKなど)では、実装独自で追加された情報が未初期化(メモリの内容が不定)のまま、システムコールを呼び出した場合でも正常に動作するようにしなければならない。
通常は、追加した情報に有効な値が入っていることを示すフラグを標準仕様に含まれている属性フラグの実装独自領域に定義する。そのフラグがセットされている(1)場合にのみ追加した情報を使用し、セットされていない(0)場合にはその追加情報は未初期化(メモリの内容が不定)であるとして、デフォルト値を適用する。
これは、このOSが実装独自の機能拡張をしているかどうかに関わらず、同じアプリケーションプログラムを、再コンパイルのみで動作させるための規定である。
移植ガイドライン | |
---|---|
サービスプロファイルで無効に指定されたパラメータを削除することが認められたため、パラメータパケットの初期化の際には注意が必要である。例えば、T_CTSK構造体に対して以下のような初期化を行うことは移植性の観点から推奨されない。 T_CTSK ctsk = { NULL, TA_HLNG|TA_RNG0|TA_USERBUF, task, 10, 2048, "", buf }; 代わりに、ISO/IEC 9899:1999で規定された構文を用いて、以下のように初期化を行うことが推奨される。 T_CTSK ctsk = { .exinf = NULL, .tskatr = TA_HLNG|TA_RNG0|TA_USERBUF, .task = task, .itskpri = 10, .stksz = 2048, .bufptr = buf }; |
機能コードは、システムコールを識別するために、各システムコールに割り付けられる番号である。
システムコールの機能コードは特に定めない。すべて実装定義とする。
拡張SVCの機能コードについては、tk_def_ssy を参照。
システムコールの戻値は原則として符号付きの整数で、エラーが発生した場合には負の値のエラーコード、処理を正常に終了した場合は E_OK(=0)または正の値とする。正常終了した場合の戻値の意味はシステムコール毎に規定する。この原則の例外として、呼び出されるとリターンすることのないシステムコールがある。リターンすることのないシステムコールは、C言語インタフェースでは戻値を持たないもの(すなわちvoid型の関数)として宣言する。
エラーコードは、メインエラーコードとサブエラーコードで構成される。エラーコードの下位16ビットがサブエラーコード、残りの上位ビットがメインエラーコードとなる。メインエラーコードは、検出の必要性や発生状況などにより、エラークラスに分類される。
#define MERCD(er) ( (ER)(er) >> 16 ) /* メインエラーコード */ #define SERCD(er) ( (H)(er) ) /* サブエラーコード */ #define ERCD(mer, ser) ( (ER)(mer) << 16 | (ER)(UH)(ser) )
ただし、ER型が16ビットの環境ではサブエラーコードを含めず、メインエラーコードをそのままエラーコードとしても良い。この場合、SERCDマクロを定義してはいけない。
#define MERCD(er) ( (ER)(er) ) /* メインエラーコード */ #define ERCD(mer, ser) ( (ER)(mer) )
待ち状態に入る可能性のあるシステムコールには、タイムアウトの機能を持たせる。タイムアウトは、指定された時間が経過しても処理が完了しない場合に、処理をキャンセルしてシステムコールからリターンするものである(この時、システムコールは 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)で永久待ちを指定できる。
関連するサービスプロファイル | |
---|---|
マイクロ秒単位の時間および時刻に関連する型 TMO_U, RELTIM_U, SYSTIM_U は、以下のサービスプロファイルが有効に設定されている場合に限り利用可能であることが保証される。 |
補足事項 | |
---|---|
RELTIM, RELTIM_U, TMO, TMO_Uで指定された時間は、指定された時間以上経過した後にタイムアウト等が起こることを保証しなければならない。例えば、タイマ割込み間隔が1ミリ秒で、タイムアウト時間として1ミリ秒が指定された場合、システムコール呼出後の2回目のタイマ割込みでタイムアウトする。(1回目のタイマ割込みでは1ミリ秒未満である。) システム時刻(SYSTIM_U)がカーネル内部でオーバーフローしてしまうような値を引数に指定した場合のシステムコールの動作は未定義である。 |