OSDN Git Service

マルチプロジェクト型にレポジトリを変更するために移動した
[toppersasp4lpc/asp.git] / asp / extension / ovrhdr / kernel / task.h
1 /*
2  *  TOPPERS/ASP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Advanced Standard Profile Kernel
5  * 
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
10  * 
11  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
12  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
31  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32  *      免責すること.
33  * 
34  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
35  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
36  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
37  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38  *  の責任を負わない.
39  * 
40  *  @(#) $Id: task.h 1863 2010-07-25 12:23:05Z ertl-hiro $
41  */
42
43 /*
44  *              タスク管理モジュール
45  */
46
47 #ifndef TOPPERS_TASK_H
48 #define TOPPERS_TASK_H
49
50 #include <queue.h>
51 #include "time_event.h"
52
53 /*
54  *  トレースログマクロのデフォルト定義
55  */
56 #ifndef LOG_TSKSTAT
57 #define LOG_TSKSTAT(p_tcb)
58 #endif /* LOG_TSKSTAT */
59
60 /*
61  *  タスク優先度の内部表現・外部表現変換マクロ
62  */
63 #define INT_PRIORITY(x)         ((uint_t)((x) - TMIN_TPRI))
64 #define EXT_TSKPRI(x)           ((PRI)(x) + TMIN_TPRI)
65
66 /*
67  *  タスク状態の内部表現
68  *
69  *  TCB中のタスク状態では,実行状態(RUNNING)と実行可能状態(READY)
70  *  は区別しない.両状態を総称して,実行できる状態(RUNNABLE)と呼ぶ.
71  *  二重待ち状態は,(TS_WAITING | TS_SUSPENDED)で表す.TS_WAIT_???は待
72  *  ち要因を表し,待ち状態(二重待ち状態を含む)の場合にのみ設定する.
73  */
74 #define TS_DORMANT              0x00U                   /* 休止状態 */
75 #define TS_RUNNABLE             0x01U                   /* 実行できる状態 */
76 #define TS_WAITING              0x02U                   /* 待ち状態 */
77 #define TS_SUSPENDED    0x04U                   /* 強制待ち状態 */
78
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)    /* 固定長メモリブロックの獲得待ち */
89
90 /*
91  *  タスク状態判別マクロ
92  *
93  *  TSTAT_DORMANTはタスクが休止状態であるかどうかを,TSTAT_RUNNABLEは
94  *  タスクが実行できる状態であるかどうかを判別する.TSTAT_WAITINGは待
95  *  ち状態と二重待ち状態のいずれかであるかどうかを,TSTAT_SUSPENDEDは
96  *  強制待ち状態と二重待ち状態のいずれかであるかどうかを判別する.
97  */
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)
102
103 /*
104  *  タスク待ち要因判別マクロ
105  *
106  *  TSTAT_WAIT_SLPはタスクが起床待ちであるかどうかを,TSTAT_WAIT_WOBJ
107  *  はタスクが同期・通信オブジェクトに対する待ちであるか(言い換えると,
108  *  同期通信オブジェクトの待ちキューにつながれているか)どうかを判別す
109  *  る.また,TSTAT_WAIT_WOBJCBはタスクが同期・通信オブジェクトの管理
110  *  ブロックの共通部分(WOBJCB)の待ちキューにつながれているかどうかを
111  *  判別する.
112  *
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と同様の方法で
119  *  実現することはできない.
120  */
121 #define TS_WAIT_MASK    (0x0fU << 3)    /* 待ち要因の取出しマスク */
122
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)
126
127 /*
128  *  待ち情報ブロック(WINFO)の定義
129  *
130  *  タスクが待ち状態の間は,TCBおよびそのp_winfoで指されるWINFOを次の
131  *  ように設定しなければならない.
132  *
133  *  (a) TCBのタスク状態を待ち状態(TS_WAITING)にする.その際に,待ち
134  *  要因(TS_WAIT_???)も設定する.
135  *
136  *  (b) タイムアウトを監視するために,タイムイベントブロックを登録する.
137  *  登録するタイムイベントブロックは,待ちに入るサービスコール処理関数
138  *  のローカル変数として確保し,それへのポインタをWINFOのp_tmevtbに記
139  *  憶する.タイムアウトの監視が必要ない場合(永久待ちの場合)には,
140  *  p_tmevtbをNULLにする.
141  *
142  *  同期・通信オブジェクトに対する待ち状態の場合には,標準のWINFOに
143  *  p_wobjcbフィールドを追加した構造体(WINFO_WOBJ,wait.hで定義)を使
144  *  う.また,以下の(c)〜(e)の設定を行う必要がある.同期・通信オブジェ
145  *  クトに関係しない待ち(起床待ち,時間経過待ち)の場合には,(c)〜(e)
146  *  は必要ない.
147  *
148  *  (c) TCBを待ち対象の同期・通信オブジェクトの待ちキューにつなぐ.待
149  *  ちキューにつなぐために,task_queueを使う.
150  *
151  *  (d) 待ち対象の同期・通信オブジェクトの管理ブロックへのポインタを,
152  *  WINFO_WOBJのp_wobjcbに記憶する.
153  *
154  *  (e) 待ち対象の同期・通信オブジェクトに依存して記憶することが必要な
155  *  情報がある場合には,WINFO_WOBJに必要な情報のためのフィールドを追加
156  *  した構造体を定義し,WINFO_WOBJの代わりに用いる.
157  *
158  *  待ち状態を解除する際には,待ち解除したタスクに対する返値をWINFOの
159  *  wercdに設定する.wercdが必要なのは待ち解除以降であるのに対して,
160  *  p_tmevtbは待ち解除後は必要ないため,メモリ節約のために共用体を使っ
161  *  ている.そのため,wercdへエラーコードを設定するのは,タイムイベント
162  *  ブロックを登録解除した後にしなければならない.
163  */
164 typedef union waiting_information {
165         ER              wercd;                  /* 待ち解除時のエラーコード */
166         TMEVTB  *p_tmevtb;              /* 待ち状態用のタイムイベントブロック */
167 } WINFO;
168
169 /*
170  *  タスク初期化ブロック
171  *
172  *  タスクに関する情報を,値が変わらないためにROMに置ける部分(タスク
173  *  初期化ブロック)と,値が変化するためにRAMに置かなければならない部
174  *  分(タスク管理ブロック,TCB)に分離し,TCB内に対応するタスク初期化
175  *  ブロックを指すポインタを入れる.タスク初期化ブロック内に対応する
176  *  TCBを指すポインタを入れる方法の方が,RAMの節約の観点からは望ましい
177  *  が,実行効率が悪くなるために採用していない.他のオブジェクトについ
178  *  ても同様に扱う.
179  *
180  *  タスク初期化ブロックには,DEF_TEXで定義されるタスク例外処理ルーチ
181  *  ンに関する情報も含む.
182  */
183 typedef struct task_initialization_block {
184         ATR                     tskatr;                 /* タスク属性 */
185         intptr_t        exinf;                  /* タスクの拡張情報 */
186         TASK            task;                   /* タスクの起動番地 */
187         uint_t          ipriority;              /* タスクの起動時優先度(内部表現) */
188
189 #ifdef USE_TSKINICTXB
190         TSKINICTXB      tskinictxb;             /* タスク初期化コンテキストブロック */
191 #else /* USE_TSKINICTXB */
192         SIZE            stksz;                  /* スタック領域のサイズ(丸めた値) */
193         void            *stk;                   /* スタック領域の先頭番地 */
194 #endif /* USE_TSKINICTXB */
195
196         ATR                     texatr;                 /* タスク例外処理ルーチン属性 */
197         TEXRTN          texrtn;                 /* タスク例外処理ルーチンの起動番地 */
198 } TINIB;
199
200 /*
201  *  TCB中のフィールドのビット幅の定義
202  *
203  *  プロセッサによっては,TCB中のフィールドのビット幅でメモリ使用量と
204  *  性能がトレードオフになるため,ターゲット依存にフィールドのビット幅
205  *  を変更することを許している.
206  */
207 #ifndef TBIT_TCB_PRIORITY
208 #define TBIT_TCB_PRIORITY               8               /* priorityフィールドのビット幅 */
209 #endif /* TBIT_TCB_PRIORITY */
210
211 /*
212  *  タスク管理ブロック(TCB)
213  *
214  *  ASPカーネルでは,タスクの起動要求キューイング数の最大値(TMAX_ACTCNT)
215  *  と起床要求キューイング数の最大値(TMAX_WUPCNT)は1に固定されている
216  *  ため,キューイングされているかどうかの真偽値で表現することができる.
217  *  また,強制待ち要求ネスト数の最大値(TMAX_SUSCNT)が1に固定されてい
218  *  るので,強制待ち要求ネスト数(suscnt)は必要ない.
219  *
220  *  TCBのいくつかのフィールドは,特定のタスク状態でのみ有効な値を保持し,
221  *  それ以外の場合は値が保証されない(よって,参照してはならない).各
222  *  フィールドが有効な値を保持する条件は次の通り.
223  *
224  *  ・初期化後は常に有効:
225  *              p_tinib,tstat,actque
226  *  ・休止状態以外で有効(休止状態では初期値になっている):
227  *              priority,wupque,enatex,texptn,leftotm
228  *  ・待ち状態(二重待ち状態を含む)で有効:
229  *              p_winfo
230  *  ・実行できる状態と同期・通信オブジェクトに対する待ち状態で有効:
231  *              task_queue
232  *  ・実行可能状態,待ち状態,強制待ち状態,二重待ち状態で有効:
233  *              tskctxb
234  */
235 typedef struct task_control_block {
236         QUEUE                   task_queue;             /* タスクキュー */
237         const TINIB             *p_tinib;               /* 初期化ブロックへのポインタ */
238
239 #ifdef UINT8_MAX
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;
248                                                                         /* 現在の優先度(内部表現)*/
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;             /* タスク例外処理許可状態 */
253
254         TEXPTN                  texptn;                 /* 保留例外要因 */
255         WINFO                   *p_winfo;               /* 待ち情報ブロックへのポインタ */
256         OVRTIM                  leftotm;                /* 残りプロセッサ時間 */
257         TSKCTXB                 tskctxb;                /* タスクコンテキストブロック */
258 } TCB;
259
260 /*
261  *  実行状態のタスク
262  *
263  *  実行状態のタスク(=プロセッサがコンテキストを持っているタスク)の
264  *  TCBを指すポインタ.実行状態のタスクがない場合はNULLにする.
265  *
266  *  サービスコールの処理中で,自タスク(サービスコールを呼び出したタス
267  *  ク)に関する情報を参照する場合はp_runtskを使う.p_runtskを書き換え
268  *  るのは,ディスパッチャ(と初期化処理)のみである.
269  */
270 extern TCB      *p_runtsk;
271
272 /*
273  *  最高優先順位のタスク
274  *
275  *  実行できるタスクの中で最高優先順位のタスクのTCBを指すポインタ.実
276  *  行できるタスクがない場合はNULLにする.
277  *
278  *  ディスパッチ禁止状態など,ディスパッチが保留されている間はp_runtsk
279  *  と一致しているとは限らない.
280  */
281 extern TCB      *p_schedtsk;
282
283 /*
284  *  ディスパッチ/タスク例外処理ルーチン起動要求フラグ
285  *
286  *  割込みハンドラ/CPU例外ハンドラの出口処理に,ディスパッチまたは
287  *  タスク例外処理ルーチンの起動を要求することを示すフラグ.
288  */
289 extern bool_t   reqflg;
290
291 /*
292  *  ディスパッチ禁止状態
293  *
294  *  ディスパッチ禁止状態であることを示すフラグ.
295  */
296 extern bool_t   disdsp;
297
298 /*
299  *  タスクディスパッチ可能状態
300  *
301  *  割込み優先度マスク全解除状態であり,ディスパッチ許可状態である(ディ
302  *  スパッチ禁止状態でない)ことを示すフラグ.
303  */
304 extern bool_t   dspflg;
305
306 /*
307  *  レディキュー
308  *
309  *  レディキューは,実行できる状態のタスクを管理するためのキューである.
310  *  実行状態のタスクも管理しているため,レディ(実行可能)キューという
311  *  名称は正確ではないが,レディキューという名称が定着しているため,こ
312  *  の名称で呼ぶことにする.
313  *
314  *  レディキューは,優先度ごとのタスクキューで構成されている.タスクの
315  *  TCBは,該当する優先度のキューに登録される.
316  */
317 extern QUEUE    ready_queue[TNUM_TPRI];
318
319 /*
320  *  レディキューサーチのためのビットマップ
321  *
322  *  レディキューのサーチを効率よく行うために,優先度ごとのタスクキュー
323  *  にタスクが入っているかどうかを示すビットマップを用意している.ビッ
324  *  トマップを使うことで,メモリアクセスの回数を減らすことができるが,
325  *  ビット操作命令が充実していないプロセッサで,優先度の段階数が少ない
326  *  場合には,ビットマップ操作のオーバーヘッドのために,逆に効率が落ち
327  *  る可能性もある.
328  *
329  *  優先度が16段階であることを仮定しているため,uint16_t型としている.
330  */
331 extern uint16_t ready_primap;
332
333 /*
334  *  タスクIDの最大値(kernel_cfg.c)
335  */
336 extern const ID tmax_tskid;
337
338 /*
339  *  タスク初期化ブロックのエリア(kernel_cfg.c)
340  */
341 extern const TINIB      tinib_table[];
342
343 /*
344  *  タスク生成順序テーブル(kernel_cfg.c)
345  */
346 extern const ID torder_table[];
347
348 /*
349  *  TCBのエリア(kernel_cfg.c)
350  */
351 extern TCB      tcb_table[];
352
353 /*
354  *  タスクの数
355  */
356 #define tnum_tsk        ((uint_t)(tmax_tskid - TMIN_TSKID + 1))
357
358 /*
359  *  タスクIDからTCBを取り出すためのマクロ
360  */
361 #define INDEX_TSK(tskid)        ((uint_t)((tskid) - TMIN_TSKID))
362 #define get_tcb(tskid)          (&(tcb_table[INDEX_TSK(tskid)]))
363 #define get_tcb_self(tskid)     ((tskid) == TSK_SELF ? p_runtsk : get_tcb(tskid))
364
365 /*
366  *  TCBからタスクIDを取り出すためのマクロ
367  */
368 #define TSKID(p_tcb)    ((ID)(((p_tcb) - tcb_table) + TMIN_TSKID))
369
370 /*
371  *  タスク管理モジュールの初期化
372  */
373 extern void     initialize_task(void);
374
375 /*
376  *  最高優先順位タスクのサーチ
377  *
378  *  レディキュー中の最高優先順位のタスクをサーチし,そのTCBへのポインタ
379  *  を返す.レディキューが空の場合には,この関数を呼び出してはならない.
380  */
381 extern TCB      *search_schedtsk(void);
382
383 /*
384  *  実行できる状態への遷移
385  *
386  *  p_tcbで指定されるタスクをレディキューに挿入する.レディキューに挿入
387  *  したタスクの優先度が,最高優先順位のタスクの優先度よりも高い場合は,
388  *  最高優先順位のタスクを更新し,ディスパッチ許可状態であればtrueを返
389  *  す.そうでない場合はfalseを返す.
390  */
391 extern bool_t   make_runnable(TCB *p_tcb);
392
393 /*
394  *  実行できる状態から他の状態への遷移
395  *
396  *  p_tcbで指定されるタスクをレディキューから削除する.p_tcbで指定した
397  *  タスクが最高優先順位のタスクであった場合には,最高優先順位のタスク
398  *  を設定しなおし,ディスパッチ許可状態であればtrueを返す.そうでない
399  *  場合はfalseを返す.タスクの状態は更新しない.
400  */
401 extern bool_t   make_non_runnable(TCB *p_tcb);
402
403 /*
404  *  休止状態への遷移
405  *
406  *  p_tcbで指定されるタスクの状態を休止状態とする.また,タスクの起動
407  *  時に初期化すべき変数の初期化と,タスク起動のためのコンテキストを設
408  *  定する.
409  */
410 extern void     make_dormant(TCB *p_tcb);
411
412 /*
413  *  休止状態から実行できる状態への遷移
414  *
415  *  p_tcbで指定されるタスクの状態を休止状態から実行できる状態とする.
416  *  実行できる状態に遷移したタスクへのディスパッチが必要な場合はtrue,
417  *  そうでない場合はfalseを返す.
418  */
419 extern bool_t   make_active(TCB *p_tcb);
420
421 /*
422  *  タスクの優先度の変更
423  *
424  *  p_tcbで指定されるタスクの優先度をnewpri(内部表現)に変更する.また,
425  *  必要な場合には最高優先順位のタスクを更新し,ディスパッチ許可状態で
426  *  あればtrueを返す.そうでない場合はfalseを返す.
427  */
428 extern bool_t   change_priority(TCB *p_tcb, uint_t newpri);
429
430 /*
431  *  レディキューの回転
432  *
433  *  レディキュー中の,priで指定される優先度のタスクキューを回転させる.
434  *  また,必要な場合には最高優先順位のタスクを変更し,ディスパッチが保
435  *  留されていなければtrueを返す.そうでない場合はfalseを返す.
436  */
437 extern bool_t   rotate_ready_queue(uint_t pri);
438
439 /*
440  *  タスク例外処理ルーチンの呼出し
441  *
442  *  タスク例外処理ルーチンを呼び出す.呼び出す前に,実行状態のタスクの
443  *  保留例外要因をクリアし,タスク例外処理禁止状態にし,CPUロックを解
444  *  除する.
445  *
446  *  タスク例外処理ルーチンから戻ると,まずCPUロック状態に戻し,その間
447  *  に保留例外要因が0でなくなっていれば,再びタスク例外処理ルーチンを
448  *  呼び出す.保留例外要因が0の場合には,例外処理許可状態にして関数か
449  *  らリターンする.
450  *
451  *  この関数は,実行状態のタスクが,タスク例外処理許可状態(enatexが
452  *  true)で,保留例外要因が0でない(texptnが0でない)場合に呼び出すこ
453  *  とを想定している.この関数は,CPUロック状態で呼び出さなければなら
454  *  ない.
455  */
456 extern void     call_texrtn(void);
457
458 /*
459  *  タスク例外処理ルーチンの起動
460  *
461  *  実行状態のタスクがタスク例外処理ルーチンの起動条件を満たしていれば,
462  *  タスク例外処理ルーチンを呼び出す.CPU例外処理ルーチンを呼び出す時
463  *  は,一時的にCPUロックを解除する.
464  *
465  *  この関数は,ディスパッチャや割込みハンドラ/CPU例外ハンドラの出口
466  *  処理から呼び出されることを想定している.この関数は,CPUロック状態
467  *  で呼び出さなければならない.
468  *
469  *  実行効率を上げるために,この関数をターゲット依存部で記述してもよい.
470  *  その場合には,OMIT_CALLTEXをマクロ定義する.
471  */
472 extern void     calltex(void);
473
474 #endif /* TOPPERS_TASK_H */