OSDN Git Service

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