OSDN Git Service

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