ER vend_exc(void); ER vdis_fex(ID tskid, UINT fexcmsk); ER vena_fex(ID tskid, UINT fexcmsk); ER vdef_fex(ID tskid, FP fexchdr); ER vras_fex(ID tskid, INT fexcode); ER vdef_brk(FN s_fncd, FP brkhdr); ER vdis_wai(ID tskid, UINT waitptn, UINT *tskwait); ER vena_wai(ID tskid); ER vchg_slt(ID tskid, INT slicetime); ER vinf_tsk(T_INFTSK *pk_inftsk, ID tskid, BOOL clr); ER vset_tev(ID tskid, INT tskevt); ER vwai_tev(INT tevmsk, TMO tmout); ER veif_tsk(VP *oldinf, VP newinf, ID tskid); ER vref_svc(T_RSVC* pk_rsvc, FN s_fncd); ER vpget_bks(VP *p_bks, VP *p_grp, INT nblk, UINT atr); ER vrel_bks(VP *p_grp, VP bks); ER vatr_bks(UINT *p_atr, VP bks); ER vref_bks(T_RBKS *pk_rbks); ER vset_pow( UINT pwmode ); ER vget_otm(SYSTIME *pk_tim);
typedef struct t_rtsk { VP exinf; /* 拡張情報 */ PRI tskpri; /* 現在の優先度 */ UINT tskstat; /* タスク状態 */ UINT tskwait; /* 待ち要因 */ ID wid; /* 待ちオブジェクトID */ INT wupcnt; /* 起床要求キューイング数 */ INT suscnt; /* SUSPEND要求ネスト数 */ → UINT waitmask; /* 禁止待ち要因 */ → INT slicetime; /* スライスタイム */ → UINT fexcmsk; /* 強制例外ビットマスク */ → UINT tskevent; /* タスクイベント発生状態 */ } T_RTSK; → TTW_EV1 0x01000000 /* タスクイベント#1待ち */ → TTW_EV2 0x02000000 /* タスクイベント#2待ち */ → TTW_EV3 0x04000000 /* タスクイベント#3待ち */ → TTW_EV4 0x08000000 /* タスクイベント#4待ち */ → TTW_EV5 0x10000000 /* タスクイベント#5待ち */ → TTW_EV6 0x20000000 /* タスクイベント#6待ち */ → TTW_EV7 0x40000000 /* タスクイベント#7待ち */ → TTW_EV8 0x80000000 /* タスクイベント#8待ち */ → typedef struct t_inftsk { → UINT stime; /* システムタイムカウンタ */ → UINT utime; /* ユーザタイムカウンタ */ → } T_INFTSK; typedef struct t_rsem { VP exinf; /* 拡張情報 */ BOOL_ID wtsk; /* 待ちタスクの有無 */ INT semcnt; /* 現在のセマフォカウント値 */ → ID gtsk; /* ロック型セマフォ獲得タスクID */ } T_RSEM; → TA_LOCKSEM 0x00010000 /* ロック型セマフォを指定 */ typedef struct t_rsys { INT sysstat; /* システム状態 */ ID runtskid; /* 実行状態にあるタスクの ID */ ID schedtskid; /* 実行状態にすべきタスクのID */ → INT cpuload; /* システムのロード(0-10000) */ } T_RSYS; → typedef struct t_rcfg { → INT timer_period; /* タイマー割込間隔 (ms) */ → INT default_slice_time; /* デフォルト連続実行時間 (ms) */ → #ifdef i386 → UW cpu_type; /* CPU タイプ */ → #endif → } T_RCFG; → typedef struct t_rsvc { → ATR svcatr; /* 拡張SVCハンドラ属性 */ → #ifdef V810 → VP textp; /* テキスト領域先頭アドレス */ → VP globp; /* グローバル領域先頭アドレス */ → #endif → } T_RSVC; → typedef struct t_rbks { → INT blksz; /* ブロックサイズ (バイト数) */ → INT total; /* 全ブロック数 */ → INT free; /* 残りブロック数 */ → } T_RBKS; → #define TPW_DOSUSPEND 1 /* サスペンド状態へ移行 */ → #define TPW_DISLOWPOW 2 /* 低消費電力モード切替禁止 */ → #define TPW_ENALOWPOW 3 /* 低消費電力モード切替許可 */
→ EV_DISWAI (-226) /* 待ち禁止による待ち解除 */ → EV_LOCKSEM (-227) /* ロック型セマフォの不正操作 */
拡張 SVC の機能コードの下位 8 ビットのみを拡張 SVC 番号とする。 残りの上位ビットは任意に使用できる。 ただし、最上位ビット ( MSB ) は 0 でなければならない。 機能コードを拡張 SVC ハンドラへのパラメータとして追加する。
i386 の場合 ER svchdr( VP para, FN s_fncd )
ER vref_svc(T_RSVC* pk_rsvc, FN s_fncd)
s_fncd
で示す拡張SVCが定義されていれば、 その定義情報を*pk_rsvc
へ返す。
同一優先度のタスクはラウンドロビンスケジューリングを行う。
タスク毎に設定される最大割り当てタイム(slicetime
)を経過すると、
自動的にその優先度のレディキューの最後に回される。
タスク生成時など休止(DORMANT)状態になるとき、
デフォルト値として slicetime = 0
が設定される。
slicetime = 0
のタスクはラウンドロビンとならず、
FCFS(First Come First Service) 方式でスケジューリングされる。
ER vchg_slt(ID tskid, INT slicetime)
slicetime
(単位ミリ秒)を設定する。tskid : TSK_SELF 可 slicetime : < 0 はエラー
ref_tsk()
により現在の slicetime
が参照可能。
(T_RTSK
に slicetime
を追加)
ref_cfg()
によりデフォルトの
slicetime (default_slice_time)
が参照可能
(T_RCFG
にフィールド追加)。
タスクに固有なイベントを8個用意し、
その個々のイベントに対して slp_tsk()
〜 wup_tsk()
と同様な単純なタスクの同期機能をサポートする。
ER vwai_tev(INT tevmsk, TMO tmout)
tevmsk
で指定した、 いずれかのタスクイベント(tskevt
= 1〜8)の発生を待つ。 イベントの発生またはタイムアウトで待ちが解除される。tevmsk
は、1 << (tskevt-1)
で表わすビット値の OR で指定する。 リターン時にtevmsk
で指定したイベントはすべてクリアされる。 イベント発生により待ちが解除されたときには、 リターン値にタスクイベントの発生状況を、tevmsk
と同じビット値の形式で返す。
rel_wai()
で待ちは無条件に解除される。vena_wai()
,vdis_wai()
が適用される。
ER vset_tev(ID tskid, INT tskevt) tskid : TSK_SELF 不可。 tskevt : 1 〜 8
タスクのイベントを発生させる。
wup_tsk()
と異なり、 同一イベントの発生回数は保持されない(発生の有無のみ保持されます)。
タスクのイベントの発生状態は保存され、
ref_tsk()
で参照可能
(T_RTSK
に tskevent
を追加)。
タスクの待ち要因として、
TTW_EV1
〜 TTW_EV8
を追加。
タスクが指定した待ち状態に入ることを禁止する機能。 また、既に禁止する待ち状態に入っていた場合は、待ちを強制解除する機能。
待ち状態禁止機能により、待ちに入らなかった場合、あるいは待ちが強制解除
された場合は、EV_DISWAI
( -226 ) のエラーコードが戻る。
禁止する待ち状態は、以下の待ち要因のパターン
(TTW_*
) で指定される。
[TTW_SLP]|[TTW_DLY ]|[TTW_NOD]|[TTW_FLG]|[TTW_SEM]| [TTW_MBX]|[TTW_SMBF]|[TTW_MBF]|[TTW_CAL]|[TTW_ACP]| [TTW_RDV]|[TTW_MPL ]|[TTW_MPF]|[TTW_PIS]|[TTW_EV1〜TTW_EV8]
TTW_RDV
は TTW_CAL
と共に指定しなくてはいけない。
タスクに対して設定されている禁止待ち状態は、
ref_tsk()
で参照可能
(T_RTSK
に waitmask
を追加)
拡張 SVC 処理中に設定された禁止待ち状態は、 拡張 SVC の処理後に元の状態に戻る。
ER vdis_wai(ID tskid, UW waitptn, UW *tskwait)
tskid
で示されたタスクに対して、waitptn
で指定した待ちを禁止する。 タスクがすでにwaitptn
に含まれる要因で待ちに入っている場合は待ちを強制解除する。 このシステムコールにより、 タスクのwaitmask = waitptn
となる。
tskid :
TSK_SELF
可waitptn :
- 禁止する待ち要因のパターン (
TTW_*
の組み合わせ )*tskwait :
- この呼び出しによって待ち状態の禁止の処理が行われた直後のタスクの待ち要因が設定される。 待ちに入っていない場合 0 が設定される。 0 以外の場合、タスクは
waitmask
には含まれない待ち要因で待ち状態になっている。ref_tsk()
で得られるtskwait
と同である。すでにランデブが成立している場合、
- (例)
- 成立前のランデブは待ちを強制解除したいが、 ランデブ成立後は待ちの強制解除は行いたくない場合。
vdis_wai(tskid, TTW_CAL, &taskwait);taskwait
にはTTW_RDV
が設定される。
ER vena_wai(ID tskid)
tskid
で示されたタスクに対して、待ちを許可する。 このシステムコールにより、 タスクのwaitmask = 0
となる。
tskid : TSK_SELF 可
タスク強制例外は、 例外が発生したタスクのコンテキストで、 かつタスク生成時に指定した保護レベル(リング)で、 強制例外ハンドラを実行する機能である。 強制例外ハンドラは、基本的にタスクの一部として実行されるため、 タスクが使用出来るシステムコールはすべて使用可能である。
強制例外には、0〜31 の 32 種類の例外コードがあり、 0 が最も優先度が高く 31 が最も低くなる。 例外コード 0 は特殊で、他の 1〜31 とは異なる特徴を持つ。
強制例外ハンドラはネストして実行されない。
強制例外ハンドラからリターンすることで、 強制例外によって割り込まれた位置に復帰する。
強制例外ハンドラからリターンせずに、
longjmp()
によりタスク内の任意の位置にジャンプすることも出来る。
強制例外ハンドラ実行中でもネストして実行される。
ユーザースタックポインタをタスク起動時の初期値に設定してから、 強制例外ハンドラが実行される。 ただし、ユーザースタックとシステムスタックが分離されていないシステムでは、 スタックポインタは初期値に戻されない。
強制例外ハンドラから復帰することは出来ない。 必ずタスクを終了しなければならない。
タスク生成時の保護レベル(リング)が TA_RNG0
のタスクに対して、強制例外を使用することは出来ない。
ER vdef_brk(FN s_fncd, FP brkhdr)
拡張SVCのブレーク関数を定義する。 拡張SVCが未登録の時はエラーとなる。 既に定義されていた場合は、後から定義した関数が有効となる。
brkhdr == NADR
の時は定義を解除する。
brkhdr()
はTA_HLNG
のみ。 PIC および PID (Position Independent Code/Data) 対応の場合には、s_fncd
の拡張SVCを定義(def_svc
) した時に指定したベースアドレスが、 高級言語対応ルーチンで設定される。VOID brkhdr(ID tskid) { /* taskid : 対象タスクID */ }
ER vdef_fex(ID tskid, FP fexchdr)
指定したタスクに対して強制例外ハンドラを定義する。 強制例外ハンドラはタスクに対して 1 つのみ定義可能で、 既に定義されていた場合は、後から定義した関数が有効となる。
exchdr == NADR
の時は定義を解除する。ペンディングの強制例外要求はクリアされ、 すべての強制例外は禁止状態となる。
強制例外ハンドラは、
tskid
のタスクのコンテキストで実行される下記の形式の関数です。 ただし、直接fexchdr()
が呼び出されるか否かは、 インプリメントに依存する。 インプリメントによっては、 そのインプリメント固有のエントリールーチンを持つ必要がある (各CPU のインプリメントに関するドキュメントを参照のこと)。PIC および PID (Position Independent Code/Data) 対応の場合には、
tskid
のタスクを生成(cre_tsk
) した時に指定したベースアドレスが設定される。VOID fexchdr(INT fexcode) { /* fexcode : 発生した例外コード 0〜31 */ ::::: /* 例外処理の終了 */ if ( fexcode == 0 ) { ext_tsk() または exd_tsk(); } else { vend_exc(); return または longjmp(); } }
ER vdis_fex(ID tskid, UINT fexcmsk) ER vena_fex(ID tskid, UINT fexcmsk)
指定したタスクに対する強制例外(
fexcode : 0〜31
) を許可/禁止する。fexmask
の1のビットに対応する強制例外を対象とする。強制例外ハンドラが定義されていないときは
E_NOEXS
のエラーとなる。禁止された強制例外の発生は完全に無視される。
強制例外の許可/禁止状態は
ref_tsk()
で取り出せる (T_RTSK
にfexcmsk
を追加)。fexcmsk
は ビット単位のマスク(0:LSB 〜 31:MSB) で0で禁止、1で許可。
ER vras_fex(ID tskid, INT fexcode)
指定したタスクに対して強制例外 (
fexcode
: 0〜31)を発生させる。タスクが拡張SVCやSVCを実行している時は、 タスクに戻る時点で強制例外が発生する。 それまでに発生した強制例外はペンディングされ、 タスクに戻った時点で順次例外ハンドラが起動される。
タスクが強制例外ハンドラを実行中の場合は、
vend_exc()
が実行されるまで、 強制例外はペンディングされる。 ただし、例外コード0の場合はペンディングされず、 ネストして強制例外ハンドラが実行される。タスクが拡張SVCを実行中で、 かつ拡張SVCのブレーク関数が定義されている場合は、 ブレーク関数を実行する。
タスクに強制例外要求がペンディングされている時は、 タスクが拡張SVCを実行し、 その中から何らかのSVCを呼び出した時点、 または拡張SVCをネストして呼び出して戻ってきた時点で 拡張SVCのブレーク関数が実行される。 拡張SVCのブレーク関数は、 1つの拡張SVCに対して1回のみ実行される。
ER vend_exc()
例外ハンドラを終了し、新たな強制例外の発生を許可する。
ペンディングされている強制例外がある場合には、 強制例外ハンドラが実行される。 ペンディングされている強制例外が複数ある場合には、 例外コードの最も小さいものが優先される。
例外コード0の例外ハンドラは、
vend_exc()
を呼び出すことは出来ない。 例外コード0の強制例外ハンドラは、ext_tsk()
またはexd_tsk()
によってタスクを終了しなければならない。
タスクが実行されていた時間を計測する。
タイマー割り込みごとに動作していたタスクをカウントする簡易的な方法。
その時のシステムモードによりユーザかシステムかを区別する。
ER vinf_tsk(T_INFTSK *inf, ID tskid, BOOL clr)
tskid
のタスクの統計情報を取り出す。clr == TRUE
の時は、 統計情報を取り出した後にクリアする。typedef struct { UINT stime; /* システム実行時間 (ms) */ UINT utime; /* ユーザー実行時間 (ms) */ } T_INFTSK;
- ※ システムモード
タスクがシステムオブジェクトにアクセスできる状態のとき 「システム」、 システムオブジェクトにアクセスすると
E_OACV
エラーになる状態のとき「ユーザー」となる。
システムのCPUロードを計測する。
タイマー割り込みごとに何もタスクが動作していない場合をカウントし、
そのカウント値と全体時間からCPUロードを求める簡易的な方法である。
T_RSYS に cpuload を追加 cpuload : 0 〜 10000 の値で、10000 は 100 % を意味する。
ref_sys()
で、
前回の ref_sys()
呼び出し以降のCPUロードを取り出す。
前回の ref_sys()
から 2^32 ms 以上の間隔をあけると、
その結果は保証されない。
cre_por
の poratr
の指定において以下をサポートする。
TA_TPRI H'0...01 呼出待ちタスクがタスク優先度順
タスク終了時に自動的にロックを解放するロック型セマフォ機能。
セマフォ属性として、以下を追加 TA_LOCKSEM 0x00010000
TA_LOCKSEM
の場合の動作:
生成時に semcnt == maxsem == 1
以外は E_PAR
エラー
同一タスクが同一セマフォに wai_sem()
を複数回実行した場合は EV_LOCKSEM
エラ−
wai_sem()
で獲得したセマフォを
sig_sem()
で解放せずにタスクが終了した場合は、
自動的にセマフォを解放する。
指定したセマフォを獲得せずに、即ち wai_sem()
を実行せずに、sig_sem()
を実行した場合は
EV_LOCKSEM
エラー
タスク独立部から呼び出すことはできず、
E_CTX
エラーとなる。
ロック用セマフォ同士のデッドロックを検出する。
ref_sem()
により、
ロック型セマフォを獲得しているタスクの ID を知ることができる。
typedef struct t_rsem { VP exinf; /* 拡張情報 */ BOOL_ID wtsk; /* 待ちタスクの有無 */ INT semcnt; /* 現在のセマフォカウント値 */ ID gtsk; /* ロック型セマフォ獲得タスク ID */ } T_RSEM;
gtsk
はロック型セマフォの場合のみ有効で、
それ以外の場合は常に0を返す。
タスクの拡張情報 (exinf
)を変更する機能である。
ER veif_tsk(VP *oldinf, VP newinf, ID tskid)
指定したタスクの
exinf
を*oldinf
に取り出した後、exinf
の値をnewinf
の値に変更する。oldinf == NADR の時は取り出さない newinf == NADR の時は変更しない。
アラームハンドラの実行後のアラーム番号の自動解放を廃止した。
vdef_alm()
での自動的に割り付けられる
アラーム番号の衝突を避けるため、
実行したアラームハンドラのアラーム番号は自動解放しない。
したがって、vdef_alm()
で定義したアラームハンドラは実際にアラームハンドラが
起動されたかどうかに関わらず、
アラームハンドラが不要になった時点で必ず
def_alm(NADR)
により定義を解除する必要がある。
ER vset_pow( UINT pwmode )
TPW_DOSUSPEND | 1 | サスペンド状態へ移行 |
TPW_DISLOWPOW | 2 | 低消費電力モード切替禁止 |
TPW_ENALOWPOW | 3 | 低消費電力モード切替許可 |
すべてのタスク及びハンドラの実行を停止し、 周辺回路(タイマーや割込コントローラ)を停止し、 電源を切る(サスペンドする)。 電源オンされたら、周辺回路の再起動をし、 すべてのタスク及びハンドラの実行を再開して、 電源を切る前の状態に復帰(リジューム)し、リターンする。
何らかの理由によりリジュームに失敗したときには、 通常(リセット時)のスタートアップ処理を行い、 新たにシステムを立ち上げなおす。
ディスパッチャ内で行われる低消費電力モードへの切替を禁止する
(low_pow
を呼び出さない)。
ディスパッチャ内で行われる低消費電力モードへの切替を許可する。
(low_pow
を呼び出す)
ITRON 起動時のデフォルトは切替許可 (TPW_ENALOWPOW
) となる。
TPW_DISLOWPOW
が指定された場合、その要求回数がカウントされる。
TPW_DISLOWPOW
が要求された回数と同じだけ
TPW_ENALOWPOW
が要求されないと、低消費電力モードは許可されない。
ER vget_otm( SYSTIME *pk_tim )
OS 起動時から現在までの通算稼働時間をミリ秒単位で返す。
稼働時間はset_tim()
による時刻設定の影響を受けず、 常に単調増加する時間となる。
下記の条件の元で、論理空間上で動作する。
ITRON 自身が動作する論理アドレス空間は共有空間であり、 タスク切替等による論理空間の切替により影響されないこと。
ITRON がアクセスするメモリ領域は 常にアクセスできることが保証され、 ページアウトされていないこと。