source: azure_iot_hub_f767zi/trunk/asp_baseplatform/kernel/task_manage.c@ 457

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

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 13.3 KB
Line 
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-2017 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$
41 */
42
43/*
44 * タスク管理機能
45 */
46
47#include "kernel_impl.h"
48#include "check.h"
49#include "task.h"
50#include "wait.h"
51#include "mutex.h"
52
53/*
54 * トレースログマクロのデフォルト定義
55 */
56#ifndef LOG_ACRE_TSK_ENTER
57#define LOG_ACRE_TSK_ENTER(pk_ctsk)
58#endif /* LOG_ACRE_TSK_ENTER */
59
60#ifndef LOG_ACRE_TSK_LEAVE
61#define LOG_ACRE_TSK_LEAVE(ercd)
62#endif /* LOG_ACRE_TSK_LEAVE */
63
64#ifndef LOG_DEL_TSK_ENTER
65#define LOG_DEL_TSK_ENTER(tskid)
66#endif /* LOG_DEL_TSK_ENTER */
67
68#ifndef LOG_DEL_TSK_LEAVE
69#define LOG_DEL_TSK_LEAVE(ercd)
70#endif /* LOG_DEL_TSK_LEAVE */
71
72#ifndef LOG_ACT_TSK_ENTER
73#define LOG_ACT_TSK_ENTER(tskid)
74#endif /* LOG_ACT_TSK_ENTER */
75
76#ifndef LOG_ACT_TSK_LEAVE
77#define LOG_ACT_TSK_LEAVE(ercd)
78#endif /* LOG_ACT_TSK_LEAVE */
79
80#ifndef LOG_IACT_TSK_ENTER
81#define LOG_IACT_TSK_ENTER(tskid)
82#endif /* LOG_IACT_TSK_ENTER */
83
84#ifndef LOG_IACT_TSK_LEAVE
85#define LOG_IACT_TSK_LEAVE(ercd)
86#endif /* LOG_IACT_TSK_LEAVE */
87
88#ifndef LOG_CAN_ACT_ENTER
89#define LOG_CAN_ACT_ENTER(tskid)
90#endif /* LOG_CAN_ACT_ENTER */
91
92#ifndef LOG_CAN_ACT_LEAVE
93#define LOG_CAN_ACT_LEAVE(ercd)
94#endif /* LOG_CAN_ACT_LEAVE */
95
96#ifndef LOG_EXT_TSK_ENTER
97#define LOG_EXT_TSK_ENTER()
98#endif /* LOG_EXT_TSK_ENTER */
99
100#ifndef LOG_EXT_TSK_LEAVE
101#define LOG_EXT_TSK_LEAVE(ercd)
102#endif /* LOG_EXT_TSK_LEAVE */
103
104#ifndef LOG_TER_TSK_ENTER
105#define LOG_TER_TSK_ENTER(tskid)
106#endif /* LOG_TER_TSK_ENTER */
107
108#ifndef LOG_TER_TSK_LEAVE
109#define LOG_TER_TSK_LEAVE(ercd)
110#endif /* LOG_TER_TSK_LEAVE */
111
112#ifndef LOG_CHG_PRI_ENTER
113#define LOG_CHG_PRI_ENTER(tskid, tskpri)
114#endif /* LOG_CHG_PRI_ENTER */
115
116#ifndef LOG_CHG_PRI_LEAVE
117#define LOG_CHG_PRI_LEAVE(ercd)
118#endif /* LOG_CHG_PRI_LEAVE */
119
120#ifndef LOG_GET_PRI_ENTER
121#define LOG_GET_PRI_ENTER(tskid, p_tskpri)
122#endif /* LOG_GET_PRI_ENTER */
123
124#ifndef LOG_GET_PRI_LEAVE
125#define LOG_GET_PRI_LEAVE(ercd, tskpri)
126#endif /* LOG_GET_PRI_LEAVE */
127
128#ifndef LOG_GET_INF_ENTER
129#define LOG_GET_INF_ENTER(p_exinf)
130#endif /* LOG_GET_INF_ENTER */
131
132#ifndef LOG_GET_INF_LEAVE
133#define LOG_GET_INF_LEAVE(ercd, exinf)
134#endif /* LOG_GET_INF_LEAVE */
135
136/*
137 * タスクの生成
138 */
139#ifdef TOPPERS_acre_tsk
140
141#ifndef TARGET_MIN_STKSZ
142#define TARGET_MIN_STKSZ 1U /* 未定義の場合は0でないことをチェック */
143#endif /* TARGET_MIN_STKSZ */
144
145ER_UINT
146acre_tsk(const T_CTSK *pk_ctsk)
147{
148 TCB *p_tcb;
149 TINIB *p_tinib;
150 ATR tskatr;
151 SIZE stksz;
152 void *stk;
153 ER ercd;
154
155 LOG_ACRE_TSK_ENTER(pk_ctsk);
156 CHECK_TSKCTX_UNL();
157 CHECK_RSATR(pk_ctsk->tskatr, TA_ACT|TARGET_TSKATR);
158 CHECK_ALIGN_FUNC(pk_ctsk->task);
159 CHECK_NONNULL_FUNC(pk_ctsk->task);
160 CHECK_TPRI(pk_ctsk->itskpri);
161 CHECK_PAR(pk_ctsk->stksz >= TARGET_MIN_STKSZ);
162 if (pk_ctsk->stk != NULL) {
163 CHECK_ALIGN_STKSZ(pk_ctsk->stksz);
164 CHECK_ALIGN_STACK(pk_ctsk->stk);
165 }
166 tskatr = pk_ctsk->tskatr;
167 stksz = pk_ctsk->stksz;
168 stk = pk_ctsk->stk;
169
170 t_lock_cpu();
171 if (queue_empty(&free_tcb)) {
172 ercd = E_NOID;
173 }
174 else {
175 if (stk == NULL) {
176 stksz = ROUND_STK_T(stksz);
177 stk = kernel_malloc(stksz);
178 tskatr |= TA_MEMALLOC;
179 }
180 if (stk == NULL) {
181 ercd = E_NOMEM;
182 }
183 else {
184 p_tcb = ((TCB *) queue_delete_next(&free_tcb));
185 p_tinib = (TINIB *)(p_tcb->p_tinib);
186 p_tinib->tskatr = tskatr;
187 p_tinib->exinf = pk_ctsk->exinf;
188 p_tinib->task = pk_ctsk->task;
189 p_tinib->ipriority = INT_PRIORITY(pk_ctsk->itskpri);
190#ifdef USE_TSKINICTXB
191 init_tskinictxb(&(p_tinib->tskinictxb), stk, pk_ctsk);
192#else /* USE_TSKINICTXB */
193 p_tinib->stksz = stksz;
194 p_tinib->stk = stk;
195#endif /* USE_TSKINICTXB */
196 p_tinib->texatr = TA_NULL;
197 p_tinib->texrtn = NULL;
198
199 p_tcb->actque = false;
200 make_dormant(p_tcb);
201 if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) {
202 if (make_active(p_tcb)) {
203 dispatch();
204 }
205 }
206 ercd = TSKID(p_tcb);
207 }
208 }
209 t_unlock_cpu();
210
211 error_exit:
212 LOG_ACRE_TSK_LEAVE(ercd);
213 return(ercd);
214}
215
216#endif /* TOPPERS_acre_tsk */
217
218/*
219 * タスクの削除
220 */
221#ifdef TOPPERS_del_tsk
222
223ER
224del_tsk(ID tskid)
225{
226 TCB *p_tcb;
227 TINIB *p_tinib;
228 ER ercd;
229
230 LOG_DEL_TSK_ENTER(tskid);
231 CHECK_TSKCTX_UNL();
232 CHECK_TSKID(tskid);
233 p_tcb = get_tcb(tskid);
234
235 t_lock_cpu();
236 if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
237 ercd = E_NOEXS;
238 }
239 else if (TSKID(p_tcb) > tmax_stskid && TSTAT_DORMANT(p_tcb->tstat)) {
240 p_tinib = (TINIB *)(p_tcb->p_tinib);
241#ifdef USE_TSKINICTXB
242 term_tskinictxb(&(p_tinib->tskinictxb));
243#else /* USE_TSKINICTXB */
244 if ((p_tinib->tskatr & TA_MEMALLOC) != 0U) {
245 kernel_free(p_tinib->stk);
246 }
247#endif /* USE_TSKINICTXB */
248 p_tinib->tskatr = TA_NOEXS;
249 queue_insert_prev(&free_tcb, &(p_tcb->task_queue));
250 ercd = E_OK;
251 }
252 else {
253 ercd = E_OBJ;
254 }
255 t_unlock_cpu();
256
257 error_exit:
258 LOG_DEL_TSK_LEAVE(ercd);
259 return(ercd);
260}
261
262#endif /* TOPPERS_del_tsk */
263
264/*
265 * タスクの起動
266 */
267#ifdef TOPPERS_act_tsk
268
269ER
270act_tsk(ID tskid)
271{
272 TCB *p_tcb;
273 ER ercd;
274
275 LOG_ACT_TSK_ENTER(tskid);
276 CHECK_TSKCTX_UNL();
277 CHECK_TSKID_SELF(tskid);
278 p_tcb = get_tcb_self(tskid);
279
280 t_lock_cpu();
281 if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
282 ercd = E_NOEXS;
283 }
284 else if (TSTAT_DORMANT(p_tcb->tstat)) {
285 if (make_active(p_tcb)) {
286 dispatch();
287 }
288 ercd = E_OK;
289 }
290 else if (!(p_tcb->actque)) {
291 p_tcb->actque = true;
292 ercd = E_OK;
293 }
294 else {
295 ercd = E_QOVR;
296 }
297 t_unlock_cpu();
298
299 error_exit:
300 LOG_ACT_TSK_LEAVE(ercd);
301 return(ercd);
302}
303
304#endif /* TOPPERS_act_tsk */
305
306/*
307 * タスクの起動(非タスクコンテキスト用)
308 */
309#ifdef TOPPERS_iact_tsk
310
311ER
312iact_tsk(ID tskid)
313{
314 TCB *p_tcb;
315 ER ercd;
316
317 LOG_IACT_TSK_ENTER(tskid);
318 CHECK_INTCTX_UNL();
319 CHECK_TSKID(tskid);
320 p_tcb = get_tcb(tskid);
321
322 i_lock_cpu();
323 if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
324 ercd = E_NOEXS;
325 }
326 else if (TSTAT_DORMANT(p_tcb->tstat)) {
327 if (make_active(p_tcb)) {
328 reqflg = true;
329 }
330 ercd = E_OK;
331 }
332 else if (!(p_tcb->actque)) {
333 p_tcb->actque = true;
334 ercd = E_OK;
335 }
336 else {
337 ercd = E_QOVR;
338 }
339 i_unlock_cpu();
340
341 error_exit:
342 LOG_IACT_TSK_LEAVE(ercd);
343 return(ercd);
344}
345
346#endif /* TOPPERS_iact_tsk */
347
348/*
349 * タスク起動要求のキャンセル
350 */
351#ifdef TOPPERS_can_act
352
353ER_UINT
354can_act(ID tskid)
355{
356 TCB *p_tcb;
357 ER_UINT ercd;
358
359 LOG_CAN_ACT_ENTER(tskid);
360 CHECK_TSKCTX_UNL();
361 CHECK_TSKID_SELF(tskid);
362 p_tcb = get_tcb_self(tskid);
363
364 t_lock_cpu();
365 if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
366 ercd = E_NOEXS;
367 }
368 else {
369 ercd = p_tcb->actque ? 1 : 0;
370 p_tcb->actque = false;
371 }
372 t_unlock_cpu();
373
374 error_exit:
375 LOG_CAN_ACT_LEAVE(ercd);
376 return(ercd);
377}
378
379#endif /* TOPPERS_can_act */
380
381/*
382 * 自タスクの終了
383 */
384#ifdef TOPPERS_ext_tsk
385
386ER
387ext_tsk(void)
388{
389 ER ercd;
390
391 LOG_EXT_TSK_ENTER();
392 CHECK_TSKCTX();
393
394 if (t_sense_lock()) {
395 /*
396 * CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し
397 * てからタスクを終了する.実装上は,サービスコール内でのCPU
398 * ロックを省略すればよいだけ.
399 */
400 }
401 else {
402 t_lock_cpu();
403 }
404 if (disdsp) {
405 /*
406 * ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ
407 * チ許可状態にしてからタスクを終了する.
408 */
409 disdsp = false;
410 }
411 if (!ipmflg) {
412 /*
413 * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tsk
414 * が呼ばれた場合は,IPMをTIPM_ENAALLにしてからタスクを終了す
415 * る.
416 */
417 t_set_ipm(TIPM_ENAALL);
418 ipmflg = true;
419 }
420 dspflg = true;
421
422 (void) make_non_runnable(p_runtsk);
423 if (!queue_empty(&(p_runtsk->mutex_queue))) {
424 (void) (*mtxhook_release_all)(p_runtsk);
425 }
426 make_dormant(p_runtsk);
427 if (p_runtsk->actque) {
428 p_runtsk->actque = false;
429 (void) make_active(p_runtsk);
430 }
431 exit_and_dispatch();
432 ercd = E_SYS;
433
434 error_exit:
435 LOG_EXT_TSK_LEAVE(ercd);
436 return(ercd);
437}
438
439#endif /* TOPPERS_ext_tsk */
440
441/*
442 * タスクの強制終了
443 */
444#ifdef TOPPERS_ter_tsk
445
446ER
447ter_tsk(ID tskid)
448{
449 TCB *p_tcb;
450 bool_t dspreq = false;
451 ER ercd;
452
453 LOG_TER_TSK_ENTER(tskid);
454 CHECK_TSKCTX_UNL();
455 CHECK_TSKID(tskid);
456 p_tcb = get_tcb(tskid);
457 CHECK_NONSELF(p_tcb);
458
459 t_lock_cpu();
460 if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
461 ercd = E_NOEXS;
462 }
463 else if (TSTAT_DORMANT(p_tcb->tstat)) {
464 ercd = E_OBJ;
465 }
466 else {
467 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
468 /*
469 * p_tcbは自タスクでないため,(シングルプロセッサでは)実
470 * 行状態でなく,make_non_runnable(p_tcb)でタスクディスパッ
471 * チが必要になることはない.
472 */
473 (void) make_non_runnable(p_tcb);
474 }
475 else if (TSTAT_WAITING(p_tcb->tstat)) {
476 wait_dequeue_wobj(p_tcb);
477 wait_dequeue_tmevtb(p_tcb);
478 }
479 if (!queue_empty(&(p_tcb->mutex_queue))) {
480 if ((*mtxhook_release_all)(p_tcb)) {
481 dspreq = true;
482 }
483 }
484 make_dormant(p_tcb);
485 if (p_tcb->actque) {
486 p_tcb->actque = false;
487 if (make_active(p_tcb)) {
488 dspreq = true;
489 }
490 }
491 if (dspreq) {
492 dispatch();
493 }
494 ercd = E_OK;
495 }
496 t_unlock_cpu();
497
498 error_exit:
499 LOG_TER_TSK_LEAVE(ercd);
500 return(ercd);
501}
502
503#endif /* TOPPERS_ter_tsk */
504
505/*
506 * タスクのベース優先度の変更
507 */
508#ifdef TOPPERS_chg_pri
509
510ER
511chg_pri(ID tskid, PRI tskpri)
512{
513 TCB *p_tcb;
514 uint_t newbpri;
515 ER ercd;
516
517 LOG_CHG_PRI_ENTER(tskid, tskpri);
518 CHECK_TSKCTX_UNL();
519 CHECK_TSKID_SELF(tskid);
520 CHECK_TPRI_INI(tskpri);
521 p_tcb = get_tcb_self(tskid);
522
523 t_lock_cpu();
524 if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
525 ercd = E_NOEXS;
526 }
527 else if (TSTAT_DORMANT(p_tcb->tstat)) {
528 ercd = E_OBJ;
529 }
530 else if ((!queue_empty(&(p_tcb->mutex_queue))
531 || TSTAT_WAIT_MTX(p_tcb->tstat))
532 && !((*mtxhook_check_ceilpri)(p_tcb, newbpri))) {
533 ercd = E_ILUSE;
534 }
535 else {
536 newbpri = (tskpri == TPRI_INI) ? p_tcb->p_tinib->ipriority
537 : INT_PRIORITY(tskpri);
538 p_tcb->bpriority = newbpri;
539 if (queue_empty(&(p_tcb->mutex_queue))
540 || !((*mtxhook_scan_ceilmtx)(p_tcb))) {
541 if (change_priority(p_tcb, newbpri, false)) {
542 dispatch();
543 }
544 }
545 ercd = E_OK;
546 }
547 t_unlock_cpu();
548
549 error_exit:
550 LOG_CHG_PRI_LEAVE(ercd);
551 return(ercd);
552}
553
554#endif /* TOPPERS_chg_pri */
555
556/*
557 * タスク優先度の参照
558 */
559#ifdef TOPPERS_get_pri
560
561ER
562get_pri(ID tskid, PRI *p_tskpri)
563{
564 TCB *p_tcb;
565 ER ercd;
566
567 LOG_GET_PRI_ENTER(tskid, p_tskpri);
568 CHECK_TSKCTX_UNL();
569 CHECK_TSKID_SELF(tskid);
570 p_tcb = get_tcb_self(tskid);
571
572 t_lock_cpu();
573 if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
574 ercd = E_NOEXS;
575 }
576 else if (TSTAT_DORMANT(p_tcb->tstat)) {
577 ercd = E_OBJ;
578 }
579 else {
580 *p_tskpri = EXT_TSKPRI(p_tcb->priority);
581 ercd = E_OK;
582 }
583 t_unlock_cpu();
584
585 error_exit:
586 LOG_GET_PRI_LEAVE(ercd, *p_tskpri);
587 return(ercd);
588}
589
590#endif /* TOPPERS_get_pri */
591
592/*
593 * 自タスクの拡張情報の参照
594 */
595#ifdef TOPPERS_get_inf
596
597ER
598get_inf(intptr_t *p_exinf)
599{
600 ER ercd;
601
602 LOG_GET_INF_ENTER(p_exinf);
603 CHECK_TSKCTX_UNL();
604
605 t_lock_cpu();
606 *p_exinf = p_runtsk->p_tinib->exinf;
607 ercd = E_OK;
608 t_unlock_cpu();
609
610 error_exit:
611 LOG_GET_INF_LEAVE(ercd, *p_exinf);
612 return(ercd);
613}
614
615#endif /* TOPPERS_get_inf */
Note: See TracBrowser for help on using the repository browser.