OSDN Git Service

マルチプロジェクト型にレポジトリを変更するために移動した
[toppersasp4lpc/asp.git] / asp / 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-2008 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 1595 2009-06-26 01:59:29Z 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_ACT_TSK_ENTER
56 #define LOG_ACT_TSK_ENTER(tskid)
57 #endif /* LOG_ACT_TSK_ENTER */
58
59 #ifndef LOG_ACT_TSK_LEAVE
60 #define LOG_ACT_TSK_LEAVE(ercd)
61 #endif /* LOG_ACT_TSK_LEAVE */
62
63 #ifndef LOG_IACT_TSK_ENTER
64 #define LOG_IACT_TSK_ENTER(tskid)
65 #endif /* LOG_IACT_TSK_ENTER */
66
67 #ifndef LOG_IACT_TSK_LEAVE
68 #define LOG_IACT_TSK_LEAVE(ercd)
69 #endif /* LOG_IACT_TSK_LEAVE */
70
71 #ifndef LOG_CAN_ACT_ENTER
72 #define LOG_CAN_ACT_ENTER(tskid)
73 #endif /* LOG_CAN_ACT_ENTER */
74
75 #ifndef LOG_CAN_ACT_LEAVE
76 #define LOG_CAN_ACT_LEAVE(ercd)
77 #endif /* LOG_CAN_ACT_LEAVE */
78
79 #ifndef LOG_EXT_TSK_ENTER
80 #define LOG_EXT_TSK_ENTER()
81 #endif /* LOG_EXT_TSK_ENTER */
82
83 #ifndef LOG_EXT_TSK_LEAVE
84 #define LOG_EXT_TSK_LEAVE(ercd)
85 #endif /* LOG_EXT_TSK_LEAVE */
86
87 #ifndef LOG_TER_TSK_ENTER
88 #define LOG_TER_TSK_ENTER(tskid)
89 #endif /* LOG_TER_TSK_ENTER */
90
91 #ifndef LOG_TER_TSK_LEAVE
92 #define LOG_TER_TSK_LEAVE(ercd)
93 #endif /* LOG_TER_TSK_LEAVE */
94
95 #ifndef LOG_CHG_PRI_ENTER
96 #define LOG_CHG_PRI_ENTER(tskid, tskpri)
97 #endif /* LOG_CHG_PRI_ENTER */
98
99 #ifndef LOG_CHG_PRI_LEAVE
100 #define LOG_CHG_PRI_LEAVE(ercd)
101 #endif /* LOG_CHG_PRI_LEAVE */
102
103 #ifndef LOG_GET_PRI_ENTER
104 #define LOG_GET_PRI_ENTER(tskid, p_tskpri)
105 #endif /* LOG_GET_PRI_ENTER */
106
107 #ifndef LOG_GET_PRI_LEAVE
108 #define LOG_GET_PRI_LEAVE(ercd, tskpri)
109 #endif /* LOG_GET_PRI_LEAVE */
110
111 #ifndef LOG_GET_INF_ENTER
112 #define LOG_GET_INF_ENTER(p_exinf)
113 #endif /* LOG_GET_INF_ENTER */
114
115 #ifndef LOG_GET_INF_LEAVE
116 #define LOG_GET_INF_LEAVE(ercd, exinf)
117 #endif /* LOG_GET_INF_LEAVE */
118
119 /*
120  *  タスクの起動
121  */
122 #ifdef TOPPERS_act_tsk
123
124 ER
125 act_tsk(ID tskid)
126 {
127         TCB             *p_tcb;
128         ER              ercd;
129
130         LOG_ACT_TSK_ENTER(tskid);
131         CHECK_TSKCTX_UNL();
132         CHECK_TSKID_SELF(tskid);
133         p_tcb = get_tcb_self(tskid);
134
135         t_lock_cpu();
136         if (TSTAT_DORMANT(p_tcb->tstat)) {
137                 if (make_active(p_tcb)) {
138                         dispatch();
139                 }
140                 ercd = E_OK;
141         }
142         else if (!(p_tcb->actque)) {
143                 p_tcb->actque = true;
144                 ercd = E_OK;
145         }
146         else {
147                 ercd = E_QOVR;
148         }
149         t_unlock_cpu();
150
151   error_exit:
152         LOG_ACT_TSK_LEAVE(ercd);
153         return(ercd);
154 }
155
156 #endif /* TOPPERS_act_tsk */
157
158 /*
159  *  タスクの起動(非タスクコンテキスト用)
160  */
161 #ifdef TOPPERS_iact_tsk
162
163 ER
164 iact_tsk(ID tskid)
165 {
166         TCB             *p_tcb;
167         ER              ercd;
168
169         LOG_IACT_TSK_ENTER(tskid);
170         CHECK_INTCTX_UNL();
171         CHECK_TSKID(tskid);
172         p_tcb = get_tcb(tskid);
173
174         i_lock_cpu();
175         if (TSTAT_DORMANT(p_tcb->tstat)) {
176                 if (make_active(p_tcb)) {
177                         reqflg = true;
178                 }
179                 ercd = E_OK;
180         }
181         else if (!(p_tcb->actque)) {
182                 p_tcb->actque = true;
183                 ercd = E_OK;
184         }
185         else {
186                 ercd = E_QOVR;
187         }
188         i_unlock_cpu();
189
190   error_exit:
191         LOG_IACT_TSK_LEAVE(ercd);
192         return(ercd);
193 }
194
195 #endif /* TOPPERS_iact_tsk */
196
197 /*
198  *  タスク起動要求のキャンセル
199  */
200 #ifdef TOPPERS_can_act
201
202 ER_UINT
203 can_act(ID tskid)
204 {
205         TCB             *p_tcb;
206         ER_UINT ercd;
207
208         LOG_CAN_ACT_ENTER(tskid);
209         CHECK_TSKCTX_UNL();
210         CHECK_TSKID_SELF(tskid);
211         p_tcb = get_tcb_self(tskid);
212
213         t_lock_cpu();
214         ercd = p_tcb->actque ? 1 : 0;
215         p_tcb->actque = false;
216         t_unlock_cpu();
217
218   error_exit:
219         LOG_CAN_ACT_LEAVE(ercd);
220         return(ercd);
221 }
222
223 #endif /* TOPPERS_can_act */
224
225 /*
226  *  自タスクの終了
227  */
228 #ifdef TOPPERS_ext_tsk
229
230 ER
231 ext_tsk(void)
232 {
233         ER              ercd;
234
235         LOG_EXT_TSK_ENTER();
236         CHECK_TSKCTX();
237
238         if (t_sense_lock()) {
239                 /*
240                  *  CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し
241                  *  てからタスクを終了する.実装上は,サービスコール内でのCPU
242                  *  ロックを省略すればよいだけ.
243                  */
244         }
245         else {
246                 t_lock_cpu();
247         }
248         if (disdsp) {
249                 /*
250                  *  ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ
251                  *  チ許可状態にしてからタスクを終了する.
252                  */
253                 disdsp = false;
254         }
255         if (t_get_ipm() != TIPM_ENAALL) {
256                 /*
257                  *  割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tsk
258                  *  が呼ばれた場合は,IPMをTIPM_ENAALLにしてからタスクを終了す
259                  *  る.
260                  */
261                 t_set_ipm(TIPM_ENAALL);
262         }
263         dspflg = true;
264
265         (void) make_non_runnable(p_runtsk);
266         make_dormant(p_runtsk);
267         if (p_runtsk->actque) {
268                 p_runtsk->actque = false;
269                 (void) make_active(p_runtsk);
270         }
271         exit_and_dispatch();
272         return(E_SYS);
273
274   error_exit:
275         LOG_EXT_TSK_LEAVE(ercd);
276         return(ercd);
277 }
278
279 #endif /* TOPPERS_ext_tsk */
280
281 /*
282  *  タスクの強制終了
283  */
284 #ifdef TOPPERS_ter_tsk
285
286 ER
287 ter_tsk(ID tskid)
288 {
289         TCB             *p_tcb;
290         ER              ercd;
291
292         LOG_TER_TSK_ENTER(tskid);
293         CHECK_TSKCTX_UNL();
294         CHECK_TSKID(tskid);
295         p_tcb = get_tcb(tskid);
296         CHECK_NONSELF(p_tcb);
297
298         t_lock_cpu();
299         if (TSTAT_DORMANT(p_tcb->tstat)) {
300                 ercd = E_OBJ;
301         }
302         else {
303                 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
304                         /*
305                          *  p_tcbは自タスクでないため,(シングルプロセッサでは)実
306                          *  行状態でなく,make_non_runnable(p_tcb)でタスクディスパッ
307                          *  チが必要になることはない.
308                          */
309                         (void) make_non_runnable(p_tcb);
310                 }
311                 else if (TSTAT_WAITING(p_tcb->tstat)) {
312                         wait_dequeue_wobj(p_tcb);
313                         wait_dequeue_tmevtb(p_tcb);
314                 }
315                 make_dormant(p_tcb);
316                 if (p_tcb->actque) {
317                         p_tcb->actque = false;
318                         if (make_active(p_tcb)) {
319                                 dispatch();
320                         }
321                 }
322                 ercd = E_OK;
323         }
324         t_unlock_cpu();
325
326   error_exit:
327         LOG_TER_TSK_LEAVE(ercd);
328         return(ercd);
329 }
330
331 #endif /* TOPPERS_ter_tsk */
332
333 /*
334  *  タスク優先度の変更
335  */
336 #ifdef TOPPERS_chg_pri
337
338 ER
339 chg_pri(ID tskid, PRI tskpri)
340 {
341         TCB             *p_tcb;
342         uint_t  newpri;
343         ER              ercd;
344
345         LOG_CHG_PRI_ENTER(tskid, tskpri);
346         CHECK_TSKCTX_UNL();
347         CHECK_TSKID_SELF(tskid);
348         CHECK_TPRI_INI(tskpri);
349         p_tcb = get_tcb_self(tskid);
350         newpri = (tskpri == TPRI_INI) ? p_tcb->p_tinib->ipriority
351                                                                                 : INT_PRIORITY(tskpri);
352
353         t_lock_cpu();
354         if (TSTAT_DORMANT(p_tcb->tstat)) {
355                 ercd = E_OBJ;
356         }
357         else {
358                 if (change_priority(p_tcb, newpri)) {
359                         dispatch();
360                 }
361                 ercd = E_OK;
362         }
363         t_unlock_cpu();
364
365   error_exit:
366         LOG_CHG_PRI_LEAVE(ercd);
367         return(ercd);
368 }
369
370 #endif /* TOPPERS_chg_pri */
371
372 /*
373  *  タスク優先度の参照
374  */
375 #ifdef TOPPERS_get_pri
376
377 ER
378 get_pri(ID tskid, PRI *p_tskpri)
379 {
380         TCB             *p_tcb;
381         ER              ercd;
382
383         LOG_GET_PRI_ENTER(tskid, p_tskpri);
384         CHECK_TSKCTX_UNL();
385         CHECK_TSKID_SELF(tskid);
386         p_tcb = get_tcb_self(tskid);
387
388         t_lock_cpu();
389         if (TSTAT_DORMANT(p_tcb->tstat)) {
390                 ercd = E_OBJ;
391         }
392         else {
393                 *p_tskpri = EXT_TSKPRI(p_tcb->priority);
394                 ercd = E_OK;
395         }
396         t_unlock_cpu();
397
398   error_exit:
399         LOG_GET_PRI_LEAVE(ercd, *p_tskpri);
400         return(ercd);
401 }
402
403 #endif /* TOPPERS_get_pri */
404
405 /*
406  *  自タスクの拡張情報の参照
407  */
408 #ifdef TOPPERS_get_inf
409
410 ER
411 get_inf(intptr_t *p_exinf)
412 {
413         ER              ercd;
414
415         LOG_GET_INF_ENTER(p_exinf);
416         CHECK_TSKCTX_UNL();
417
418         t_lock_cpu();
419         *p_exinf = p_runtsk->p_tinib->exinf;
420         ercd = E_OK;
421         t_unlock_cpu();
422
423   error_exit:
424         LOG_GET_INF_LEAVE(ercd, *p_exinf);
425         return(ercd);
426 }
427
428 #endif /* TOPPERS_get_inf */