第11章 スケジューリング機能
本章では,RI78V4が提供しているスケジューリング機能について解説しています。
RI78V4におけるスケジューリング機能では,動的に変化していくタスクの遷移状態を観察することにより,タスクの実行順序を管理/決定し,最適なタスクにCPUの利用権を与える機能を提供しています。
RI78V4では,スケジューラの駆動方式として“何らかの事象(きっかけ)”が発生した際に起動する
事象駆動方式を採用しています。
RI78V4における事象駆動方式では,以下に示した事象が発生した場合に“スケジューラ”を起動し,ディスパッチ処理(タスクのスケジューリング処理)を実行します。
- タスクの状態遷移を引き起こす可能性があるサービス・コールの発行
- 非タスク(周期ハンドラ,割り込みハンドラなど)からの復帰命令の発行
-
時間管理機能を実現する際に利用しているクロック割り込みの発生
RI78V4では,タスクのスケジューリング方式として“各タスクに定義されている優先度”を利用した
優先度方式,および,RI78V4のスケジューリング対象となってからの経過時間を利用した
FCFS方式を採用しています。
RI78V4における優先度方式では,実行可能な状態(RUNNING状態,またはREADY状態)へと遷移している全タスクの中から“最も高い優先度を持つタスク”を選び出し,CPUの利用権を与えます。
備考 RI78V4における優先度は,その値が小さいほど,高い優先度であることを意味します。
RI78V4では,同一の優先度を“複数のタスク”に対して定義することが可能です。このため,
優先度方式におけるタスクを選び出す基準である“最も高い優先度を持つタスク”が複数存在する場合があります。
そこで,RI78V4では,このような場合には,FCFS方式(First Come First Service方式)によるディスパッチ処理(タスクのスケジューリング処理)を実行し,実行可能な状態(READY状態)へと遷移してから“最も時間が経過しているタスク”を選び出し,CPUの利用権を与えます。
RI78V4では,タスクのスケジューリング方式を実現する手段として“レディ・キュー”を利用しています。
なお,RI78V4におけるレディ・キューは,優先度をキーとしたハッシュ・テーブルであり,実行可能な状態(RUNNING状態,またはREADY状態)へと遷移したタスクがFIFO順でキューイングされます。このため,スケジューラは,起動された際にレディ・キューの優先度高位から“タスクの検出処理”を実行し,キューイングされているタスクを検出した際には,該当優先度の先頭タスクにCPUの利用権を与えることにより,タスクのスケジューリング方式(優先度方式,FCFS方式)を実現しています。
以下に,複数のタスクがレディ・キューにキューイングされている場合を示します。
図11−1 スケジューリング方式(優先度方式,FCFS方式)の実現
RI78V4では,レディ・キューの生成方法を“
カーネル初期化部において静的に生成する”に限定しています。
したがって,RI78V4では,レディ・キューを処理プログラムからサービス・コールを発行するなどして動的に生成することはできません。
- 静的な生成
レディ・キューの静的な生成は,システム・コンフィギュレーション・ファイルに
優先度情報を定義することにより実現されます。
RI78V4では,
カーネル初期化部において,情報ファイルに格納されているデータをもとにレディ・キューの生成処理を実行し,管理対象とします。
RI78V4では,
カーネル初期化部において静的に生成されたレディ・キューを処理プログラムからサービス・コールを発行するなどして動的に削除することはできません。
RI78V4では,処理プログラムからタスクのキューイング順序を変更し,“タスクの実行順序”を明示的に入れ替える機能を提供しています。
以下に,タスクのキューイング順序を変更した際の状態変化を示します。
なお,レディ・キューの回転は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
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 本サービス・コールを周期ハンドラなどから一定周期で発行することにより,ラウンドロビン・スケジューリングを実現することができます。
RI78V4では,処理プログラムからタスクの優先度を変更し,“タスクの実行順序”を明示的に入れ替える機能を提供しています。
以下に,タスクの優先度を変更した際の状態変化を示します。
なお,優先度の変更は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
chg_pri,
ichg_pri
パラメータ
tskidで指定されたタスクの優先度(現在優先度)をパラメータ
tskpriで指定された値に変更します。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
func_task ( VP_INT exinf )
{
ID tskid = ID_tskA; /*変数の宣言,初期化*/
PRI tskpri = 9; /*変数の宣言,初期化*/
............
............
chg_pri ( tskid, tskpri ); /*優先度の変更*/
............
............
}
|
備考 本サービス・コールを発行した際,対象タスクがRUNNING状態,またはREADY状態であった場合には,優先度の変更処理を実行したのち,パラメータ
tskpriで指定された優先度に対応したレディ・キューの最後尾にキューイングし直す処理もあわせて実行されます。
RI78V4では,処理プログラムからシステム状態を操作し,ディスパッチ処理(タスクのスケジューリング処理)を明示的に禁止することにより,スケジューラの起動を抑制する機能を提供しています。
以下に,スケジューリングの抑制機能を利用した際の処理の流れを示します。
ディスパッチ禁止状態への移行は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
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 ( ); /*ディスパッチ禁止状態の解除*/
............
............
}
|
備考 本サービス・コールでは,許可要求のキューイングが行われません。このため,システム状態種別がディスパッチ許可状態であった場合には,何も処理は行わず,エラーとしても扱いません。
RI78V4では,非タスク(周期ハンドラ,割り込みハンドラなど)内の処理を高速に終了させる目的から,非タスク内の処理が完了するまでの間に“ディスパッチ処理(タスクのスケジューリング処理)を伴うサービス・コール(
ichg_pri,
isig_semなど)”が発行された場合には,キュー操作,カウンタ操作などといった処理を行うだけであり,実際のディスパッチ処理は,非タスクからの復帰命令(return命令の発行など)が発行されるまで遅延され,一括して行うようにしています。
以下に,非タスク内でディスパッチ処理を伴うサービス・コールを発行した際の処理の流れを示します。
アイドル・ルーチンは,CPUが提供しているスタンバイ機能を有効活用(低消費電力システムの実現)するためにユーザ・オウン・コーディング部として切り出されたアイドル処理専用ルーチンであり,RI78V4のスケジューリング対象となるタスク(RUNNING状態,またはREADY状態のタスク)がシステム内に1つも存在しなくなった際にスケジューラから呼び出されます。
RI78V4では,アイドル・ルーチンの登録方法を“
カーネル初期化部において静的に登録する”に限定しています。
したがって,RI78V4では,アイドル・ルーチンを処理プログラムからサービス・コールを発行するなどして動的に登録することはできません。
- 静的な登録
アイドル・ルーチンの静的な登録は,規定された関数名idle_handlerでアイドル・ルーチンを記述することにより実現されます。
RI78V4では,
カーネル初期化部において,該当シンボル情報をもとにアイドル・ルーチンの登録処理を実行し,管理対象とします。
RI78V4では,
カーネル初期化部において静的に登録されたアイドル・ルーチンを処理プログラムからサービス・コールを発行するなどして動的に登録解除することはできません。
アイドル・ルーチンを記述する場合,引き数を持たないvoid型の関数(関数名:idle_handler)として記述します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/
#include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/
void
idle_handler ( void )
{
............ /*アイドル・ルーチンの本体処理*/
............
return; /*アイドル・ルーチンの終了*/
}
|
$INCLUDE (kernel.inc) ;標準ヘッダ・ファイルの定義
$INCLUDE (kernel_id.inc) ;システム情報ヘッダ・ファイルの定義
.PUBLIC _idle_handler
.SECTION .textf, TEXTF
_idle_handler:
............ ;アイドル・ルーチンの本体処理
............
RET ;アイドル・ルーチンの終了
|
RI78V4では,アイドル・ルーチンを“非タスク(タスクとは独立したもの)”として位置づけています。
また,RI78V4では,アイドル・ルーチンに制御を移す際に“独自の前処理”を,アイドル・ルーチンから制御を戻す際にも“独自の後処理”を実行しています。
このため,アイドル・ルーチンを記述する際には,以下に示す注意点があります。
- スタックの切り替え
RI78V4では,アイドル・ルーチンに制御を移す際に“システム・スタックへの切り替え処理”を,アイドル・ルーチンから制御を戻す際に“切り替え先の処理プログラム用スタック(システム・スタック,またはタスク・スタック)への切り替え処理”を実行しています。
したがって,ユーザは,アイドル・ルーチン内でスタックの切り替えに関する処理を記述する必要はありません。
- 割り込み状態
RI78V4では,アイドル・ルーチンに制御を移す際に“マスカブル割り込みの受け付けが許可された状態”としています。
したがって,ユーザは,アイドル・ルーチン内でマスカブル割り込みの受け付けに関する処理を記述する必要はありません。
- サービス・コールの発行
RI78V4では,アイドル・ルーチン内でサービス・コールを発行することを禁止しています。
以下に,アイドル・ルーチンとして実行すべき処理の一覧を示します。