source: atk2-sc3_fl850f1l/kernel/task.c@ 165

Last change on this file since 165 was 117, checked in by ertl-ishikawa, 9 years ago

ATK2-SC3 1.3.2 FL850F1L(RH850F1L)依存部(GCC/GHS/CCRH)を追加

File size: 15.2 KB
Line 
1/*
2 * TOPPERS ATK2
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 * Automotive Kernel Version 2
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2004-2015 by Center for Embedded Computing Systems
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 * Copyright (C) 2011-2015 by FUJI SOFT INCORPORATED, JAPAN
11 * Copyright (C) 2011-2013 by Spansion LLC, USA
12 * Copyright (C) 2011-2015 by NEC Communication Systems, Ltd., JAPAN
13 * Copyright (C) 2011-2015 by Panasonic Advanced Technology Development Co., Ltd., JAPAN
14 * Copyright (C) 2011-2014 by Renesas Electronics Corporation, JAPAN
15 * Copyright (C) 2011-2015 by Sunny Giken Inc., JAPAN
16 * Copyright (C) 2011-2015 by TOSHIBA CORPORATION, JAPAN
17 * Copyright (C) 2004-2015 by Witz Corporation
18 * Copyright (C) 2014-2015 by AISIN COMCRUISE Co., Ltd., JAPAN
19 * Copyright (C) 2014-2015 by eSOL Co.,Ltd., JAPAN
20 * Copyright (C) 2014-2015 by SCSK Corporation, JAPAN
21 *
22 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
23 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
24 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
25 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
26 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
27 * スコード中に含まれていること.
28 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
29 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
30 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
31 * の無保証規定を掲載すること.
32 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
33 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
34 * と.
35 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
36 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
37 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
38 * 報告すること.
39 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
40 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
41 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
42 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
43 * 免責すること.
44 *
45 * 本ソフトウェアは,AUTOSAR(AUTomotive Open System ARchitecture)仕
46 * 様に基づいている.上記の許諾は,AUTOSARの知的財産権を許諾するもので
47 * はない.AUTOSARは,AUTOSAR仕様に基づいたソフトウェアを商用目的で利
48 * 用する者に対して,AUTOSARパートナーになることを求めている.
49 *
50 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
51 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
52 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
53 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
54 * の責任を負わない.
55 *
56 * $Id: task.c 187 2015-06-25 03:39:04Z t_ishikawa $
57 */
58
59/*
60 * タスク制御モジュール
61 */
62
63#include "kernel_impl.h"
64#include "check.h"
65#include "task.h"
66#include "interrupt.h"
67
68/*
69 * トレースログマクロのデフォルト定義
70 */
71#ifndef LOG_TSKSTAT
72#define LOG_TSKSTAT(p_tcb)
73#endif /* LOG_TSKSTAT */
74
75/* 内部関数のプロトタイプ宣言 */
76LOCAL_INLINE uint16 bitmap_search(uint16 bitmap);
77LOCAL_INLINE boolean primap_empty(void);
78LOCAL_INLINE PriorityType primap_search(void);
79LOCAL_INLINE void primap_set(PriorityType pri);
80LOCAL_INLINE void primap_clear(PriorityType pri);
81
82#ifdef TOPPERS_task_initialize
83
84/*
85 * 実行状態のタスク
86 */
87TCB *p_runtsk;
88
89/*
90 * 最高優先順位タスク
91 */
92TCB *p_schedtsk;
93
94/*
95 * レディキュー中の最高優先度
96 */
97PriorityType nextpri;
98
99/*
100 * レディキュー
101 */
102QUEUE ready_queue[TNUM_TPRI];
103
104/*
105 * レディキューサーチのためのビットマップ
106 */
107uint16 ready_primap;
108
109/*
110 * タスク管理モジュールの初期化
111 */
112void
113task_initialize(void)
114{
115 TaskType i;
116 TCB *p_tcb;
117
118 p_runtsk = NULL;
119 p_schedtsk = NULL;
120
121 for (i = 0U; i < TNUM_TPRI; i++) {
122 queue_initialize(&(ready_queue[i]));
123 }
124 nextpri = TPRI_MINTASK;
125 ready_primap = 0U;
126
127 for (i = 0U; i < tnum_task; i++) {
128 p_tcb = &(tcb_table[i]);
129 p_tcb->p_tinib = &(tinib_table[i]);
130 p_tcb->actcnt = 0U;
131 p_tcb->curevt = 0U;
132 p_tcb->tstat = SUSPENDED;
133#ifdef CFG_USE_PROTECTIONHOOK
134 p_tcb->calltfn = FALSE;
135#endif /* CFG_USE_PROTECTIONHOOK */
136 if ((p_tcb->p_tinib->autoact & ((AppModeType) 1 << appmodeid)) != APPMODE_NONE) {
137 (void) make_active(p_tcb);
138 }
139 }
140}
141
142#endif /* TOPPERS_task_initialize */
143
144/*
145 * ビットマップサーチ関数
146 *
147 * bitmap内の1のビットの内,最も下位(右)のものをサーチし,そのビッ
148 * ト番号を返す
149 * ビット番号は,最下位ビットを0とする.bitmapに0を指定
150 * してはならない.この関数では,bitmapが16ビットであることを仮定し,
151 * uint16型としている
152 *
153 * ビットサーチ命令を持つプロセッサでは,ビットサーチ命令を使うように
154 * 書き直した方が効率が良い場合がある
155 * このような場合には,ターゲット依存部でビットサーチ命令を使った
156 * bitmap_searchを定義し,OMIT_BITMAP_SEARCHをマクロ定義すればよい
157 * また,ビットサーチ命令のサーチ方向が逆などの理由で優先度とビット
158 * との対応を変更したい場合には,PRIMAP_BITをマクロ定義すればよい
159 *
160 * また,標準ライブラリにffsがあるなら,次のように定義して標準ライブ
161 * ラリを使った方が効率が良い可能性もある
162 * #define bitmap_search(bitmap) (ffs(bitmap) - 1)
163 */
164#ifndef PRIMAP_BIT
165#define PRIMAP_BIT(pri) ((uint16) ((uint16) 1U << (pri)))
166#endif /* PRIMAP_BIT */
167
168#ifndef OMIT_BITMAP_SEARCH
169
170LOCAL_INLINE uint16
171bitmap_search(uint16 bitmap)
172{
173 /*
174 * ビットマップサーチ関数用テーブル
175 */
176 const uint8 bitmap_search_table[BITMAP_NUM] = {
177 0U, 1U, 0U, 2U, 0U, 1U, 0U,
178 3U, 0U, 1U, 0U, 2U, 0U, 1U, 0U
179 };
180
181 uint16 n = 0U;
182
183 ASSERT(bitmap != 0U);
184 if ((bitmap & 0x00ffU) == 0U) {
185 bitmap >>= 8U;
186 n += 8U;
187 }
188 if ((bitmap & 0x0fU) == 0U) {
189 bitmap >>= 4U;
190 n += 4U;
191 }
192 return(n + bitmap_search_table[(bitmap & 0x000fU) - 1U]);
193}
194
195#endif /* OMIT_BITMAP_SEARCH */
196
197/*
198 * 優先度ビットマップが空かのチェック
199 */
200LOCAL_INLINE boolean
201primap_empty(void)
202{
203 return(ready_primap == 0U);
204}
205
206/*
207 * 優先度ビットマップのサーチ
208 */
209LOCAL_INLINE PriorityType
210primap_search(void)
211{
212 return((PriorityType) bitmap_search(ready_primap));
213}
214
215/*
216 * 優先度ビットマップのセット
217 */
218LOCAL_INLINE void
219primap_set(PriorityType pri)
220{
221 ready_primap |= PRIMAP_BIT(pri);
222}
223
224/*
225 * 優先度ビットマップのクリア
226 */
227LOCAL_INLINE void
228primap_clear(PriorityType pri)
229{
230 ready_primap &= (uint16) ~PRIMAP_BIT(pri);
231}
232
233/*
234 * 最高優先順位タスクのサーチ
235 */
236#ifdef TOPPERS_search_schedtsk
237
238void
239search_schedtsk(void)
240{
241 if (primap_empty() != FALSE) {
242 p_schedtsk = NULL;
243 }
244 else {
245 p_schedtsk = (TCB *) (queue_delete_next(&(ready_queue[nextpri])));
246 if (queue_empty(&(ready_queue[nextpri])) != FALSE) {
247 primap_clear(nextpri);
248 nextpri = (primap_empty() != FALSE) ?
249 TPRI_MINTASK : primap_search();
250 }
251 }
252}
253
254#endif /* TOPPERS_search_schedtsk */
255
256/*
257 * 実行できる状態への移行
258 */
259#ifdef TOPPERS_make_runnable
260
261boolean
262make_runnable(TCB *p_tcb)
263{
264 PriorityType pri, schedpri;
265 boolean is_next_schedtsk = TRUE;
266
267 p_tcb->tstat = READY;
268 LOG_TSKSTAT(p_tcb);
269 if (p_schedtsk != NULL) {
270 pri = p_tcb->curpri;
271 schedpri = p_schedtsk->curpri;
272 if (pri >= schedpri) {
273 /*
274 * schedtsk の方が優先度が高い場合,p_tcb をレ
275 * ディキューの最後に入れる
276 */
277 queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue));
278 primap_set(pri);
279 if (pri < nextpri) {
280 nextpri = pri;
281 }
282 is_next_schedtsk = FALSE;
283 }
284 else {
285 /*
286 * p_tcb の方が優先度が高い場合,schedtsk をレディキュー
287 * の先頭に入れ,p_tcb を新しい schedtsk とする
288 */
289 queue_insert_next(&(ready_queue[schedpri]), &(p_schedtsk->task_queue));
290 primap_set(schedpri);
291 nextpri = schedpri;
292 }
293 }
294
295 if (is_next_schedtsk != FALSE) {
296 p_schedtsk = p_tcb;
297 }
298 return(is_next_schedtsk);
299}
300
301#endif /* TOPPERS_make_runnable */
302
303/*
304 * 実行できる状態から他の状態への遷移
305 *
306 * SC1-MCでmake_non_runnableが実装されるため
307 * SC1にもmake_non_runableを実装し,SC1もSC1-MCの関数構成に合せる
308 * (SC1-MCでは,p_runtskとp_schedtskが一致していることを確認する処理を入れる必要があるが,
309 * SC1では,search_schedtskのみ呼び出す処理とする)
310 */
311#ifdef TOPPERS_make_non_runnable
312
313void
314make_non_runnable(void)
315{
316 search_schedtsk();
317}
318
319#endif /* TOPPERS_make_non_runnable */
320
321/*
322 * タスクの起動
323 *
324 * TerminateTask や ChainTask の中で,自タスクに対して make_active を
325 * 呼ぶ場合があるので注意する
326 */
327#ifdef TOPPERS_make_active
328
329boolean
330make_active(TCB *p_tcb)
331{
332 p_tcb->curpri = p_tcb->p_tinib->inipri;
333 if (TSKID(p_tcb) < tnum_exttask) {
334 p_tcb->curevt = EVTMASK_NONE;
335 p_tcb->waievt = EVTMASK_NONE;
336 }
337 p_tcb->p_lastrescb = NULL;
338 p_tcb->p_lastcntcb = NULL;
339
340 activate_context(p_tcb);
341 return(make_runnable(p_tcb) != FALSE);
342}
343
344#endif /* TOPPERS_make_active */
345
346/*
347 * タスクのプリエンプト
348 */
349#ifdef TOPPERS_preempt
350
351void
352preempt(void)
353{
354 PriorityType pri;
355
356 ASSERT(p_runtsk == p_schedtsk);
357 pri = p_runtsk->curpri;
358 queue_insert_next(&(ready_queue[pri]), &(p_runtsk->task_queue));
359 primap_set(pri);
360 search_schedtsk();
361}
362
363#endif /* TOPPERS_preempt */
364
365/*
366 * 実行中のタスクをSUSPENDED状態にする
367 * リソース解放した状態で呼出す必要がある
368 */
369#ifdef TOPPERS_suspend
370
371void
372suspend(void)
373{
374 p_runtsk->tstat = SUSPENDED;
375 LOG_TSKSTAT(p_runtsk);
376 make_non_runnable();
377 if (p_runtsk->actcnt > 0U) {
378 p_runtsk->actcnt -= 1U;
379 (void) make_active(p_runtsk);
380 }
381}
382
383#endif /* TOPPERS_suspend */
384
385/*
386 * タスクの全リソース返却
387 */
388#ifdef TOPPERS_release_taskresources
389
390void
391release_taskresources(TCB *p_tcb)
392{
393 if (p_tcb->p_lastrescb != NULL) {
394 if (p_tcb->curpri <= TPRI_MINISR) {
395 /* リソースを全部解放すれば割込み許可になる */
396 x_set_ipm((PriorityType) TIPM_ENAALL);
397 }
398 /* リソースを全部解放すれば実行中優先度に戻る */
399 p_tcb->curpri = p_tcb->p_tinib->exepri;
400
401 /* OS割込み禁止状態以上で来る p_tcb->p_lastrescb != NULL */
402 do {
403 p_tcb->p_lastrescb->lockflg = FALSE;
404 p_tcb->p_lastrescb = p_tcb->p_lastrescb->p_prevrescb;
405 } while (p_tcb->p_lastrescb != NULL);
406 }
407}
408
409#endif /* TOPPERS_release_taskresources */
410
411/*
412 * タスクのカウンタの状態をすべてCS_NULLに戻す
413 */
414#ifdef TOPPERS_cancel_taskcounters
415
416void
417cancel_taskcounters(TCB *p_tcb)
418{
419 if (p_tcb->p_lastcntcb != NULL) {
420
421 /* OS割込み禁止状態以上で来る */
422 do {
423 p_tcb->p_lastcntcb->cstat = CS_NULL;
424 p_tcb->p_lastcntcb = p_tcb->p_lastcntcb->p_prevcntcb;
425 } while (p_tcb->p_lastcntcb != NULL);
426 }
427}
428#endif /* TOPPERS_cancel_taskcounters */
429
430/*
431 * タスクの不正終了時の保護
432 * TerminateTask(),ChainTask()なしでの自タスクの終了
433 * (タスクの関数からリターン)した場合の処理
434 */
435#ifdef TOPPERS_exit_task
436
437void
438exit_task(void)
439{
440 x_nested_lock_os_int();
441
442 /* 割込み禁止状態の場合は割込み禁止を解除する */
443 release_interrupts(OSServiceId_Invalid);
444
445 /* リソース確保したままの場合はリソースを解放する */
446 release_taskresources(p_runtsk);
447
448#ifdef CFG_USE_ERRORHOOK
449 /* エラーフックを呼ぶ */
450 call_errorhook(E_OS_MISSINGEND, OSServiceId_TaskMissingEnd);
451#endif /* CFG_USE_ERRORHOOK */
452
453 suspend();
454
455 /* ポストタスクフックが有効な場合はポストタスクフックが呼ばれる */
456 exit_and_dispatch();
457}
458
459#endif /* TOPPERS_exit_task */
460
461#ifdef TOPPERS_remove_task_from_queue
462
463/*
464 * レディキューからタスクを削除する
465 */
466void
467remove_task_from_queue(TCB *p_tcb, PriorityType remove_task_pri)
468{
469 queue_delete(&(p_tcb->task_queue));
470 if (queue_empty(&(ready_queue[remove_task_pri])) != FALSE) {
471 primap_clear(remove_task_pri);
472 nextpri = (primap_empty() != FALSE) ? TPRI_MINTASK : primap_search();
473 }
474}
475
476#endif /* TOPPERS_remove_task_from_queue */
477
478#ifdef TOPPERS_suspend_ready_task
479
480/*
481 * レディキューに入っているタスクを休止状態にする
482 */
483void
484suspend_ready_task(TCB *p_tcb, PriorityType remove_task_pri)
485{
486 p_tcb->tstat = SUSPENDED;
487 LOG_TSKSTAT(p_tcb);
488 remove_task_from_queue(p_tcb, remove_task_pri);
489 if (p_tcb->actcnt > 0U) {
490 p_tcb->actcnt -= 1U;
491 (void) make_active(p_tcb);
492 }
493}
494
495#endif /* TOPPERS_suspend_ready_task */
496
497/*
498 * 自タスクの強制終了
499 * ProtectionHook, TeminateApplication からのみ呼出される
500 * リソースの解放,割込み禁止の解除を行った後
501 * TerminateTask相当の処理を行う
502 * 強制タスク終了の場合は,PostTaskHookを呼出さないのでTerminateTask
503 * とは異なる処理となる
504 * 本関数はOS割込み禁止状態で呼出されることを前提とする
505 */
506#ifdef TOPPERS_force_terminate_task
507
508void
509force_terminate_task(TCB *p_tcb, StatusType terminate_cause, boolean term_osap_flag)
510{
511 /* curpriとinipriが異なる値でレディキューに繋がれている場合への対応 */
512 PriorityType remove_task_pri = p_tcb->curpri;
513
514 /*
515 * 割込み禁止を解除する
516 * エラーフックは呼ばない
517 * エラーフックを呼ばないため,引数にOSServiceId_Invalidをする
518 */
519 release_interrupts(OSServiceId_Invalid);
520
521 /* リソース確保したままの場合,リソース解放 */
522 release_taskresources(p_tcb);
523 /* カウンタの状態を初期化する */
524 cancel_taskcounters(p_tcb);
525
526 if ((terminate_cause & PEOB_STACKMONITORING_TERMTASK) == 0U) {
527 if ((p_tcb == p_runtsk) && (p_runtsk == p_schedtsk)) {
528
529 /* 実行中タスクのCPU例外, 割込み発生時のスタックモニタリング, 信頼関数終了後のスタックモニタリング */
530 suspend();
531 }
532 else {
533 if (p_tcb == p_schedtsk) {
534 /*
535 * 既にレディキューから外されているタスクの終了処理
536 * p_schedtsk/p_tcbの状態を変更し,次に実行すべきタスクを探す
537 */
538 p_tcb->tstat = SUSPENDED;
539 search_schedtsk();
540 }
541 else {
542 /*
543 * curpriとinipriが異なる値でレディキューに繋がれている場合への
544 * 対応で,リソース解放前の優先度を使用し,対象タスクをSUSPEND状態とし,
545 * レディキューから削除する.
546 */
547 suspend_ready_task(p_tcb, remove_task_pri);
548 }
549 }
550 }
551
552 if (term_osap_flag != FALSE) {
553 /*
554 * OSAP終了/再起動処理からの呼び出し
555 * 実施すべき処理がない
556 */
557 }
558 else if (((terminate_cause & (~PROTECTION_ERROR_OPTIONAL_BIT)) == E_OS_STACKFAULT) &&
559 ((terminate_cause & (PROTECTION_ERROR_OPTIONAL_BIT)) != 0U)) {
560 /*
561 * ディスパッチャ,割込み入口処理でのスタックモニタリング
562 * 信頼関数終了後のスタックモニタリングはelse側
563 * 実行中のタスクはディスパッチャが起動するまでなし
564 */
565 p_runtsk = NULL;
566 }
567 else {
568 /* 全割込み禁止状態で,タスク強制終了しても,DisableAllInterrupts全割込み禁止状態を解除しない */
569 callevel_stat = (callevel_stat & TSYS_DISALLINT) | TCL_TASK;
570 x_clear_nested_os_int();
571
572 exit_and_dispatch_nohook();
573 }
574}
575
576#endif /* TOPPERS_force_terminate_task */
577
578/*
579 * OSAP所属するタスクの強制終了
580 */
581#ifdef TOPPERS_force_term_osap_task
582
583void
584force_term_osap_task(OSAPCB *p_osapcb)
585{
586 /* OSAPに所属するタスクを強制終了 */
587 TaskType i;
588 TCB *p_tcb;
589
590 for (i = 0U; i < tnum_task; i++) {
591 if (tinib_table[i].p_osapcb == p_osapcb) {
592 p_tcb = &tcb_table[i];
593 /*
594 * OSAP終了/再起動よりタスクの強制終了
595 */
596 p_tcb->actcnt = 0U;
597 p_tcb->curevt = 0U;
598#ifdef CFG_USE_PROTECTIONHOOK
599 p_tcb->calltfn = FALSE;
600#endif /* CFG_USE_PROTECTIONHOOK */
601
602 if (p_tcb->tstat == READY) {
603 force_terminate_task(p_tcb, 0U, TRUE);
604 }
605 else {
606 p_tcb->tstat = SUSPENDED;
607 }
608
609 /*
610 * ここでは割込み禁止を解除しない
611 * ここにくるまでの間に,p_runtskが終了され,p_schedtskが
612 * 更新されていた場合,現在のATK2の設計では,割込みハンドラ
613 * の出口処理で,p_runtsk != p_schedtskによるディスパッチ
614 * 判定を行っているため,OSAPの強制処理中に,他の
615 * タスクにディスパッチしてしまう
616 * C2ISRのレスポンス性能を向上するため,割込みの解除/禁止を,
617 * タスクを強制終了する毎に実施する設計も考えられるが,
618 * ATK2の現在のディスパッチ設計を変更する必要がある
619 */
620 }
621 }
622}
623
624#endif /* TOPPERS_force_term_osap_task */
Note: See TracBrowser for help on using the repository browser.