OSDN Git Service

a3873529a4a92efb45ea689d4f3de3a24591b550
[trx-305dsp/dsp.git] / hirado / kernel / doc / design.txt
1
2                     = JSPカーネル 設計メモ =
3
4              (Release 1.4対応,最終更新: 15-Mar-2005)
5
6 ------------------------------------------------------------------------ 
7  TOPPERS/JSP Kernel
8      Toyohashi Open Platform for Embedded Real-Time Systems/
9      Just Standard Profile Kernel
10
11  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
12                              Toyohashi Univ. of Technology, JAPAN
13
14  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
15  によって公表されている GNU General Public License の Version 2 に記
16  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
17  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
18  利用と呼ぶ)することを無償で許諾する.
19  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
20      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
21      スコード中に含まれていること.
22  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
23      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
24      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
25      の無保証規定を掲載すること.
26  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
27      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
28      と.
29    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
30        作権表示,この利用条件および下記の無保証規定を掲載すること.
31    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
32        報告すること.
33  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
34      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
35
36  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
37  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
38  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
39  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
40
41  @(#) $Id: design.txt,v 1.1 2009/01/31 05:27:37 suikan Exp $
42 ------------------------------------------------------------------------
43
44
45 1.JSPカーネルにおける制限事項
46
47 (1) サポートする機能
48
49 JSPカーネルは,名前の通りスタンダードプロファイルに含まれる機能のみを
50 サポートする.スタンダードプロファイル外の機能は,原則としてサポートし
51 ない.
52
53 内部構造の設計にあたっては,スタンダードプロファイル外の機能をサポート
54 するための拡張性は考慮せず,スタンダードプロファイルに含まれる機能を効
55 率良く実現することを目指す.
56
57 (2) サービスコール内での割込みの扱い
58
59 JSPカーネルでは,サービスコールはすべて割込み禁止で実行する.スタンダー
60 ドプロファイルの機能の範囲内では,この方法で十分と考えられるが,拡張機
61 能を追加する時には設計を見直すべきである.具体的には,非タスクコンテキ
62 ストから呼び出されたサービスコールを遅延実行する方法が有力である.
63
64 (3) CPU例外ハンドラの実行コンテキスト
65
66 JSPカーネルでは,CPU例外ハンドラは非タスクコンテキストで実行する.
67
68 参考: μITRON4.0仕様では,タスクコンテキストで発生したCPU例外に対する
69 CPU例外ハンドラを,タスクコンテキストで実行するか非タスクコンテキスト
70 で実行するかは,実装定義としている.
71
72
73 2.実行コンテキストとシステム状態の仮想化
74
75 (1) 実行コンテキスト
76
77 実行コンテキストは,タスクコンテキストと非タスクコンテキストのいずれか
78 に分類される.
79
80 実行コンテキストの管理はターゲット依存部で行う.具体的には,タスクコン
81 テキストと非タスクコンテキストを判別する関数(sense_context)を,ター
82 ゲット依存部で用意する.
83
84 また,タスクコンテキストと非タスクコンテキストの間の遷移も,ターゲット
85 依存部の責任である.具体的には,割込みハンドラ/CPU例外ハンドラが起動
86 されると非タスクコンテキストに切り換わり,割込みハンドラ/CPU例外ハン
87 ドラからリターンすると元の実行コンテキストに戻るよう,ターゲット依存部
88 を実装する.
89
90 (2) CPUロック状態
91
92 システムは,CPUロック状態か,CPUロック解除状態のいずれかにある.CPUロッ
93 ク状態では,すべての割込み(カーネルの管理外のものを除く.以下同じ)が
94 禁止されている.
95
96 CPUロック状態の管理はターゲット依存部で行う.具体的には,CPUロック状態/
97 CPUロック解除状態のいずれの状態であるかを判別する関数(sense_lock,
98 t_sense_lock,i_sense_lock)と,CPUロック状態とCPUロック解除状態の間を
99 遷移させる関数(t_lock_cpu,t_unlock_cpu,i_lock_cpu,i_unlock_cpu)を,
100 ターゲット依存部で用意する.これらの関数を呼び出す以外の方法で,CPUロッ
101 ク状態とCPUロック解除状態の間を遷移することはない.
102
103
104 3.ディスパッチとタスク例外処理ルーチン起動の方法
105
106 (1) ディスパッチが必要なタイミング
107
108 ディスパッチを行う必要があるのは,以下のタイミングである.
109
110 (a) サービスコール内での明示的なタスクディスパッチ要求
111
112 タスクコンテキストから呼び出されたサービスコール処理において,明示的に
113 タスクディスパッチが要求された場合.具体的には,実行状態のタスクよりも
114 優先順位の高く実行できる状態のタスクが生じる場合と,実行状態のタスク
115 (自タスク)を待ち状態にする場合がある.いずれの場合にも,サービスコー
116 ル処理内でディスパッチャを明示的に呼び出すことで,ディスパッチを行う.
117
118 (b) 割込みハンドラ/CPU例外ハンドラの出口
119
120 割込みハンドラ/CPU例外ハンドラ(以下,ハンドラと総称する)から呼び出
121 されたサービスコールでタスクディスパッチが要求された場合,ハンドラの出
122 口でタスクディスパッチが必要かチェックし,必要であればタスクディスパッ
123 チを行う.ハンドラが多重に起動されている場合,最も外側のハンドラの出口
124 でのみ行う(※).
125
126 ※ プロセッサによっては,CPU例外ハンドラの入口処理の先頭では,非タスク
127 コンテキストであると認識させられない場合がある.このような場合,入口処
128 理の途中でハンドラが多重に起動されても,内側のハンドラでさらに外側のハ
129 ンドラがあることを認識できず,内側のハンドラでタスクディスパッチを行う
130 ことになる.この場合でも,入口処理の非タスクコンテキストであると認識さ
131 れない部分は,ハンドラの一部ではないと解釈すれば,上記の原則は守られて
132 いることになる.この注記は,以下の記述にも同様にあてはまる.
133
134 (2) タスク例外処理ルーチンの起動が必要なタイミング
135
136 タスク例外処理ルーチンを起動するのは,仕様書によると,「タスク例外処理
137 許可状態」「保留例外要因が 0 でない」「タスクが実行状態である」「非タ
138 スクコンテキストまたはCPU例外ハンドラが実行されていない」の四つの条件
139 が揃った場合である.このことから,タスク例外処理ルーチンの起動を行う必
140 要があるのは,以下のタイミングである.
141
142 (a) タスクディスパッチの直後
143
144 タスクディスパッチにより,実行状態のタスク(runtsk)が変化する.新しく
145 実行状態になったタスクが起動条件を満たしていれば,タスク例外処理ルーチ
146 ンを起動する.
147
148 (b) 割込みハンドラ/CPU例外ハンドラの出口
149
150 割込みハンドラ/CPU例外ハンドラ(以下,ハンドラと総称する)の出口では,
151 タスクディスパッチを行う場合がある.その場合には,(a) の理由で必要なら,
152 タスク例外処理ルーチンを起動する.
153
154 ハンドラの出口でタスクディスパッチを行わない場合でも,ハンドラ内で実行
155 状態のタスクに対してタスク例外処理が要求された場合には,ハンドラの出口
156 で起動条件をチェックし,起動条件を満たしていればタスク例外処理ルーチン
157 を起動する.ハンドラが多重に起動されている場合,最も外側のハンドラの出
158 口でのみ行う(※).
159
160 (c) 自タスクに対するタスク例外処理の要求
161
162 自タスクに対してタスク例外処理を要求した結果,自タスクが起動条件を満た
163 すようになれば,タスク例外処理ルーチンを起動する.
164
165 (d) タスク例外処理の許可
166
167 タスク例外処理許可状態に移行した結果,自タスクが起動条件を満たすように
168 なれば,タスク例外処理ルーチンを起動する.タスク例外処理許可状態への移
169 行は,ena_tex の呼出しによって起こる.
170
171 (3) サービスコール処理内での明示的なディスパッチャの呼出し
172
173 タスクコンテキストから呼び出されたサービスコール処理においてディスパッ
174 チが必要になった場合,サービスコールの処理を中断すべきタイミングで 
175 dispatch を呼び出す.dispatch を呼び出すと,その時点で最も優先順位の高
176 いタスクが実行される.dispatch は,呼び出したタスクが次に実行状態にな
177 るとタスク例外処理ルーチンの起動条件をチェックし,起動条件を満たしてい
178 ればタスク例外処理ルーチンを起動する.
179
180 そのため,dispatch を呼び出したサービスコールへ処理が戻ってくるのは,
181 呼び出したタスクが次に実行状態となり,起動すべきタスク例外処理ルーチン
182 がなくなった時点である.
183
184 なお,dispatch の処理は,ターゲット依存部で提供される.
185
186 (4) 割込みハンドラ/CPU例外ハンドラの出口での処理
187
188 割込みハンドラ/CPU例外ハンドラ(以下,ハンドラと総称する)の出口処理
189 では,ディスパッチが必要か,タスク例外処理ルーチンの起動が必要かをチェッ
190 クし,必要な処理を行う.ハンドラが多重に起動されている場合,最も外側の
191 ハンドラの出口でのみこの処理を行う.
192
193 具体的には,ディスパッチとタスク例外処理ルーチンの起動のいずれかの処理
194 が必要な場合には reqflg を TRUE にすることとし,最も外側のハンドラの出
195 口で reqflg が TRUE になっていれば,まずディスパッチが必要かチェックし,
196 必要ならディスパッチを行う.ディスパッチにより新たに実行状態になったタ
197 スクがタスク例外処理ルーチンの起動条件を満たしていれば,タスク例外処理
198 ルーチンを起動する.ディスパッチが必要なかった場合には,実行中のタスク
199 がタスク例外処理ルーチンの起動条件を満たしているかチェックし,満たして
200 いればタスク例外処理ルーチンを起動する.二つのタスク例外処理ルーチンの
201 起動処理は,意味的には異なるものだが,ルーチン的には共通化できる可能性
202 がある.
203
204 なお,ハンドラの出口処理は,ターゲット依存部で提供される.
205
206 (5) タスクの起動と終了時の処理
207
208 タスク起動時のレジスタ復帰と,タスク終了時のレジスタ保存は,ターゲット
209 依存部の実装によっては省略できる.
210
211 タスクの起動は,create_context と activate_context によって,次にその
212 タスクへのディスパッチが起こった時に,タスクの起動番地から実行するよう
213 にタスクコンテキストを設定することで行う.
214
215 タスク終了時には,unlock_cpu に代えて,exit_and_dispatch を呼び出す.
216 exit_and_dispatch は,現在実行中のコンテキストを保存せずに,ディスパッ
217 チを行う関数である.
218
219 なお,create_context,activate_context,exit_and_dispatch の処理は,ター
220 ゲット依存部で提供される.
221
222 (6) 実行できる状態のタスクがない場合の扱い
223
224 実行できる状態のタスクがない場合の対策として,アイドルタスクを導入する
225 方法がある.アイドルタスクを導入すると,ディスパッチャの途中で割込み待
226 ちをする必要がないので,ソフトウェアの構造的にはエレガントになる.また,
227 ディスパッチャ中での条件分岐も減る.逆に,RAM の使用量がどうしても増え
228 てしまうという問題がある.このことから,アイドルタスクは使わない方針と
229 する.
230
231 (7) ディスパッチ保留状態の保持方法
232
233 ディスパッチが保留されるのは,次のいずれかの場合である.
234
235  ・ディスパッチ禁止状態
236  ・非タスクコンテキスト実行中
237
238 CPU例外ハンドラは非タスクコンテキストで実行するとしたため,CPU例外ハン
239 ドラ実行中は,非タスクコンテキスト実行中に含めて考えることができる.ま
240 た,サービスコールはすべて割込み禁止で実行するため,サービスコール実行
241 中も考慮する必要がない.
242
243 この中で,非タスクコンテキスト実行中は,sense_context() で判定できる.
244 そこで,ディスパッチ禁止状態を表すBOOL型の変数を用意すれば,ディスパッ
245 チ保留状態が保持できることになる.実際には,ディスパッチ許可状態を表す
246 BOOL型の変数 enatex を導入した.
247
248 ※ サービスコール実行中に割込みを許可する(ディスパッチは許可しない)
249 場合には,サービスコール処理の途中で起動された割込みハンドラの出口では,
250 ディスパッチもタスク例外処理ルーチンの起動も行ってはならない.参照する
251 場所が違うことから,両者の禁止を別々の変数にする方法も考えられるが,設
252 定する方の効率を考えると,一つの変数で両方禁止できる方が良いと思われる.
253 すなわち,ディスパッチ禁止状態とサービスコール実行中状態を,同じ変数を
254 ビットフィールドに分けて記憶するのが妥当と考えられる.さらに,CPU例外
255 ハンドラをタスクコンテキストで実行する実装では,同じ変数にCPU例外ハン
256 ドラのネスト回数も記憶したくなる.例えば,次のような変数 pndflg を導入
257 する方法が考えられる.
258
259  ・最下位ビット … サービスコール実行中
260                                 → 1 なら両者保留
261  ・下から2ビットめ … ディスパッチ禁止状態
262                                 → 1 ならタスク切替え保留
263  ・残りのビット … CPU例外ハンドラのネスト回数
264                                 → 0 以外ならタスク切替え保留
265
266
267 4.サービスコールの記述方法
268
269 (1) sns_xxx
270
271 sns_ctx,sns_loc,sns_dsp,sns_tex は,サービスコール内部でクリティカ
272 ルセクションを作らなくても実装できる.
273
274 (2) タスクコンテキスト専用のサービスコール
275
276 ※ CPUロック状態で呼ばれるとエラーになることに注意.
277
278 (2-1) タスク切換えを起こさないもの(例: get_pri)
279
280         エラーチェック
281         t_lock_cpu();
282         /*
283          *  クリティカルセクション実行
284          */
285         t_unlock_cpu();
286
287 (2-2) タスク切換えを起こす可能性のあるもの(例: act_tsk)
288
289         エラーチェック
290         t_lock_cpu();
291         /*
292          *  クリティカルセクション実行
293          */
294         if (タスクディスパッチが必要 && enadsp) {
295                 /* 自タスクを待ち状態にするサービスコールでは,
296                         上で enadsp をチェックする必要はない.*/
297                 dispatch();
298         }
299         t_unlock_cpu();
300
301 (2-3) 自タスクを終了するもの(ext_tsk)
302
303         エラーチェック
304         t_lock_cpu();
305         /*
306          *  クリティカルセクション実行
307          */
308         exit_and_dispatch();
309
310 (2-4) ras_tex
311
312         エラーチェック
313         tcb = get_tcb_self(tskid);
314         t_lock_cpu();
315
316         E_OBJエラーのチェック
317
318         tcb->texptn |= rasptn;
319         if (tcb == runtsk && runtsk->enatex) {
320                 texptn = runtsk->texptn;
321                 runtsk->enatex = FALSE;
322                 runtsk->texptn = 0;
323
324                 t_unlock_cpu();
325                 (*runtsk->tinib->texrtn)(texptn, runtsk->tinib->exinf);
326
327                 /* CPUロック状態のままリターンした場合を対策 */
328                 if (!t_sense_lock()) {
329                         t_lock_cpu();
330                 }
331
332                 タスク例外処理ルーチンの起動条件を再度チェック&起動
333                 (runtsk->texptn が 0 になるまで上の処理を繰り返す)
334
335                 runtsk->enatex = TRUE;
336         }
337         t_unlock_cpu();
338
339 (2-5) ena_tex
340
341         エラーチェック
342         t_lock_cpu();
343
344         E_OBJエラーのチェック
345
346         runtsk->enatex = TRUE;
347         if (runtsk->texptn != 0) {
348                 texptn = runtsk->texptn;
349                 runtsk->enatex = FALSE;
350                 runtsk->texptn = 0;
351
352                 t_unlock_cpu();
353                 (*runtsk->tinib->texrtn)(texptn, runtsk->tinib->exinf);
354
355                 /* CPUロック状態のままリターンした場合を対策 */
356                 if (!t_sense_lock()) {
357                         t_lock_cpu();
358                 }
359
360                 タスク例外処理ルーチンの起動条件を再度チェック&起動
361                 (runtsk->texptn が 0 になるまで上の処理を繰り返す)
362
363                 runtsk->enatex = TRUE;
364         }
365         t_unlock_cpu();
366
367 (3) 非タスクコンテキスト専用のサービスコール
368
369 ※ CPUロック状態で呼ばれるとエラーになることに注意.
370
371 (3-1) タスク切替えを起こさないもの
372
373         i_lock_cpu();
374         /*
375          *  クリティカルセクション実行
376          */
377         i_unlock_cpu();
378
379 (3-2) タスク切替えを起こす可能性のあるもの(例: iact_tsk)
380
381         i_lock_cpu();
382         /*
383          *  クリティカルセクション実行
384          *
385          *  タスクディスパッチが必要な場合には,reqflg を TRUE にする.
386          *  ただし,enadsp が FALSE の時は,reqflg を TRUE にしない.
387          */
388         i_unlock_cpu();
389
390 (3-3) iras_tex
391
392         エラーチェック
393         tcb = get_tcb(tskid);
394         i_lock_cpu();
395
396         E_OBJエラーのチェック
397
398         tcb->texptn |= rasptn;
399         if (tcb == runtsk && runtsk->enatex) {
400                 reqflg = TRUE;
401         }
402         i_unlock_cpu();
403
404 以上
405
406