第8章 システム状態管理機能
本章では,RI78V4が提供しているシステム状態管理機能について解説しています。
RI78V4におけるシステム状態管理機能では,CPUロック状態への移行,ディスパッチ禁止状態への移行などといったシステムの状態を操作する機能のほかに,コンテキスト種別の参照,CPUロック状態の参照などといったシステムの状態を参照する機能も提供しています。
レディ・キューの回転は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
rot_rdq,
irot_rdq
パラメータ
tskpriで指定された優先度に対応したレディ・キューの先頭タスクを最後尾につなぎかえ,タスクの実行順序を明示的に変更します。
以下に,本サービス・コールを利用した際の状態変化を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_cychdr ( void )
{
PRI tskpri = 8; /*変数の宣言,初期化*/
............
............
irot_rdq ( tskpri ); /*レディ・キューの回転*/
............
............
return; /*周期ハンドラの終了*/
}
|
備考1 本サービス・コールでは,回転要求のキューイングが行われません。このため,該当優先度に対応したレディ・キューにタスクが1つもキューイングされていなかった場合には,何も処理は行わず,エラーとしても扱いません。
備考2 本サービス・コールを周期ハンドラなどから一定周期で発行することにより,ラウンドロビン・スケジューリングを実現することができます。
備考3 レディ・キューは,優先度をキーとしたハッシュ・テーブルであり,実行可能な状態(READY状態,またはRUNNING状態)へと遷移したタスクがFIFO順でキューイングされます。
このため,スケジューラは,起動された際にレディ・キューの優先度高位から“タスクの検出処理”を実行し,キューイングされているタスクを検出した際には,該当優先度の先頭タスクにCPUの利用権を与えることにより,RI78V4の
スケジューリング方式を実現しています。
RUNNING状態のタスクの参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
get_tid,
iget_tid
RUNNING状態のタスクのIDをパラメータ
p_tskidで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_cychdr ( void )
{
ID p_tskid; /*変数の宣言*/
............
............
iget_tid ( &p_tskid ); /*RUNNING状態のタスクの参照*/
............
............
return; /*周期ハンドラの終了*/
}
|
備考 本サービス・コールでは,RUNNING状態へと遷移しているタスクが存在しなかった場合(IDLE状態)には,パラメータ
p_tskidで指定された領域にTSK_NONEを格納します。
CPUロック状態への移行は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
loc_cpu,
iloc_cpu
システム状態種別をCPUロック状態へと変更します。
これにより,本サービス・コールの発行から
unl_cpu,または
iunl_cpuが発行されるまでの間,“マスカブル割り込みの受け付け処理”が禁止されるとともに,サービス・コールの発行が制限されます。
なお,RI78V4では,本サービス・コールの発行から
unl_cpu,または
iunl_cpuが発行されるまでの間にマスカブル割り込みが発生した場合には,該当割り込み処理(割り込みハンドラ)への移行を
unl_cpu,または
iunl_cpuが発行されるまで遅延しています。
また,RI78V4では,CPUロック状態で発行可能なサービス・コールを以下に示したものに制限しています。
以下に,本サービス・コールを利用した際の処理の流れを示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_task ( VP_INT exinf )
{
............
............
loc_cpu ( ); /*CPUロック状態への移行*/
............ /*CPUロック状態*/
............
unl_cpu ( ); /*CPUロック状態の解除*/
............
............
}
|
備考1 本サービス・コールの発行により変更したCPUロック状態の解除は,本サービス・コールを発行した処理プログラムが終了する以前に行う必要があります。
備考2 本サービス・コールでは,ロック要求のキューイングが行われません。このため,システム状態種別がCPUロック状態であった場合には,何も処理は行わず,エラーとしても扱いません。
備考3 RI78V4では,割り込みマスク・フラグ・レジスタMK
xx,および,プログラム・ステータス・ワードPSWのインサービス・プライオリティ・フラグISP
xを操作して,“マスカブル割り込みの受け付け禁止”を実現しています。このため,本サービス・コールの発行から
unl_cpu,または
iunl_cpuが発行されるまでの間,処理プログラムから該当レジスタを操作することは禁止されています。
CPUロック状態の解除は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
unl_cpu,
iunl_cpu
システム状態種別を非CPUロック状態へと変更します。
これにより,
loc_cpu,または
iloc_cpuの発行により禁止されていた“マスカブル割り込みの受け付け処理”が許可されるとともに,および,サービス・コールの発行制限が解除されます。
なお,RI78V4では,
loc_cpu,または
iloc_cpuの発行から本サービス・コールが発行されるまでの間にマスカブル割り込みが発生した場合には,該当割り込み処理(割り込みハンドラ)への移行を本サービス・コールが発行されるまで遅延しています。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_task ( VP_INT exinf )
{
............
............
loc_cpu ( ); /*CPUロック状態への移行*/
............ /*CPUロック状態*/
............
unl_cpu ( ); /*CPUロック状態の解除*/
............
............
}
|
備考1 本サービス・コールでは,解除要求のキューイングが行われません。このため,システム状態種別が非CPUロック状態であった場合には,何も処理は行わず,エラーとしても扱いません。
備考2 RI78V4では,割り込みマスク・フラグ・レジスタMK
xx,および,プログラム・ステータス・ワードPSWのインサービス・プライオリティ・フラグISP
xを操作して,“マスカブル割り込みの受け付け許可”を実現しています。このため,
loc_cpu,または
iloc_cpuの発行から本サービス・コールが発行されるまでの間,処理プログラムから該当レジスタを操作することは禁止されています。
ディスパッチ禁止状態への移行は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
dis_dsp
システム状態種別をディスパッチ禁止状態へと変更します。
これにより,本サービス・コールの発行から
ena_dspが発行されるまでの間,ディスパッチ処理(タスクのスケジューリング処理)が禁止されます。
なお,RI78V4では,本サービス・コールの発行から
ena_dspが発行されるまでの間に“ディスパッチ処理を伴うサービス・コール(
chg_pri,
sig_semなど)”が発行された場合には,キュー操作,カウンタ操作などといった処理を行うだけであり,実際のディスパッチ処理は,
ena_dspが発行されるまで遅延され,一括して行うようにしています。
以下に,本サービス・コールを利用した際の処理の流れを示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_task ( VP_INT exinf )
{
............
............
dis_dsp ( ); /*ディスパッチ禁止状態への移行*/
............ /*ディスパッチ禁止状態*/
............
ena_dsp ( ); /*ディスパッチ禁止状態の解除*/
............
............
}
|
備考1 本サービス・コールでは,禁止要求のキューイングが行われません。このため,システム状態種別がディスパッチ禁止状態であった場合には,何も処理は行わず,エラーとしても扱いません。
備考2 本サービス・コールの発行により変更したディスパッチ禁止状態の解除は,本サービス・コールを発行したタスクがDORMANT状態へと遷移する以前に行う必要があります。
ディスパッチ禁止状態の解除は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
ena_dsp
システム状態種別をディスパッチ許可状態へと変更します。
これにより,
dis_dspの発行により禁止されていたディスパッチ処理(タスクのスケジューリング処理)が許可されます。
なお,RI78V4では,
dis_dspの発行から本サービス・コールが発行されるまでの間に“ディスパッチ処理を伴うサービス・コール(
chg_pri,
sig_semなど)”が発行された場合には,キュー操作,カウンタ操作などといった処理を行うだけであり,実際のディスパッチ処理は,本サービス・コールが発行されるまで遅延され,一括して行うようにしています。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_task ( VP_INT exinf )
{
............
............
dis_dsp ( ); /*ディスパッチ禁止状態への移行*/
............ /*ディスパッチ禁止状態*/
............
ena_dsp ( ); /*ディスパッチ禁止状態の解除*/
............
............
}
|
備考 本サービス・コールでは,許可要求のキューイングが行われません。このため,システム状態種別がディスパッチ許可状態であった場合には,何も処理は行わず,エラーとしても扱いません。
コンテキスト種別の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
sns_ctx
本サービス・コールを発行した処理プログラムのコンテキスト種別(非タスク・コンテキスト,タスク・コンテキスト)を獲得します。
なお,本サービス・コールが正常終了した際には,戻り値として“獲得したコンテキスト種別(TRUE:非タスク・コンテキスト,FALSE:タスク・コンテキスト)”が返されます。
非タスク・コンテキスト: 周期ハンドラ,割り込みハンドラ
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_sub ( void )
{
BOOL ercd; /*変数の宣言*/
............
............
ercd = sns_ctx ( ); /*コンテキスト種別の参照*/
if ( ercd == TRUE ) {
............ /*非タスク・コンテキスト*/
............
} else if ( ercd == FALSE ) {
............ /*タスク・コンテキスト*/
............
}
............
............
}
|
CPUロック状態の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
sns_loc
本サービス・コールを発行した際のシステム状態種別(CPUロック状態,非CPUロック状態)を獲得します。
なお,本サービス・コールが正常終了した際には,戻り値として“獲得したシステム状態種別(TRUE:CPUロック状態,FALSE:非CPUロック状態)”が返されます。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_sub ( void )
{
BOOL ercd; /*変数の宣言*/
............
............
ercd = sns_loc ( ); /*CPUロック状態の参照*/
if ( ercd == TRUE ) {
............ /*CPUロック状態*/
............
} else if ( ercd == FALSE ) {
............ /*非CPUロック状態*/
............
}
............
............
}
|
ディスパッチ禁止状態の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
sns_dsp
本サービス・コールを発行した際のシステム状態種別(ディスパッチ禁止状態,ディスパッチ許可状態)を獲得します。
なお,本サービス・コールが正常終了した際には,戻り値として“獲得したシステム状態種別(TRUE:ディスパッチ禁止状態,FALSE:ディスパッチ許可状態)”が返されます。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_sub ( void )
{
BOOL ercd; /*変数の宣言*/
............
............
ercd = sns_dsp ( ); /*ディスパッチ禁止状態の参照*/
if ( ercd == TRUE ) {
............ /*ディスパッチ禁止状態*/
............
} else if ( ercd == FALSE ) {
............ /*ディスパッチ許可状態*/
............
}
............
............
}
|
ディスパッチ保留状態の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
sns_dpn
本サービス・コールを発行した際のシステム状態種別(ディスパッチ保留状態であるか否か)を獲得します。
なお,本サービス・コールが正常終了した際には,戻り値として“獲得したシステム状態種別(TRUE:ディスパッチ保留状態,FALSE:非ディスパッチ保留状態)”が返されます。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_sub ( void )
{
BOOL ercd; /*変数の宣言*/
............
............
ercd = sns_dpn ( ); /*ディスパッチ保留状態の参照*/
if ( ercd == TRUE ) {
............ /*ディスパッチ保留状態*/
............
} else if ( ercd == FALSE ) {
............ /*非ディスパッチ保留状態*/
............
}
............
............
}
|
備考 ディスパッチ保留状態とは,
dis_dsp,
loc_cpu,
iloc_cpuといったサービス・コールを発行して明示的にディスパッチ処理(タスクのスケジューリング処理)の実行が禁止された状態,および,非タスクが処理を実行中の状態を指します。