第11章  システム状態管理機能
 本章では,RI600PXが提供しているシステム状態管理機能について解説しています。
 
 RI600PXにおけるシステム状態管理機能では,タスクの優先順位の回転,ディスパッチ禁止状態への遷移などといったシステムの状態を操作する機能のほかに,コンテキスト種別の参照,CPUロック状態の参照などといったシステムの状態を参照する機能も提供しています。
 
 タスクの優先順位の回転は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
 
 -	 
rot_rdq,
irot_rdq
パラメータ
tskpriで指定された優先度に対応したレディ・キューの先頭タスクを最後尾につなぎかえ,タスクの実行順序を明示的に変更します。
 
 
 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 #pragma cychandler Cychdr1              /*備考5参照*/
 
 void Cychdr1 ( VP_INT exinf );          /*備考5参照*/
 
 void Cychdr1 ( VP_INT exinf );          /*周期ハンドラ*/
 
 {
         PRI     tskpri = 8;             /*変数の宣言,初期化*/
 
 
         ............
         ............
 
 
         irot_rdq ( tskpri );            /*タスクの優先順位の回転*/
 
 
         ............
         ............
 
 
         return;                         /*周期ハンドラの終了*/
 }
 
 | 
 
 備考1	 本サービス・コールでは,レディ・キューの対象優先度にタスクが1つもキューイングされていなかった場合には,何も処理は行わず,エラーとしても扱いません。
 
 備考2	 本サービス・コールを周期ハンドラなどから一定周期で発行することにより,ラウンドロビン・スケジューリングを実現することができます。
 
 備考3	 RI600PXにおけるレディ・キューは,優先度をキーとしたハッシュ・テーブルであり,実行可能な状態(RUNNING状態またはREADY状態)へと遷移したタスクがFIFO順でキューイングされます。このため,スケジューラは,起動された際にレディ・キューの優先度高位から検出処理を実行し,キューイングされているタスクを検出した場合には,該当優先度の先頭タスクにCPUの利用権を与えることにより,RI600PXのスケジューリング方式(優先度方式,FCFS方式)を実現しています。
 
 備考4	 
tskpriに
TPRI_SELFを指定すると,自タスクのベース優先度を対象とします。
ミューテックスをロック中のタスクの現在優先度は,ベース優先度と異なる場合があります。この場合,そのタスクが本サービス・コールで
tskpriに
TPRI_SELFを指定しても,自タスクが属する現在優先度のレディ・キューを回転することはできません。
 
 備考5	 システム・コンフィギュレーション・ファイルで生成した周期ハンドラについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。
 
 RUNNING状態のタスクの参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
 
 -	 
get_tid,
iget_tid
RUNNING状態のタスクのIDをパラメータ
p_tskidで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。
 
 
 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 
 
 void Inthdr ( VP_INT exinf );           /*割り込みハンドラ*/
 
 {
         ID      p_tskid;                /*変数の宣言*/
 
 
         ............
         ............
 
 
         iget_tid ( &p_tskid );          /*RUNNING状態のタスクの参照*/
 
 
         ............
         ............
 
 
         return;                         /*割り込みハンドラの終了*/
 }
 
 | 
 
 備考1	 本サービス・コールでは,RUNNING状態へと遷移しているタスクが存在しなかった場合には,パラメータ
p_tskidで指定された領域に
TSK_NONEを格納します。
 
 CPUロック状態では,タスクのスケジューリングは禁止され,カーネル管理割り込みもマスクされます。つまり,カーネル管理外割り込みハンドラを除くすべての処理プログラムに対して,排他的に処理を行うことができます。
 
 以下のサービス・コールによって,CPUロック状態へ移行します。
 
  
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 自タスクの終了と削除(CPUロック状態は解除されます)
  
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
 
 以下に,“CPUロック状態”を利用した際の処理の流れを示します。
 
 以下に,CPUロック状態への移行とその解除の記述例を示します。
 
 
 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 #pragma task Task1                      /*備考7参照*/
 
 void Task1 ( VP_INT exinf );            /*備考7参照*/
 
 void Task1 ( VP_INT exinf )
 
 {
         ............
         ............
 
 
         loc_cpu ( );                    /*CPUロック状態への移行*/
 
 
         ............                    /*CPUロック状態*/
         ............
 
 
         unl_cpu ( );                    /*CPUロック状態の解除*/
 
 
         ............
         ............
 }
 
 | 
 
 備考2	 
loc_cpu,
iloc_cpuでは,ロック要求のキューイングが行われません。このため,すでにCPUロック状態の場合には,何も処理は行わず,エラーとしても扱いません。
 
 備考3	 
unl_cpu,
iunl_cpuでは,解除要求のキューイングが行われません。このため,すでに非CPUロック状態の場合には,何も処理は行わず,エラーとしても扱いません。
 
 備考5	 CPUロック状態の期間は基本クロック用タイマ割り込みはマスクされます。このため,CPUロック状態の期間が長くなると,
時間管理機能で扱う時間が遅れる場合があります。
 
 備考7	 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。
 
 複数のタスクやハンドラから呼ばれる関数では,現在のCPUロック状態を参照したい場合があります。このような場合には,
sns_locを使用します。
 
 -	 
