3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
11 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
12 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
14 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
21 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
24 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
26 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
28 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
31 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
34 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
35 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
36 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
37 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
40 * $Id: task.h 2018 2010-12-31 13:43:05Z ertl-hiro $
47 #ifndef TOPPERS_TASK_H
48 #define TOPPERS_TASK_H
51 #include "time_event.h"
57 #define LOG_TSKSTAT(p_tcb)
58 #endif /* LOG_TSKSTAT */
61 * タスク優先度の内部表現・外部表現変換マクロ
63 #define INT_PRIORITY(x) ((uint_t)((x) - TMIN_TPRI))
64 #define EXT_TSKPRI(x) ((PRI)(x) + TMIN_TPRI)
69 * TCB中のタスク状態では,実行状態(RUNNING)と実行可能状態(READY)
70 * は区別しない.両状態を総称して,実行できる状態(RUNNABLE)と呼ぶ.
71 * 二重待ち状態は,(TS_WAITING | TS_SUSPENDED)で表す.TS_WAIT_???は待
72 * ち要因を表し,待ち状態(二重待ち状態を含む)の場合にのみ設定する.
74 #define TS_DORMANT 0x00U /* 休止状態 */
75 #define TS_RUNNABLE 0x01U /* 実行できる状態 */
76 #define TS_WAITING 0x02U /* 待ち状態 */
77 #define TS_SUSPENDED 0x04U /* 強制待ち状態 */
79 #define TS_WAIT_DLY (0x00U << 3) /* 時間経過待ち */
80 #define TS_WAIT_SLP (0x01U << 3) /* 起床待ち */
81 #define TS_WAIT_RDTQ (0x02U << 3) /* データキューからの受信待ち */
82 #define TS_WAIT_RPDQ (0x03U << 3) /* 優先度データキューからの受信待ち */
83 #define TS_WAIT_SEM (0x04U << 3) /* セマフォ資源の獲得待ち */
84 #define TS_WAIT_FLG (0x05U << 3) /* イベントフラグ待ち */
85 #define TS_WAIT_SDTQ (0x06U << 3) /* データキューへの送信待ち */
86 #define TS_WAIT_SPDQ (0x07U << 3) /* 優先度データキューへの送信待ち */
87 #define TS_WAIT_MBX (0x08U << 3) /* メールボックスからの受信待ち */
88 #define TS_WAIT_MPF (0x09U << 3) /* 固定長メモリブロックの獲得待ち */
93 * TSTAT_DORMANTはタスクが休止状態であるかどうかを,TSTAT_RUNNABLEは
94 * タスクが実行できる状態であるかどうかを判別する.TSTAT_WAITINGは待
95 * ち状態と二重待ち状態のいずれかであるかどうかを,TSTAT_SUSPENDEDは
96 * 強制待ち状態と二重待ち状態のいずれかであるかどうかを判別する.
98 #define TSTAT_DORMANT(tstat) ((tstat) == TS_DORMANT)
99 #define TSTAT_RUNNABLE(tstat) (((tstat) & TS_RUNNABLE) != 0U)
100 #define TSTAT_WAITING(tstat) (((tstat) & TS_WAITING) != 0U)
101 #define TSTAT_SUSPENDED(tstat) (((tstat) & TS_SUSPENDED) != 0U)
106 * TSTAT_WAIT_SLPはタスクが起床待ちであるかどうかを,TSTAT_WAIT_WOBJ
107 * はタスクが同期・通信オブジェクトに対する待ちであるか(言い換えると,
108 * 同期通信オブジェクトの待ちキューにつながれているか)どうかを判別す
109 * る.また,TSTAT_WAIT_WOBJCBはタスクが同期・通信オブジェクトの管理
110 * ブロックの共通部分(WOBJCB)の待ちキューにつながれているかどうかを
113 * TSTAT_WAIT_SLPは,任意のタスク状態の中から,タスクが起床待ちである
114 * ことを判別できる.すなわち,TSTAT_WAITINGにより待ち状態であることを
115 * 判別せずに,TSTAT_SLPだけを用いて起床待ち状態であることを判別できる.
116 * これを効率的に実現するために,TS_WAIT_SLPの値を,(0x00U << 3)ではな
117 * く(0x01U << 3)としている.そのため,タスクが時間経過待ち状態である
118 * ことを判別するためのTSTAT_WAIT_DLYを,TSTAT_WAIT_SLPと同様の方法で
121 #define TS_WAIT_MASK (0x0fU << 3) /* 待ち要因の取出しマスク */
123 #define TSTAT_WAIT_SLP(tstat) (((tstat) & TS_WAIT_MASK) == TS_WAIT_SLP)
124 #define TSTAT_WAIT_WOBJ(tstat) (((tstat) & TS_WAIT_MASK) >= TS_WAIT_RDTQ)
125 #define TSTAT_WAIT_WOBJCB(tstat) (((tstat) & TS_WAIT_MASK) >= TS_WAIT_SEM)
130 * タスクが待ち状態の間は,TCBおよびそのp_winfoで指されるWINFOを次の
133 * (a) TCBのタスク状態を待ち状態(TS_WAITING)にする.その際に,待ち
134 * 要因(TS_WAIT_???)も設定する.
136 * (b) タイムアウトを監視するために,タイムイベントブロックを登録する.
137 * 登録するタイムイベントブロックは,待ちに入るサービスコール処理関数
138 * のローカル変数として確保し,それへのポインタをWINFOのp_tmevtbに記
139 * 憶する.タイムアウトの監視が必要ない場合(永久待ちの場合)には,
142 * 同期・通信オブジェクトに対する待ち状態の場合には,標準のWINFOに
143 * p_wobjcbフィールドを追加した構造体(WINFO_WOBJ,wait.hで定義)を使
144 * う.また,以下の(c)〜(e)の設定を行う必要がある.同期・通信オブジェ
145 * クトに関係しない待ち(起床待ち,時間経過待ち)の場合には,(c)〜(e)
148 * (c) TCBを待ち対象の同期・通信オブジェクトの待ちキューにつなぐ.待
149 * ちキューにつなぐために,task_queueを使う.
151 * (d) 待ち対象の同期・通信オブジェクトの管理ブロックへのポインタを,
152 * WINFO_WOBJのp_wobjcbに記憶する.
154 * (e) 待ち対象の同期・通信オブジェクトに依存して記憶することが必要な
155 * 情報がある場合には,WINFO_WOBJに必要な情報のためのフィールドを追加
156 * した構造体を定義し,WINFO_WOBJの代わりに用いる.
158 * 待ち状態を解除する際には,待ち解除したタスクに対する返値をWINFOの
159 * wercdに設定する.wercdが必要なのは待ち解除以降であるのに対して,
160 * p_tmevtbは待ち解除後は必要ないため,メモリ節約のために共用体を使っ
161 * ている.そのため,wercdへエラーコードを設定するのは,タイムイベント
162 * ブロックを登録解除した後にしなければならない.
164 typedef union waiting_information {
165 ER wercd; /* 待ち解除時のエラーコード */
166 TMEVTB *p_tmevtb; /* 待ち状態用のタイムイベントブロック */
172 * タスクに関する情報を,値が変わらないためにROMに置ける部分(タスク
173 * 初期化ブロック)と,値が変化するためにRAMに置かなければならない部
174 * 分(タスク管理ブロック,TCB)に分離し,TCB内に対応するタスク初期化
175 * ブロックを指すポインタを入れる.タスク初期化ブロック内に対応する
176 * TCBを指すポインタを入れる方法の方が,RAMの節約の観点からは望ましい
177 * が,実行効率が悪くなるために採用していない.他のオブジェクトについ
180 * タスク初期化ブロックには,DEF_TEXで定義されるタスク例外処理ルーチ
183 typedef struct task_initialization_block {
184 ATR tskatr; /* タスク属性 */
185 intptr_t exinf; /* タスクの拡張情報 */
186 TASK task; /* タスクの起動番地 */
187 uint_t ipriority; /* タスクの起動時優先度(内部表現) */
189 #ifdef USE_TSKINICTXB
190 TSKINICTXB tskinictxb; /* タスク初期化コンテキストブロック */
191 #else /* USE_TSKINICTXB */
192 SIZE stksz; /* スタック領域のサイズ(丸めた値) */
193 void *stk; /* スタック領域の先頭番地 */
194 #endif /* USE_TSKINICTXB */
196 ATR texatr; /* タスク例外処理ルーチン属性 */
197 TEXRTN texrtn; /* タスク例外処理ルーチンの起動番地 */
203 * プロセッサによっては,TCB中のフィールドのビット幅でメモリ使用量と
204 * 性能がトレードオフになるため,ターゲット依存にフィールドのビット幅
207 #ifndef TBIT_TCB_PRIORITY
208 #define TBIT_TCB_PRIORITY 8 /* priorityフィールドのビット幅 */
209 #endif /* TBIT_TCB_PRIORITY */
214 * ASPカーネルでは,タスクの起動要求キューイング数の最大値(TMAX_ACTCNT)
215 * と起床要求キューイング数の最大値(TMAX_WUPCNT)は1に固定されている
216 * ため,キューイングされているかどうかの真偽値で表現することができる.
217 * また,強制待ち要求ネスト数の最大値(TMAX_SUSCNT)が1に固定されてい
218 * るので,強制待ち要求ネスト数(suscnt)は必要ない.
220 * TCBのいくつかのフィールドは,特定のタスク状態でのみ有効な値を保持し,
221 * それ以外の場合は値が保証されない(よって,参照してはならない).各
222 * フィールドが有効な値を保持する条件は次の通り.
225 * p_tinib,tstat,actque
226 * ・休止状態以外で有効(休止状態では初期値になっている):
227 * priority,wupque,enatex,texptn
228 * ・待ち状態(二重待ち状態を含む)で有効:
230 * ・実行できる状態と同期・通信オブジェクトに対する待ち状態で有効:
232 * ・実行可能状態,待ち状態,強制待ち状態,二重待ち状態で有効:
235 typedef struct task_control_block {
236 QUEUE task_queue; /* タスクキュー */
237 const TINIB *p_tinib; /* 初期化ブロックへのポインタ */
240 uint8_t tstat; /* タスク状態(内部表現)*/
241 #else /* UINT8_MAX */
242 BIT_FIELD_UINT tstat : 8; /* タスク状態(内部表現)*/
243 #endif /* UINT8_MAX */
244 #if defined(UINT8_MAX) && (TBIT_TCB_PRIORITY == 8)
245 uint8_t priority; /* 現在の優先度(内部表現)*/
246 #else /* defined(UINT8_MAX) && (TBIT_TCB_PRIORITY == 8) */
247 BIT_FIELD_UINT priority : TBIT_TCB_PRIORITY;
249 #endif /* defined(UINT8_MAX) && (TBIT_TCB_PRIORITY == 8) */
250 BIT_FIELD_BOOL actque : 1; /* 起動要求キューイング */
251 BIT_FIELD_BOOL wupque : 1; /* 起床要求キューイング */
252 BIT_FIELD_BOOL enatex : 1; /* タスク例外処理許可状態 */
254 TEXPTN texptn; /* 保留例外要因 */
255 WINFO *p_winfo; /* 待ち情報ブロックへのポインタ */
256 TSKCTXB tskctxb; /* タスクコンテキストブロック */
262 * 実行状態のタスク(=プロセッサがコンテキストを持っているタスク)の
263 * TCBを指すポインタ.実行状態のタスクがない場合はNULLにする.
265 * サービスコールの処理中で,自タスク(サービスコールを呼び出したタス
266 * ク)に関する情報を参照する場合はp_runtskを使う.p_runtskを書き換え
267 * るのは,ディスパッチャ(と初期化処理)のみである.
269 extern TCB *p_runtsk;
274 * 実行できるタスクの中で最高優先順位のタスクのTCBを指すポインタ.実
275 * 行できるタスクがない場合はNULLにする.
277 * ディスパッチ禁止状態など,ディスパッチが保留されている間はp_runtsk
280 extern TCB *p_schedtsk;
283 * ディスパッチ/タスク例外処理ルーチン起動要求フラグ
285 * 割込みハンドラ/CPU例外ハンドラの出口処理に,ディスパッチまたは
286 * タスク例外処理ルーチンの起動を要求することを示すフラグ.
288 extern bool_t reqflg;
293 * 割込み優先度マスク全解除状態であることを示すフラグ.
295 extern bool_t ipmflg;
300 * ディスパッチ禁止状態であることを示すフラグ.
302 extern bool_t disdsp;
307 * 割込み優先度マスク全解除状態であり,ディスパッチ許可状態である(ディ
308 * スパッチ禁止状態でない)ことを示すフラグ.
310 extern bool_t dspflg;
315 * レディキューは,実行できる状態のタスクを管理するためのキューである.
316 * 実行状態のタスクも管理しているため,レディ(実行可能)キューという
317 * 名称は正確ではないが,レディキューという名称が定着しているため,こ
320 * レディキューは,優先度ごとのタスクキューで構成されている.タスクの
321 * TCBは,該当する優先度のキューに登録される.
323 extern QUEUE ready_queue[TNUM_TPRI];
326 * レディキューサーチのためのビットマップ
328 * レディキューのサーチを効率よく行うために,優先度ごとのタスクキュー
329 * にタスクが入っているかどうかを示すビットマップを用意している.ビッ
330 * トマップを使うことで,メモリアクセスの回数を減らすことができるが,
331 * ビット操作命令が充実していないプロセッサで,優先度の段階数が少ない
332 * 場合には,ビットマップ操作のオーバーヘッドのために,逆に効率が落ち
335 * 優先度が16段階であることを仮定しているため,uint16_t型としている.
337 extern uint16_t ready_primap;
340 * タスクIDの最大値(kernel_cfg.c)
342 extern const ID tmax_tskid;
345 * タスク初期化ブロックのエリア(kernel_cfg.c)
347 extern const TINIB tinib_table[];
350 * タスク生成順序テーブル(kernel_cfg.c)
352 extern const ID torder_table[];
355 * TCBのエリア(kernel_cfg.c)
357 extern TCB tcb_table[];
362 #define tnum_tsk ((uint_t)(tmax_tskid - TMIN_TSKID + 1))
365 * タスクIDからTCBを取り出すためのマクロ
367 #define INDEX_TSK(tskid) ((uint_t)((tskid) - TMIN_TSKID))
368 #define get_tcb(tskid) (&(tcb_table[INDEX_TSK(tskid)]))
369 #define get_tcb_self(tskid) ((tskid) == TSK_SELF ? p_runtsk : get_tcb(tskid))
372 * TCBからタスクIDを取り出すためのマクロ
374 #define TSKID(p_tcb) ((ID)(((p_tcb) - tcb_table) + TMIN_TSKID))
379 extern void initialize_task(void);
384 * レディキュー中の最高優先順位のタスクをサーチし,そのTCBへのポインタ
385 * を返す.レディキューが空の場合には,この関数を呼び出してはならない.
387 extern TCB *search_schedtsk(void);
392 * p_tcbで指定されるタスクをレディキューに挿入する.レディキューに挿入
393 * したタスクの優先度が,最高優先順位のタスクの優先度よりも高い場合は,
394 * 最高優先順位のタスクを更新し,ディスパッチ許可状態であればtrueを返
395 * す.そうでない場合はfalseを返す.
397 extern bool_t make_runnable(TCB *p_tcb);
402 * p_tcbで指定されるタスクをレディキューから削除する.p_tcbで指定した
403 * タスクが最高優先順位のタスクであった場合には,最高優先順位のタスク
404 * を設定しなおし,ディスパッチ許可状態であればtrueを返す.そうでない
405 * 場合はfalseを返す.タスクの状態は更新しない.
407 extern bool_t make_non_runnable(TCB *p_tcb);
412 * p_tcbで指定されるタスクの状態を休止状態とする.また,タスクの起動
413 * 時に初期化すべき変数の初期化と,タスク起動のためのコンテキストを設
416 extern void make_dormant(TCB *p_tcb);
421 * p_tcbで指定されるタスクの状態を休止状態から実行できる状態とする.
422 * 実行できる状態に遷移したタスクへのディスパッチが必要な場合はtrue,
425 extern bool_t make_active(TCB *p_tcb);
430 * p_tcbで指定されるタスクの優先度をnewpri(内部表現)に変更する.また,
431 * 必要な場合には最高優先順位のタスクを更新し,ディスパッチ許可状態で
432 * あればtrueを返す.そうでない場合はfalseを返す.
434 extern bool_t change_priority(TCB *p_tcb, uint_t newpri);
439 * 自タスクの優先度をnewpri(内部表現)に変更する.また,必要な場合に
440 * は最高優先順位のタスクを更新し,ディスパッチ許可状態であればtrueを
441 * 返す.そうでない場合はfalseを返す.
443 extern bool_t raise_priority(uint_t newpri);
448 * レディキュー中の,p_queueで指定されるタスクキューを回転させる.また,
449 * 必要な場合には最高優先順位のタスクを変更し,ディスパッチが保留され
450 * ていなければtrueを返す.そうでない場合はfalseを返す.
452 extern bool_t rotate_ready_queue(QUEUE *p_queue);
457 * タスク例外処理ルーチンを呼び出す.呼び出す前に,実行状態のタスクの
458 * 保留例外要因をクリアし,タスク例外処理禁止状態にし,CPUロックを解
461 * タスク例外処理ルーチンから戻ると,まずCPUロック状態に戻し,その間
462 * に保留例外要因が0でなくなっていれば,再びタスク例外処理ルーチンを
463 * 呼び出す.保留例外要因が0の場合には,例外処理許可状態にして関数か
466 * この関数は,実行状態のタスクが,タスク例外処理許可状態(enatexが
467 * true)で,保留例外要因が0でない(texptnが0でない)場合に呼び出すこ
468 * とを想定している.この関数は,CPUロック状態で呼び出さなければなら
471 extern void call_texrtn(void);
476 * 実行状態のタスクがタスク例外処理ルーチンの起動条件を満たしていれば,
477 * タスク例外処理ルーチンを呼び出す.CPU例外処理ルーチンを呼び出す時
480 * この関数は,ディスパッチャや割込みハンドラ/CPU例外ハンドラの出口
481 * 処理から呼び出されることを想定している.この関数は,CPUロック状態
484 * 実行効率を上げるために,この関数をターゲット依存部で記述してもよい.
485 * その場合には,OMIT_CALLTEXをマクロ定義する.
487 extern void calltex(void);
489 #endif /* TOPPERS_TASK_H */