source: uKadecot/trunk/ssp/kernel/task.c@ 108

Last change on this file since 108 was 108, checked in by coas-nagasima, 9 years ago

MIMEプロパティの変更

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-chdr; charset=SHIFT_JIS
File size: 9.2 KB
RevLine 
[101]1/*
2 * TOPPERS/SSP Kernel
3 * Smallest Set Profile Kernel
4 *
5 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
6 * Toyohashi Univ. of Technology, JAPAN
7 * Copyright (C) 2005-2009 by Embedded and Real-Time Systems Laboratory
8 * Graduate School of Information Science, Nagoya Univ., JAPAN
9 * Copyright (C) 2010-2015 by Naoki Saito
10 * Nagoya Municipal Industrial Research Institute, JAPAN
11 * Copyright (C) 2010 by Meika Sugimoto
12 *
13 * 上記著作権者は,以下の (1)〜(4) の条件を満たす場合に限り,本ソフトウェ
14 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改変・
15 * 再配布(以下,利用と呼ぶ)することを無償で許諾する.
16 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作権
17 * 表示,この利用条件および下記の無保証規定が,そのままの形でソース
18 * コード中に含まれていること.
19 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使用
20 * できる形で再配布する場合には,再配布に伴うドキュメント(利用者マ
21 * ニュアルなど)に,上記の著作権表示,この利用条件および下記の無保
22 * 証規定を掲載すること.
23 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使用
24 * できない形で再配布する場合には,次のいずれかの条件を満たすこと.
25 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著作
26 * 権表示,この利用条件および下記の無保証規定を掲載すること.
27 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに報
28 * 告すること.
29 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損害
30 * からも,上記著作権者およびTOPPERSプロジェクトを免責すること.また,
31 * 本ソフトウェアのユーザまたはエンドユーザからのいかなる理由に基づ
32 * く請求からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
33 *
34 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者およ
35 * びTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的に対す
36 * る適合性も含めて,いかなる保証も行わない.また,本ソフトウェアの利用
37 * により直接的または間接的に生じたいかなる損害に関しても,その責任を負
38 * わない.
39 *
40 */
41
42#include "kernel_impl.h"
43#include "task.h"
44
45/*
46 * トレースログマクロのデフォルト定義
47 */
48
49#ifndef LOG_DSP_ENTER
50 #define LOG_DSP_ENTER(tskidx)
51#endif /* LOG_DSP_ENTER */
52
53#ifndef LOG_DSP_LEAVE
54 #define LOG_DSP_LEAVE(tskidx)
55#endif /* LOG_DSP_ENTER */
56
57
58extern const intptr_t tinib_exinf[]; /* タスクの拡張情報 */
59extern const TASK tinib_task[]; /* タスクの起動番地 */
60extern const uint_t tinib_epriority[]; /* タスクの実行時優先度(内部表現) */
61
62/* 内部関数のプロトタイプ宣言 */
63Inline bool_t primap_empty(void);
64Inline bool_t primap_test(uint_t pri);
65Inline uint_t primap_search(void);
66Inline void primap_set(uint_t pri);
67Inline void primap_clear(uint_t pri);
68Inline uint_t bitmap_search(uint_t bitmap);
69
70
71#ifdef TOPPERS_tskini
72
73/*
74 * 実行状態タスクの現在優先度
75 */
76uint_t runtsk_curpri;
77
78/*
79 * 実行状態タスクの起動時優先度
80 */
81uint_t runtsk_ipri;
82
83/*
84 * レディキューサーチのためのビットマップ
85 */
86volatile uint_t ready_primap;
87
88/*
89 * 起動要求キューイングのビットマップ
90 */
91uint_t actque_bitmap;
92
93/*
94 * タスクディスパッチ起動要求フラグ
95 */
96bool_t reqflg;
97
98/*
99 * ディスパッチ禁止状態
100 */
101bool_t disdsp;
102
103/*
104 * read_primapの初期値
105 */
106extern const uint_t init_rdypmap;
107
108#endif /* TOPPERS_tskini */
109
110#ifdef TOPPERS_get_ipriself
111
112/*
113 * タスクIDからの起動時優先度取得(タスクコンテキスト用)
114 */
115uint_t
116get_ipri_self(ID tskid)
117{
118 uint_t ipri;
119
120 if(tskid != TSK_SELF)
121 {
122 ipri = (uint_t)((tskid) - TMIN_TSKID);
123 }
124 else
125 {
126 ipri = runtsk_ipri;
127 }
128 return ipri;
129}
130
131#endif /* TOPPERS_get_ipriself */
132
133/*
134 * タスクIDからの起動時優先度取得(非タスクコンテキスト用)
135 */
136#ifdef TOPPERS_get_ipri
137
138uint_t
139get_ipri(ID tskid)
140{
141 return (uint_t)(tskid - TMIN_TSKID);
142}
143
144#endif /* TOPPERS_get_ipri */
145
146/*
147 * ビットマップサーチ関数
148 *
149 * bitmap内の1のビットの内,最も下位(右)のものをサーチし,そのビッ
150 * ト番号を返す.ビット番号は,最下位ビットを0とする.bitmapに0を指定
151 * してはならない.この関数では,bitmapが8ビットであることを仮定し,
152 * uint8_t型としている.
153 *
154 * ビットサーチ命令を持つプロセッサでは,ビットサーチ命令を使うように
155 * 書き直した方が効率が良い場合がある.このような場合には,ターゲット
156 * 依存部でビットサーチ命令を使ったbitmap_searchを定義し,
157 * OMIT_BITMAP_SEARCHをマクロ定義すればよい.また,ビットサーチ命令の
158 * サーチ方向が逆などの理由で優先度とビットとの対応を変更したい場合に
159 * は,PRIMAP_BITをマクロ定義すればよい.
160 *
161 * また,標準ライブラリにffsがあるなら,次のように定義して標準ライブ
162 * ラリを使った方が効率が良い可能性もある.
163 * #define bitmap_search(bitmap) (ffs(bitmap) - 1)
164 */
165#ifndef PRIMAP_BIT
166#define PRIMAP_BIT(pri) (1U << (pri))
167#endif /* PRIMAP_BIT */
168
169#ifndef OMIT_BITMAP_SEARCH
170
171static const uint8_t bitmap_search_table[] = { 0U, 1U, 0U, 2U, 0U, 1U, 0U,
172 3U, 0U, 1U, 0U, 2U, 0U, 1U, 0U };
173
174Inline uint_t
175bitmap_search(uint_t bitmap)
176{
177 uint_t n = 0U;
178
179#if TMAX_TPRI != 8
180 if ((bitmap & 0x00ffU) == 0U) {
181 bitmap >>= 8U;
182 n += 8U;
183 }
184#endif
185
186 if ((bitmap & 0x0fU) == 0U) {
187 bitmap >>= 4U;
188 n += 4U;
189 }
190 return (n + bitmap_search_table[(bitmap & 0x0fU) - 1U]);
191}
192
193#endif /* OMIT_BITMAP_SEARCH */
194
195
196/*
197 * 起動時優先度ビットマップが空かのチェック
198 */
199Inline bool_t
200primap_empty(void)
201{
202 return (ready_primap == 0U);
203}
204
205/*
206 * 指定した起動時優先度の起動時優先度ビットマップがセットされているかどうかのチェック
207 */
208Inline bool_t
209primap_test(uint_t pri)
210{
211 return ((ready_primap & PRIMAP_BIT(pri)) != 0U);
212}
213
214/*
215 * 起動時優先度ビットマップのサーチ
216 */
217Inline uint_t
218primap_search(void)
219{
220 return bitmap_search(ready_primap);
221}
222
223/*
224 * 起動時優先度ビットマップのセット
225 */
226Inline void
227primap_set(uint_t pri)
228{
229 ready_primap |= PRIMAP_BIT(pri);
230}
231
232/*
233 * 起動時優先度ビットマップのクリア
234 */
235Inline void
236primap_clear(uint_t pri)
237{
238 ready_primap &= ~PRIMAP_BIT(pri);
239}
240
241/*
242 * 最高優先順位タスクのサーチ
243 */
244
245#ifdef TOPPERS_tsksched
246
247uint_t
248search_schedtsk(void)
249{
250 return primap_search();
251}
252
253#endif /* TOPPERS_tsksched */
254
255#ifdef TOPPERS_tskdmt
256/*
257 * 指定した起動時優先度のタスクが実行できる状態かどうかのテスト
258 *
259 */
260bool_t
261test_dormant(uint_t ipri)
262{
263 return !primap_test(ipri);
264}
265
266#endif /* TOPPERS_tskdmt */
267
268/*
269 * タスク管理モジュールの初期化
270 */
271
272
273#ifdef TOPPERS_tskini
274
275void
276initialize_task(void)
277{
278 /* 起動時優先度ビットマップの初期化 */
279 ready_primap = init_rdypmap;
280
281 /* タスク優先度の初期化 */
282 runtsk_curpri = TSKPRI_NULL;
283 runtsk_ipri = TSKPRI_NULL;
284
285 /* 起動要求キューイングの初期化 */
286 actque_bitmap = 0U;
287
288 /* 割込み禁止フラグの初期化 */
289 disdsp = false;
290}
291
292#endif /* TOPPERS_tskini */
293
294/*
295 * タスクの起動
296 */
297
298#ifdef TOPPERS_tskact
299
300bool_t
301make_active(uint_t ipri)
302{
303 bool_t dsp;
304
305 primap_set(ipri);
306
307 /*
308 * 実行状態タスクの現在優先度と引数で指定された
309 * 起動対象タスクの初期優先度を比較し,実行状態タスクを
310 * 変更するか判定する.
311 *
312 * ただし実行状態タスクを変更する場合はディスパッチ禁止状態も参照する.
313 */
314 if(ipri < runtsk_curpri) {
315 dsp = !disdsp;
316 }
317 else {
318 dsp = false;
319 }
320
321 return dsp;
322}
323
324#endif /* TOPPERS_tskact */
325
326
327/*
328 * タスクの実行
329 */
330
331#ifdef TOPPERS_tskrun
332
333void
334run_task(uint_t ipri)
335{
336 uint_t next_pri; /* 次に実行開始するタスクの起動時優先度 */
337 uint_t saved_ipri; /* 呼び出し元タスクの初期優先度 */
338 uint_t saved_curpri; /* 呼び出し元タスクの現在優先度 */
339 bool_t cont;
340
341 /* 最高優先順位タスクを実行する前に,現在実行中のタスクの現在優先度と初期優先度を保存する */
342 next_pri = ipri;
343 saved_ipri = runtsk_ipri;
344 saved_curpri = runtsk_curpri;
345
346 do {
347 /* 実行するタスクの現在優先度を実行時優先度に設定する */
348 runtsk_curpri = tinib_epriority[next_pri];
349 runtsk_ipri = next_pri;
350#ifndef _MSC_VER
351 /* CPUロック解除 */
352 t_unlock_cpu();
353
354 /* タスク実行開始 */
355 (*((TASK)(tinib_task[next_pri])))(tinib_exinf[next_pri]);
356#else
357 dispatch_task(next_pri);
358#endif
359 if (t_sense_lock()) {
360 /*
361 * CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し
362 * てからタスクを終了する.実装上は,サービスコール内でのCPU
363 * ロックを省略すればよいだけ.
364 */
365 }
366 else {
367 /*
368 * このt_lock_cpuをこの下のdisdspの設定のようにしないのは,
369 * CPUロック中に再度t_lock_cpuを呼ばないためである.
370 */
371 t_lock_cpu();
372 }
373
374 /* 割込み優先度マスクは全解除状態のはずなので,何もしない */
375
376 /*
377 * ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ
378 * チ許可状態にしてからタスクを終了する.
379 *
380 * 本来は以下のように記述すべきであるが,いずれにせよdisdspを
381 * falseにすればいいため,単にfalseに設定する.
382 *
383 * if (disdsp) {
384 * disdsp = false;
385 * }
386 */
387 disdsp = false;
388
389 /* ビットマップクリア. */
390 primap_clear(next_pri);
391
392 cont = false;
393
394 /* タスク起動要求キューイングのチェック */
395 if (actque_test(next_pri)) {
396 actque_clear(next_pri);
397 (void) make_active(next_pri);
398 }
399
400 /* いずれかのタスクが実行可能状態になっているか */
401 if(!primap_empty())
402 {
403 /* 戻り先タスクの現在優先度より高い起動時優先度をもつタスクが起動されたか */
404 next_pri = search_schedtsk();
405 if(saved_curpri > next_pri)
406 {
407 cont = true;
408 }
409 }
410 } while(cont);
411
412 runtsk_curpri = saved_curpri;
413 runtsk_ipri = saved_ipri;
414}
415
416#endif /* TOPPERS_tskrun */
417
418/*
419 * タスクディスパッチャ
420 */
421
422#ifdef TOPPERS_tskdsp
423
424void
425dispatcher(void)
426{
427 do {
428 if(!primap_empty()) {
429 /* タスクの開始 */
430 run_task(search_schedtsk());
431 }
432 else {
433 idle_loop();
434 }
435 } while(true);
436}
437
438#endif /* TOPPERS_tsk_dsp */
Note: See TracBrowser for help on using the repository browser.