sns_loc
本サービス・コールは,CPUロック状態か否かを調べます。本サービス・コールは,戻り値として,CPUロック状態の場合はTRUE,CPUロック解除状態の場合はFALSEを返します。
以下に,本サービス・コールの記述例を示します。
 
 
 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 
 
 void CommonFunc ( void );
 
 void CommonFunc ( void )
 
 {
         BOOL ercd;                      /*変数の宣言*/
 
 
         ............
         ............
 
 
         ercd = sns_loc ( );             /*CPUロック状態の参照*/
 
 
         if ( ercd == TRUE ) {
                 ............            /*CPUロック状態*/
                 ............
         } else if ( ercd == FALSE ) {
                 ............            /*非CPUロック状態*/
                 ............
         }
 
 
         ............
         ............
 }
 
 | 
 
 ディスパッチ禁止状態では,タスクのスケジューリングが禁止されるため,他のタスクに対して排他的に処理を行うことができます。
 
 以下のサービス・コールによって,ディスパッチ禁止状態へ移行します。また,
chg_imsによって割り込みマスク(PSW.IPL)を0以外に変更したときにも,ディスパッチ禁止状態へ移行します。
 
 以下に,“ディスパッチ禁止状態”を利用した際の処理の流れを示します。
 
 
 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 #pragma task Task1                      /*備考5参照*/
 
 void Task1 ( VP_INT exinf );            /*備考5参照*/
 
 void Task1 ( VP_INT exinf )
 
 {
         ............
         ............
 
 
         dis_dsp ( );                    /*ディスパッチ禁止状態への移行*/
 
 
         ............                    /*ディスパッチ禁止状態*/
         ............
 
 
         ena_dsp ( );                    /*ディスパッチ禁止状態の解除*/
 
 
         ............
         ............
 }
 
 | 
 
 備考1	 ディスパッチ禁止状態の解除は,
dis_dspを発行したタスクがDORMANT状態へ遷移する以前に行う必要があります。
 
 備考2	 
dis_dspでは,禁止要求のキューイングが行われません。このため,すでにディスパッチ禁止状態の場合には,何も処理は行わず,エラーとしても扱いません。
 
 備考3	 
ena_dspでは,許可要求のキューイングが行われません。このため,すでにディスパッチ許可状態の場合には,何も処理は行わず,エラーとしても扱いません。
 
 備考4	 ディスパッチ禁止状態の間に“自タスクを状態遷移させる可能性のあるサービス・コール(
wai_sem,
wai_flgなど)”を発行した場合には,要求条件の即時成立/不成立を問わず,戻り値としてE_CTXを返します。
 
 備考5	 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。
 
 複数のタスクから呼ばれる関数では,現在のディスパッチ禁止状態を参照したい場合があります。このような場合には,
sns_dspを使用します。
 
 -	 
sns_dsp
本サービス・コールは,ディスパッチ禁止状態か否かを調べます。本サービス・コールは,戻り値として,ディスパッチ禁止状態の場合はTRUE,ディスパッチ許可状態の場合はFALSEを返します。
以下に,本サービス・コールの記述例を示します。
 
 
 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 
 
 void CommonFunc ( void );
 
 void CommonFunc ( void )
 
 {
         BOOL ercd;                      /*変数の宣言*/
 
 
         ............
         ............
 
 
         ercd = sns_dsp ( );             /*ディスパッチ禁止状態の参照*/
 
 
         if ( ercd == TRUE ) {
                 ............            /*ディスパッチ禁止状態*/
                 ............
         } else if ( ercd == FALSE ) {
                 ............            /*ディスパッチ許可状態*/
                 ............
         }
 
 
         ............
         ............
 }
 
 | 
 
 複数のタスクやハンドラから呼ばれる関数では,現在のコンテキスト種別を参照したい場合があります。このような場合には,
sns_ctxを使用します。
 
 -	 
sns_ctx
本サービス・コールは,本サービス・コールを発行した処理プログラムのコンテキスト種別を調べます。本サービス・コールは,戻り値として,非タスク・コンテキストの場合はTRUE,タスク・コンテキストの場合はFALSEを返します。
以下に,本サービス・コールの記述例を示します。
 
 
 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 
 
 void CommonFunc ( void );
 
 void CommonFunc ( void )
 
 {
         BOOL ercd;                      /*変数の宣言*/
 
 
         ............
         ............
 
 
         ercd = sns_ctx ( );             /*コンテキスト種別の参照*/
 
 
         if ( ercd == TRUE ) {
                 ............            /*非タスク・コンテキスト処理*/
                 ............
         } else if ( ercd == FALSE ) {
                 ............            /*タスク・コンテキスト処理*/
                 ............
         }
 
 
         ............
         ............
 }
 
 | 
 
 以下のいずれかの条件を満たすときをディスパッチ保留状態と呼びます。
 
 複数のタスクやハンドラから呼ばれる関数では,現在のディスパッチ保留状態を参照したい場合があります。このような場合には,
sns_dpnを使用します。
 
 -	 
sns_dpn
本サービス・コールは,ディスパッチ保留状態か否かを調べます。本サービス・コールは,戻り値として,ディスパッチ保留状態の場合はTRUE,ディスパッチ保留状態でない場合はFALSEを返します。
以下に,本サービス・コールの記述例を示します。
 
 
 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 
 
 void CommonFunc ( void );
 
 void CommonFunc ( void )
 
 {
         BOOL ercd;                      /*変数の宣言*/
 
 
         ............
         ............
 
 
         ercd = sns_dpn ( );             /*ディスパッチ保留状態の参照*/
 
 
         if ( ercd == TRUE ) {
                 ............            /*ディスパッチ保留状態*/
                 ............
         } else if ( ercd == FALSE ) {
                 ............            /*非ディスパッチ保留状態*/
                 ............
         }
 
 
         ............
         ............
 }
 
 |