00001 /* 00002 * TOPPERS/ASP Kernel 00003 * Toyohashi Open Platform for Embedded Real-Time Systems/ 00004 * Advanced Standard Profile Kernel 00005 * 00006 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory 00007 * Toyohashi Univ. of Technology, JAPAN 00008 * Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory 00009 * Graduate School of Information Science, Nagoya Univ., JAPAN 00010 * 00011 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ 00012 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 00013 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. 00014 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 00015 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー 00016 * スコード中に含まれていること. 00017 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 00018 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 00019 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 00020 * の無保証規定を掲載すること. 00021 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 00022 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ 00023 * と. 00024 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 00025 * 作権表示,この利用条件および下記の無保証規定を掲載すること. 00026 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに 00027 * 報告すること. 00028 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 00029 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. 00030 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 00031 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを 00032 * 免責すること. 00033 * 00034 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お 00035 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 00036 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ 00037 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ 00038 * の責任を負わない. 00039 * 00040 * @(#) $Id: task.h 748 2008-03-07 17:18:06Z hiro $ 00041 */ 00042 00043 /* 00044 * タスク管理モジュール 00045 */ 00046 00047 #ifndef TOPPERS_TASK_H 00048 #define TOPPERS_TASK_H 00049 00050 #include <queue.h> 00051 #include "time_event.h" 00052 00053 /* 00054 * トレースログマクロのデフォルト定義 00055 */ 00056 #ifndef LOG_TSKSTAT 00057 #define LOG_TSKSTAT(p_tcb) 00058 #endif /* LOG_TSKSTAT */ 00059 00060 /* 00061 * タスク優先度の内部表現・外部表現変換マクロ 00062 */ 00063 #define INT_PRIORITY(x) ((uint_t)((x) - TMIN_TPRI)) 00064 #define EXT_TSKPRI(x) ((PRI)(x) + TMIN_TPRI) 00065 00066 /* 00067 * タスク状態の内部表現 00068 * 00069 * TCB中のタスク状態では,実行状態(RUNNING)と実行可能状態(READY) 00070 * は区別しない.両状態を総称して,実行できる状態(RUNNABLE)と呼ぶ. 00071 * 二重待ち状態は,(TS_WAITING | TS_SUSPENDED)で表す.TS_WAIT_???は待 00072 * ち要因を表し,待ち状態(二重待ち状態を含む)の場合にのみ設定する. 00073 */ 00074 #define TS_DORMANT 0x00U /* 休止状態 */ 00075 #define TS_RUNNABLE 0x01U /* 実行できる状態 */ 00076 #define TS_WAITING 0x02U /* 待ち状態 */ 00077 #define TS_SUSPENDED 0x04U /* 強制待ち状態 */ 00078 00079 #define TS_WAIT_DLY (0x00U << 3) /* 時間経過待ち */ 00080 #define TS_WAIT_SLP (0x01U << 3) /* 起床待ち */ 00081 #define TS_WAIT_RDTQ (0x02U << 3) /* データキューからの受信待ち */ 00082 #define TS_WAIT_RPDQ (0x03U << 3) /* 優先度データキューからの受信待ち */ 00083 #define TS_WAIT_SEM (0x04U << 3) /* セマフォ資源の獲得待ち */ 00084 #define TS_WAIT_FLG (0x05U << 3) /* イベントフラグ待ち */ 00085 #define TS_WAIT_SDTQ (0x06U << 3) /* データキューへの送信待ち */ 00086 #define TS_WAIT_SPDQ (0x07U << 3) /* 優先度データキューへの送信待ち */ 00087 #define TS_WAIT_MBX (0x08U << 3) /* メールボックスからの受信待ち */ 00088 #define TS_WAIT_MPF (0x09U << 3) /* 固定長メモリブロックの獲得待ち */ 00089 00090 /* 00091 * タスク状態判別マクロ 00092 * 00093 * TSTAT_DORMANTはタスクが休止状態であるかどうかを,TSTAT_RUNNABLEは 00094 * タスクが実行できる状態であるかどうかを判別する.TSTAT_WAITINGは待 00095 * ち状態と二重待ち状態のいずれかであるかどうかを,TSTAT_SUSPENDEDは 00096 * 強制待ち状態と二重待ち状態のいずれかであるかどうかを判別する. 00097 */ 00098 #define TSTAT_DORMANT(tstat) ((tstat) == TS_DORMANT) 00099 #define TSTAT_RUNNABLE(tstat) (((tstat) & TS_RUNNABLE) != 0U) 00100 #define TSTAT_WAITING(tstat) (((tstat) & TS_WAITING) != 0U) 00101 #define TSTAT_SUSPENDED(tstat) (((tstat) & TS_SUSPENDED) != 0U) 00102 00103 /* 00104 * タスク待ち要因判別マクロ 00105 * 00106 * TSTAT_WAIT_SLPはタスクが起床待ちであるかどうかを,TSTAT_WAIT_WOBJ 00107 * はタスクが同期・通信オブジェクトに対する待ちであるか(言い換えると, 00108 * 同期通信オブジェクトの待ちキューにつながれているか)どうかを判別す 00109 * る.また,TSTAT_WAIT_WOBJCBはタスクが同期・通信オブジェクトの管理 00110 * ブロックの共通部分(WOBJCB)の待ちキューにつながれているかどうかを 00111 * 判別する. 00112 * 00113 * TSTAT_WAIT_SLPは,任意のタスク状態の中から,タスクが起床待ちである 00114 * ことを判別できる.すなわち,TSTAT_WAITINGにより待ち状態であることを 00115 * 判別せずに,TSTAT_SLPだけを用いて起床待ち状態であることを判別できる. 00116 * これを効率的に実現するために,TS_WAIT_SLPの値を,(0x00U << 3)ではな 00117 * く(0x01U << 3)としている.そのため,タスクが時間経過待ち状態である 00118 * ことを判別するためのTSTAT_WAIT_DLYを,TSTAT_WAIT_SLPと同様の方法で 00119 * 実現することはできない. 00120 */ 00121 #define TS_WAIT_MASK (0x0fU << 3) /* 待ち要因の取出しマスク */ 00122 00123 #define TSTAT_WAIT_SLP(tstat) (((tstat) & TS_WAIT_MASK) == TS_WAIT_SLP) 00124 #define TSTAT_WAIT_WOBJ(tstat) (((tstat) & TS_WAIT_MASK) >= TS_WAIT_RDTQ) 00125 #define TSTAT_WAIT_WOBJCB(tstat) (((tstat) & TS_WAIT_MASK) >= TS_WAIT_SEM) 00126 00127 /* 00128 * 待ち情報ブロック(WINFO)の定義 00129 * 00130 * タスクが待ち状態の間は,TCBおよびそのp_winfoで指されるWINFOを次の 00131 * ように設定しなければならない. 00132 * 00133 * (a) TCBのタスク状態を待ち状態(TS_WAITING)にする.その際に,待ち 00134 * 要因(TS_WAIT_???)も設定する. 00135 * 00136 * (b) タイムアウトを監視するために,タイムイベントブロックを登録する. 00137 * 登録するタイムイベントブロックは,待ちに入るサービスコール処理関数 00138 * のローカル変数として確保し,それへのポインタをWINFOのp_tmevtbに記 00139 * 憶する.タイムアウトの監視が必要ない場合(永久待ちの場合)には, 00140 * p_tmevtbをNULLにする. 00141 * 00142 * 同期・通信オブジェクトに対する待ち状態の場合には,標準のWINFOに 00143 * p_wobjcbフィールドを追加した構造体(WINFO_WOBJ,wait.hで定義)を使 00144 * う.また,以下の(c)〜(e)の設定を行う必要がある.同期・通信オブジェ 00145 * クトに関係しない待ち(起床待ち,時間経過待ち)の場合には,(c)〜(e) 00146 * は必要ない. 00147 * 00148 * (c) TCBを待ち対象の同期・通信オブジェクトの待ちキューにつなぐ.待 00149 * ちキューにつなぐために,task_queueを使う. 00150 * 00151 * (d) 待ち対象の同期・通信オブジェクトの管理ブロックへのポインタを, 00152 * WINFO_WOBJのp_wobjcbに記憶する. 00153 * 00154 * (e) 待ち対象の同期・通信オブジェクトに依存して記憶することが必要な 00155 * 情報がある場合には,WINFO_WOBJに必要な情報のためのフィールドを追加 00156 * した構造体を定義し,WINFO_WOBJの代わりに用いる. 00157 * 00158 * 待ち状態を解除する際には,待ち解除したタスクに対する返値をWINFOの 00159 * wercdに設定する.wercdが必要なのは待ち解除以降であるのに対して, 00160 * p_tmevtbは待ち解除後は必要ないため,メモリ節約のために共用体を使っ 00161 * ている.そのため,wercdへエラーコードを設定するのは,タイムイベント 00162 * ブロックを登録解除した後にしなければならない. 00163 */ 00164 typedef union waiting_information { 00165 ER wercd; /* 待ち解除時のエラーコード */ 00166 TMEVTB *p_tmevtb; /* 待ち状態用のタイムイベントブロック */ 00167 } WINFO; 00168 00169 /* 00170 * タスク初期化ブロック 00171 * 00172 * タスクに関する情報を,値が変わらないためにROMに置ける部分(タスク 00173 * 初期化ブロック)と,値が変化するためにRAMに置かなければならない部 00174 * 分(タスク管理ブロック,TCB)に分離し,TCB内に対応するタスク初期化 00175 * ブロックを指すポインタを入れる.タスク初期化ブロック内に対応する 00176 * TCBを指すポインタを入れる方法の方が,RAMの節約の観点からは望ましい 00177 * が,実行効率が悪くなるために採用していない.他のオブジェクトについ 00178 * ても同様に扱う. 00179 * 00180 * タスク初期化ブロックには,DEF_TEXで定義されるタスク例外処理ルーチ 00181 * ンに関する情報も含む. 00182 */ 00183 typedef struct task_initialization_block { 00184 ATR tskatr; /* タスク属性 */ 00185 intptr_t exinf; /* タスクの拡張情報 */ 00186 TASK task; /* タスクの起動番地 */ 00187 uint_t ipriority; /* タスクの起動時優先度(内部表現) */ 00188 SIZE stksz; /* スタック領域のサイズ(丸めた値) */ 00189 void *stk; /* スタック領域の先頭番地 */ 00190 00191 ATR texatr; /* タスク例外処理ルーチン属性 */ 00192 TEXRTN texrtn; /* タスク例外処理ルーチンの起動番地 */ 00193 } TINIB; 00194 00195 /* 00196 * TCB中のフィールドのビット幅の定義 00197 * 00198 * プロセッサによっては,TCB中のフィールドのビット幅でメモリ使用量と 00199 * 性能がトレードオフになるため,ターゲット依存にフィールドのビット幅 00200 * を変更することを許している. 00201 */ 00202 #ifndef TBIT_TCB_PRIORITY 00203 #define TBIT_TCB_PRIORITY 8 /* priorityフィールドのビット幅 */ 00204 #endif /* TBIT_TCB_PRIORITY */ 00205 00206 /* 00207 * タスク管理ブロック(TCB) 00208 * 00209 * ASPカーネルでは,タスクの起動要求キューイング数の最大値(TMAX_ACTCNT) 00210 * と起動要求キューイング数の最大値(TMAX_WUPCNT)は1に固定されている 00211 * ため,キューイングされているかどうかの真偽値で表現することができる. 00212 * また,強制待ち要求ネスト数の最大値(TMAX_SUSCNT)が1に固定されてい 00213 * るので,強制待ち要求ネスト数(suscnt)は必要ない. 00214 * 00215 * TCBのいくつかのフィールドは,特定のタスク状態でのみ有効な値を保持し, 00216 * それ以外の場合は値が保証されない(よって,参照してはならない).各 00217 * フィールドが有効な値を保持する条件は次の通り. 00218 * 00219 * ・初期化後は常に有効: 00220 * p_tinib,tstat,actque 00221 * ・休止状態以外で有効(休止状態では初期値になっている): 00222 * priority,wupque,enatex,texptn 00223 * ・待ち状態(二重待ち状態を含む)で有効: 00224 * p_winfo 00225 * ・実行できる状態と同期・通信オブジェクトに対する待ち状態で有効: 00226 * task_queue 00227 * ・実行可能状態,待ち状態,強制待ち状態,二重待ち状態で有効: 00228 * tskctxb 00229 */ 00230 typedef struct task_control_block { 00231 QUEUE task_queue; /* タスクキュー */ 00232 const TINIB *p_tinib; /* 初期化ブロックへのポインタ */ 00233 00234 #ifdef UINT8_MAX 00235 uint8_t tstat; /* タスク状態(内部表現)*/ 00236 #else /* UINT8_MAX */ 00237 BIT_FIELD_UINT tstat : 8; /* タスク状態(内部表現)*/ 00238 #endif /* UINT8_MAX */ 00239 BIT_FIELD_UINT priority : TBIT_TCB_PRIORITY; 00240 /* 現在の優先度(内部表現)*/ 00241 BIT_FIELD_BOOL actque : 1; /* 起動要求キューイング */ 00242 BIT_FIELD_BOOL wupque : 1; /* 起床要求キューイング */ 00243 BIT_FIELD_BOOL enatex : 1; /* タスク例外処理許可状態 */ 00244 00245 TEXPTN texptn; /* 保留例外要因 */ 00246 WINFO *p_winfo; /* 待ち情報ブロックへのポインタ */ 00247 CTXB tskctxb; /* タスクコンテキストブロック */ 00248 } TCB; 00249 00250 /* 00251 * 実行状態のタスク 00252 * 00253 * 実行状態のタスク(=プロセッサがコンテキストを持っているタスク)の 00254 * TCBを指すポインタ.実行状態のタスクがない場合はNULLにする. 00255 * 00256 * サービスコールの処理中で,自タスク(サービスコールを呼び出したタス 00257 * ク)に関する情報を参照する場合はp_runtskを使う.p_runtskを書き換え 00258 * るのは,ディスパッチャ(と初期化処理)のみである. 00259 */ 00260 extern TCB *p_runtsk; 00261 00262 /* 00263 * 最高優先順位のタスク 00264 * 00265 * 実行できるタスクの中で最高優先順位のタスクのTCBを指すポインタ.実 00266 * 行できるタスクがない場合はNULLにする. 00267 * 00268 * ディスパッチ禁止状態など,ディスパッチが保留されている間はp_runtsk 00269 * と一致しているとは限らない. 00270 */ 00271 extern TCB *p_schedtsk; 00272 00273 /* 00274 * ディスパッチ/タスク例外処理ルーチン起動要求フラグ 00275 * 00276 * 割込みハンドラ/CPU例外ハンドラの出口処理に,ディスパッチまたは 00277 * タスク例外処理ルーチンの起動を要求することを示すフラグ. 00278 */ 00279 extern bool_t reqflg; 00280 00281 /* 00282 * ディスパッチ禁止状態 00283 * 00284 * ディスパッチ禁止状態であることを示すフラグ. 00285 */ 00286 extern bool_t disdsp; 00287 00288 /* 00289 * タスクディスパッチ可能状態 00290 * 00291 * ディスパッチ禁止状態でなく,割込み優先度マスク(IPM)がTIPM_ENAALL 00292 * であることを示すフラグ. 00293 */ 00294 extern bool_t dspflg; 00295 00296 /* 00297 * レディキュー 00298 * 00299 * レディキューは,実行できる状態のタスクを管理するためのキューである. 00300 * 実行状態のタスクも管理しているため,レディ(実行可能)キューという 00301 * 名称は正確ではないが,レディキューという名称が定着しているため,こ 00302 * の名称で呼ぶことにする. 00303 * 00304 * レディキューは,優先度ごとのタスクキューで構成されている.タスクの 00305 * TCBは,該当する優先度のキューに登録される. 00306 */ 00307 extern QUEUE ready_queue[TNUM_TPRI]; 00308 00309 /* 00310 * レディキューサーチのためのビットマップ 00311 * 00312 * レディキューのサーチを効率よく行うために,優先度ごとのタスクキュー 00313 * にタスクが入っているかどうかを示すビットマップを用意している.ビッ 00314 * トマップを使うことで,メモリアクセスの回数を減らすことができるが, 00315 * ビット操作命令が充実していないプロセッサで,優先度の段階数が少ない 00316 * 場合には,ビットマップ操作のオーバーヘッドのために,逆に効率が落ち 00317 * る可能性もある. 00318 */ 00319 extern uint16_t ready_primap; 00320 00321 /* 00322 * タスクIDの最大値(kernel_cfg.c) 00323 */ 00324 extern const ID tmax_tskid; 00325 00326 /* 00327 * タスク初期化ブロックのエリア(kernel_cfg.c) 00328 */ 00329 extern const TINIB tinib_table[]; 00330 00331 /* 00332 * タスク生成順序テーブル(kernel_cfg.c) 00333 */ 00334 extern const ID torder_table[]; 00335 00336 /* 00337 * TCBのエリア(kernel_cfg.c) 00338 */ 00339 extern TCB tcb_table[]; 00340 00341 /* 00342 * タスクの数 00343 */ 00344 #define tnum_tsk ((uint_t)(tmax_tskid - TMIN_TSKID + 1)) 00345 00346 /* 00347 * タスクIDからTCBを取り出すためのマクロ 00348 */ 00349 #define INDEX_TSK(tskid) ((uint_t)((tskid) - TMIN_TSKID)) 00350 #define get_tcb(tskid) (&(tcb_table[INDEX_TSK(tskid)])) 00351 #define get_tcb_self(tskid) ((tskid) == TSK_SELF ? p_runtsk : get_tcb(tskid)) 00352 00353 /* 00354 * TCBからタスクIDを取り出すためのマクロ 00355 */ 00356 #define TSKID(p_tcb) ((ID)(((p_tcb) - tcb_table) + TMIN_TSKID)) 00357 00358 /* 00359 * タスク管理モジュールの初期化 00360 */ 00361 extern void initialize_task(void); 00362 00363 /* 00364 * 最高優先順位タスクのサーチ 00365 * 00366 * レディキュー中の最高優先順位のタスクをサーチし,そのTCBへのポインタ 00367 * を返す.レディキューが空の場合には,この関数を呼び出してはならない. 00368 */ 00369 extern TCB *search_schedtsk(void); 00370 00371 /* 00372 * 実行できる状態への移行 00373 * 00374 * p_tcbで指定されるタスクの状態を実行できる状態とし,レディキューに 00375 * 挿入する.実行できる状態になったタスクの優先度が,最高優先順位のタ 00376 * スクの優先度よりも高い場合は,最高優先順位のタスクを更新し,ディス 00377 * パッチ許可状態であればtrueを返す.そうでない場合はfalseを返す. 00378 */ 00379 extern bool_t make_runnable(TCB *p_tcb); 00380 00381 /* 00382 * 実行できる状態から他の状態への移行 00383 * 00384 * p_tcbで指定されるタスクをレディキューから削除する.p_tcbで指定した 00385 * タスクが最高優先順位のタスクであった場合には,最高優先順位のタスク 00386 * を設定しなおし,ディスパッチ許可状態であればtrueを返す.そうでない 00387 * 場合はfalseを返す.タスクの状態は更新しない. 00388 */ 00389 extern bool_t make_non_runnable(TCB *p_tcb); 00390 00391 /* 00392 * 休止状態への移行 00393 * 00394 * p_tcbで指定されるタスクの状態を休止状態とする.また,タスクの起動 00395 * 時に初期化すべき変数の初期化と,タスク起動のためのコンテキストを設 00396 * 定する. 00397 */ 00398 extern void make_dormant(TCB *p_tcb); 00399 00400 /* 00401 * 休止状態から実行できる状態への移行 00402 * 00403 * p_tcbで指定されるタスクの状態を休止状態から実行できる状態とする. 00404 * 実行できる状態に移行したタスクへのディスパッチが必要な場合はtrue, 00405 * そうでない場合はfalseを返す. 00406 */ 00407 extern bool_t make_active(TCB *p_tcb); 00408 00409 /* 00410 * タスクの優先度の変更 00411 * 00412 * p_tcbで指定されるタスクの優先度をnewpri(内部表現)に変更する.また, 00413 * 必要な場合には最高優先順位のタスクを更新し,ディスパッチ許可状態で 00414 * あればtrueを返す.そうでない場合はfalseを返す. 00415 */ 00416 extern bool_t change_priority(TCB *p_tcb, uint_t newpri); 00417 00418 /* 00419 * レディキューの回転 00420 * 00421 * レディキュー中の,priで指定される優先度のタスクキューを回転させる. 00422 * また,必要な場合には最高優先順位のタスクを変更し,ディスパッチが保 00423 * 留されていなければtrueを返す.そうでない場合はfalseを返す. 00424 */ 00425 extern bool_t rotate_ready_queue(uint_t pri); 00426 00427 /* 00428 * タスク例外処理ルーチンの呼出し 00429 * 00430 * タスク例外処理ルーチンを呼び出す.呼び出す前に,実行状態のタスクの 00431 * 保留例外要因をクリアし,タスク例外処理禁止状態にし,CPUロックを解 00432 * 除する. 00433 * 00434 * タスク例外処理ルーチンから戻ると,まずCPUロック状態に戻し,その間 00435 * に保留例外要因が0でなくなっていれば,再びタスク例外処理ルーチンを 00436 * 呼び出す.保留例外要因が0の場合には,例外処理許可状態にして関数か 00437 * らリターンする. 00438 * 00439 * この関数は,実行状態のタスクが,タスク例外処理許可状態(enatexが 00440 * true)で,保留例外要因が0でない(texptnが0でない)場合に呼び出すこ 00441 * とを想定している.この関数は,CPUロック状態で呼び出さなければなら 00442 * ない. 00443 * 00444 * 実行効率を上げるために,この関数をターゲット依存部で記述してもよい. 00445 * その場合には,OMIT_CALL_TEXRTNをマクロ定義する. 00446 */ 00447 extern void call_texrtn(void); 00448 00449 /* 00450 * タスク例外処理ルーチンの起動 00451 * 00452 * 実行状態のタスクがタスク例外処理ルーチンの起動条件を満たしていれば, 00453 * タスク例外処理ルーチンを呼び出す.CPU例外処理ルーチンを呼び出す時 00454 * は,一時的にCPUロックを解除する. 00455 * 00456 * この関数は,ディスパッチャや割込みハンドラ/CPU例外ハンドラの出口 00457 * 処理から呼び出されることを想定している.この関数は,CPUロック状態 00458 * で呼び出さなければならない. 00459 * 00460 * 実行効率を上げるために,この関数をターゲット依存部で記述してもよい. 00461 * その場合には,OMIT_CALLTEXをマクロ定義する. 00462 */ 00463 extern void calltex(void); 00464 00465 #endif /* TOPPERS_TASK_H */
Copyright © 2008 by Kijineko Inc.