|
|
task_manage.c説明を見る。00001 /* 00002 * TOPPERS/FDMP Kernel 00003 * Toyohashi Open Platform for Embedded Real-Time Systems/ 00004 * Function Distributed Multiprocessor Kernel 00005 * 00006 * Copyright (C) 2000-2004 by Embedded and Real-Time Systems Laboratory 00007 * Toyohashi Univ. of Technology, JAPAN 00008 * Copyright (C) 2005-2006 by Embedded and Real-Time Systems Laboratory 00009 * Graduate School of Information Science, Nagoya Univ., JAPAN 00010 * 00011 * 上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 00012 * によって公表されている GNU General Public License の Version 2 に記 00013 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア 00014 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下, 00015 * 利用と呼ぶ)することを無償で許諾する. 00016 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 00017 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー 00018 * スコード中に含まれていること. 00019 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 00020 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 00021 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 00022 * の無保証規定を掲載すること. 00023 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 00024 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ 00025 * と. 00026 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 00027 * 作権表示,この利用条件および下記の無保証規定を掲載すること. 00028 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに 00029 * 報告すること. 00030 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 00031 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. 00032 * 00033 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お 00034 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も 00035 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直 00036 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない. 00037 * 00038 * @(#) $Id: task_manage.c,v 1.5 2006/03/14 04:37:54 honda Exp $ 00039 */ 00040 00045 #include "fdmp_kernel.h" 00046 #include "check.h" 00047 #include "task.h" 00048 #include "wait.h" 00049 00053 #ifdef __act_tsk 00054 00055 SYSCALL ER 00056 act_tsk(ID tskid) 00057 { 00058 TCB *tcb; 00059 ER ercd; 00060 CCB *ccb; 00061 BOOL dspreq = FALSE; 00062 00063 LOG_ACT_TSK_ENTER(tskid); 00064 CHECK_TSKCTX_UNL(); 00065 ccb = T_CHECK_CLSID_CCB(tskid); 00066 tskid = remove_clsid(tskid); 00067 CHECK_TSKID_SELF(ccb, tskid); 00068 tcb = get_tcb_self(ccb, tskid); 00069 00070 retry: 00071 T_ACQUIRE_LOCK(ccb->tsk_lock); 00072 if (TSTAT_DORMANT(tcb->tstat)) { 00073 if (make_active(ccb, tcb)) { 00074 dspreq = dispatch_request(ccb->prcid); 00075 } 00076 ercd = E_OK; 00077 } 00078 else if (!(tcb->actcnt)) { 00079 tcb->actcnt = TRUE; 00080 ercd = E_OK; 00081 } 00082 else { 00083 ercd = E_QOVR; 00084 } 00085 T_RELEASE_LOCK_AND_DISPATCH(ccb->tsk_lock, dspreq); 00086 00087 exit: 00088 LOG_ACT_TSK_LEAVE(ercd); 00089 return(ercd); 00090 } 00091 00092 #endif /* __act_tsk */ 00093 00097 #ifdef __iact_tsk 00098 00099 SYSCALL ER 00100 iact_tsk(ID tskid) 00101 { 00102 TCB *tcb; 00103 ER ercd; 00104 CCB *ccb; 00105 00106 LOG_IACT_TSK_ENTER(tskid); 00107 CHECK_INTCTX_UNL(); 00108 ccb = I_CHECK_CLSID_CCB(tskid); 00109 tskid = remove_clsid(tskid); 00110 CHECK_TSKID(ccb, tskid); 00111 tcb = get_tcb(ccb, tskid); 00112 00113 retry: 00114 I_ACQUIRE_LOCK(ccb->tsk_lock); 00115 if (TSTAT_DORMANT(tcb->tstat)) { 00116 if (make_active(ccb, tcb)) { 00117 if (dispatch_request(ccb->prcid)) { 00118 reqflg = TRUE; 00119 } 00120 } 00121 ercd = E_OK; 00122 } 00123 else if (!(tcb->actcnt)) { 00124 tcb->actcnt = TRUE; 00125 ercd = E_OK; 00126 } 00127 else { 00128 ercd = E_QOVR; 00129 } 00130 I_RELEASE_LOCK(ccb->tsk_lock); 00131 00132 exit: 00133 LOG_IACT_TSK_LEAVE(ercd); 00134 return(ercd); 00135 } 00136 00137 #endif /* __iact_tsk */ 00138 00142 #ifdef __can_act 00143 00144 SYSCALL ER_UINT 00145 can_act(ID tskid) 00146 { 00147 TCB *tcb; 00148 ER_UINT ercd; 00149 CCB *ccb; 00150 00151 LOG_CAN_ACT_ENTER(tskid); 00152 CHECK_TSKCTX_UNL(); 00153 ccb = T_CHECK_CLSID_CCB(tskid); 00154 tskid = remove_clsid(tskid); 00155 CHECK_TSKID_SELF(ccb, tskid); 00156 tcb = get_tcb_self(ccb, tskid); 00157 00158 retry: 00159 T_ACQUIRE_LOCK(ccb->tsk_lock); 00160 if (tcb == runtsk && tcb->terflg) { 00161 ercd = E_OBJ; 00162 } 00163 else { 00164 ercd = tcb->actcnt ? 1 : 0; 00165 tcb->actcnt = FALSE; 00166 } 00167 T_RELEASE_LOCK(ccb->tsk_lock); 00168 00169 exit: 00170 LOG_CAN_ACT_LEAVE(ercd); 00171 return(ercd); 00172 } 00173 00174 #endif /* __can_act */ 00175 00180 #ifdef __ext_tsk 00181 00182 SYSCALL void 00183 ext_tsk(void) 00184 { 00185 LOG_EXT_TSK_ENTER(); 00186 00187 if (sense_context()) { 00188 /* 00189 * 非タスクコンテキストから ext_tsk が呼ばれた場合, 00190 * システムログにエラーを記録し,そのまま実行を続ける. 00191 * その結果,強制的にタスクコンテキストに切り換えて, 00192 * 実行状態のタスクを終了させることになる.カーネルは 00193 * そのまま実行を継続するが,ターゲットによっては,非 00194 * タスクコンテキスト用のスタックにゴミが残ったり,割 00195 * 込みハンドラのネスト数の管理に矛盾が生じたりする場 00196 * 合がある. 00197 */ 00198 syslog_0(LOG_ALERT, 00199 "ext_tsk is called from non-task contexts."); 00200 } 00201 00202 retry: 00203 if (sense_lock()) { 00204 /* 00205 * CPUロック状態で ext_tsk が呼ばれた場合は,CPUロック 00206 * を解除してからタスクを終了する.実装上は,サービス 00207 * コール内でのCPUロックを省略すればよいだけ. 00208 */ 00209 syslog_0(LOG_WARNING, 00210 "ext_tsk is called from CPU locked state."); 00211 } 00212 else { 00213 if (sense_context()) { 00214 i_lock_cpu(); 00215 } 00216 else { 00217 t_lock_cpu(); 00218 } 00219 } 00220 00221 if (ACQUIRE_LOCK(runccb->tsk_lock)) { 00222 if (sense_context()) { 00223 i_unlock_cpu(); 00224 } 00225 else { 00226 t_unlock_cpu(); 00227 } 00228 goto retry; 00229 } 00230 00231 if (!(enadsp)) { 00232 /* 00233 * ディスパッチ禁止状態で ext_tsk が呼ばれた場合は, 00234 * ディスパッチ許可状態にしてからタスクを終了する. 00235 */ 00236 syslog_0(LOG_WARNING, 00237 "ext_tsk is called from dispatch disabled state."); 00238 enadsp = TRUE; 00239 } 00240 00246 if (!(runtsk->terflg)) { 00247 make_non_runnable(runccb, runtsk); 00248 make_dormant(runtsk); 00249 if (runtsk->actcnt) { 00250 runtsk->actcnt = FALSE; 00251 make_active(runccb, runtsk); 00252 } 00253 } 00254 RELEASE_LOCK(runccb->tsk_lock); 00255 exit_and_dispatch(); 00256 } 00257 00258 #endif /* __ext_tsk */ 00259 00263 #ifdef __ter_tsk 00264 00265 SYSCALL ER 00266 ter_tsk(ID tskid) 00267 { 00268 TCB *tcb; 00269 CCB *ccb, *occb; 00270 UINT tstat; 00271 ER ercd; 00272 BOOL dspreq = FALSE; 00273 00274 LOG_TER_TSK_ENTER(tskid); 00275 CHECK_TSKCTX_UNL(); 00276 ccb = T_CHECK_CLSID_CCB(tskid); 00277 tskid = remove_clsid(tskid); 00278 CHECK_TSKID(ccb, tskid); 00279 tcb = get_tcb(ccb, tskid); 00280 CHECK_NONSELF(tcb); 00281 00282 retry: 00283 T_ACQUIRE_LOCK(ccb->tsk_lock); 00284 if (TSTAT_DORMANT(tstat = tcb->tstat)) { 00285 ercd = E_OBJ; 00286 } 00287 else { 00288 if (TSTAT_RUNNABLE(tstat)) { 00289 if (make_non_runnable(ccb, tcb)) { 00290 /* 00291 * 対象タスクが他プロセッサ上のタスクかつRUNNABLEの場合, 00292 * RUN状態の可能性があるため,ディスパッチ要求を出す 00293 */ 00294 assert(ccb != my_local_ccb); 00295 dspreq = TRUE; 00296 } 00297 } 00298 else if (TSTAT_WAITING(tstat)) { 00299 if ((tstat & TS_WAIT_WOBJCB) == 0) { 00300 wait_cancel(ccb, tcb); 00301 } 00302 else { 00303 /* 00304 * オブジェクト待ちの場合 00305 */ 00306 /* 00307 * 00308 * デットロックを回避のため,一度ロックを手放した状態で 00309 * 二つ以上のter_tskが競合した場合に一回分しか実行されない可能性 00310 * がある.そこで,既に他のter_tskが発行されていれば(pend_tertskがTRUE) 00311 * actcntの操作のみを行いリターンする. 00312 */ 00313 if (tcb->pend_tertsk) { 00314 if (tcb->actcnt) { 00315 tcb->actcnt = FALSE; 00316 ercd = E_OK; 00317 } 00318 else { 00319 ercd = E_OBJ; 00320 } 00321 RELEASE_LOCK(ccb->tsk_lock); 00322 goto exit; 00323 } 00324 00325 /* 00326 * デッドロック回避を行う 00327 * 待ち対象になっているオブジェクトのCCBを取得し, 00328 * タスク強制終了保留フラグのセットから, 00329 * 一度タスクロックを開放(プロセッサロックは開放しない)する 00330 */ 00331 occb = ((WINFO_WOBJ *)(tcb->winfo))->ccb; 00332 tcb->pend_tertsk = TRUE; 00333 RELEASE_LOCK(ccb->tsk_lock); 00334 00335 /* 00336 * あらためて 00337 * オブジェクトロック -> タスクロック 00338 * の順でロックを取得 00339 */ 00340 if (ACQUIRE_LOCK(occb->obj_lock)) { 00341 t_unlock_cpu(); 00342 goto retry; 00343 } 00344 T_ACQUIRE_NESTED_LOCK(ccb->tsk_lock, occb->obj_lock); 00345 00346 /* 既に他の箇所で終了処理がなされたかチェック */ 00347 if (!(tcb->pend_tertsk)){ 00348 /* 既に他の箇所で終了処理がなされた */ 00349 T_RELEASE_NESTED_LOCK(ccb->tsk_lock, occb->obj_lock); 00350 T_RELEASE_LOCK(occb->obj_lock); 00351 ercd = E_OK; 00352 goto exit; 00353 } 00354 wait_cancel(ccb, tcb); 00355 RELEASE_LOCK(occb->obj_lock); 00356 } 00357 } 00358 /* 00359 * TCBを解放して,terflgをTRUEにする. 00360 */ 00361 make_dormant(tcb); 00362 tcb->terflg = TRUE; 00363 if (tcb->actcnt) { 00364 tcb->actcnt = FALSE; 00365 if (make_active(ccb, tcb)) { 00366 dspreq = TRUE; 00367 } 00368 } 00369 if (dspreq){ 00370 dspreq = dispatch_request(ccb->prcid); 00371 } 00372 ercd = E_OK; 00373 } 00374 T_RELEASE_LOCK_AND_DISPATCH(ccb->tsk_lock, dspreq); 00375 00376 exit: 00377 LOG_TER_TSK_LEAVE(ercd); 00378 return(ercd); 00379 } 00380 00381 #endif /* __ter_tsk */ 00382 00386 #ifdef __chg_pri 00387 00388 SYSCALL ER 00389 chg_pri(ID tskid, PRI tskpri) 00390 { 00391 CCB *ccb, *occb; 00392 TCB *tcb; 00393 UINT newpri; 00394 UINT tstat; 00395 ER ercd; 00396 BOOL dspreq = FALSE; 00397 00398 LOG_CHG_PRI_ENTER(tskid, tskpri); 00399 CHECK_TSKCTX_UNL(); 00400 ccb = T_CHECK_CLSID_CCB(tskid); 00401 tskid = remove_clsid(tskid); 00402 CHECK_TSKID_SELF(ccb, tskid); 00403 CHECK_TPRI_INI(tskpri); 00404 tcb = get_tcb_self(ccb, tskid); 00405 newpri = (tskpri == TPRI_INI) ? tcb->tinib->ipriority 00406 : INT_PRIORITY(tskpri); 00407 00408 retry: 00409 T_ACQUIRE_LOCK(ccb->tsk_lock); 00410 if (TSTAT_DORMANT(tstat = tcb->tstat) || (tcb == runtsk && tcb->terflg)) { 00411 ercd = E_OBJ; 00412 } 00413 else if (TSTAT_RUNNABLE(tstat)) { 00414 if (change_priority(ccb, tcb, newpri)) { 00415 dspreq = dispatch_request(ccb->prcid); 00416 } 00417 ercd = E_OK; 00418 } 00419 else { 00420 if ((tstat & TS_WAIT_WOBJCB) == 0) { 00421 tcb->priority = newpri; 00422 } 00423 else { 00424 /* 00425 * オブジェクト待ちの場合,デッドロック回避を行う 00426 */ 00427 00428 /* 00429 * 優先度変更保留セットし, 00430 * 待ち対象になっているオブジェクトのCCBを取得から, 00431 * 一度タスクロックを開放(プロセッサロックは開放しない)する 00432 */ 00433 occb = ((WINFO_WOBJ *)(tcb->winfo))->ccb; 00434 tcb->pend_chgpri = TRUE; 00435 tcb->pend_newpri = newpri; 00436 RELEASE_LOCK(ccb->tsk_lock); 00437 00438 /* 00439 * あらためて 00440 * オブジェクトロック -> タスクロック 00441 * の順でロックを取得 00442 */ 00443 if (ACQUIRE_LOCK(occb->obj_lock)) { 00444 t_unlock_cpu(); 00445 goto retry; 00446 } 00447 T_ACQUIRE_NESTED_LOCK(ccb->tsk_lock, occb->obj_lock); 00448 00449 /* タスクの状態が変化していないかチェック */ 00450 if (!(tcb->pend_chgpri)) { 00451 /* 既に他の箇所で優先度変更処理がなされた */ 00452 T_RELEASE_NESTED_LOCK(ccb->tsk_lock, occb->obj_lock); 00453 T_RELEASE_LOCK(occb->obj_lock); 00454 ercd = E_OK; 00455 goto exit; 00456 } 00457 tcb->priority = tcb->pend_newpri; 00458 tcb->pend_chgpri = FALSE; 00459 wobj_change_priority(((WINFO_WOBJ *)(tcb->winfo)) 00460 ->wobjcb, tcb); 00461 RELEASE_LOCK(occb->obj_lock); 00462 } 00463 ercd = E_OK; 00464 } 00465 T_RELEASE_LOCK_AND_DISPATCH(ccb->tsk_lock, dspreq); 00466 00467 exit: 00468 LOG_CHG_PRI_LEAVE(ercd); 00469 return(ercd); 00470 } 00471 00472 #endif /* __chg_pri */ 00473 00477 #ifdef __get_pri 00478 00479 SYSCALL ER 00480 get_pri(ID tskid, PRI *p_tskpri) 00481 { 00482 CCB *ccb; 00483 TCB *tcb; 00484 ER ercd; 00485 00486 LOG_GET_PRI_ENTER(tskid, p_tskpri); 00487 CHECK_TSKCTX_UNL(); 00488 ccb = T_CHECK_CLSID_CCB(tskid); 00489 tskid = remove_clsid(tskid); 00490 CHECK_TSKID_SELF(ccb, tskid); 00491 tcb = get_tcb_self(ccb, tskid); 00492 00493 retry: 00494 T_ACQUIRE_LOCK(ccb->tsk_lock); 00495 if (TSTAT_DORMANT(tcb->tstat) || (tcb == runtsk && tcb->terflg)) { 00496 ercd = E_OBJ; 00497 } 00498 else { 00499 *p_tskpri = EXT_TSKPRI(tcb->priority); 00500 ercd = E_OK; 00501 } 00502 T_RELEASE_LOCK(ccb->tsk_lock); 00503 00504 exit: 00505 LOG_GET_PRI_LEAVE(ercd, *p_tskpri); 00506 return(ercd); 00507 } 00508 00509 #endif /* __get_pri */ Copyright © 2006 by TAKAGI Nobuhisa. このページは Mon Apr 3 23:49:13 2006 に Doxygen によって生成されました。 |