|
|
task_sync.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_sync.c,v 1.3 2006/03/14 04:37:54 honda Exp $ 00039 */ 00040 00046 #include "fdmp_kernel.h" 00047 #include "check.h" 00048 #include "class.h" 00049 #include "task.h" 00050 #include "wait.h" 00051 00055 #ifdef __slp_tsk 00056 00057 SYSCALL ER 00058 slp_tsk() 00059 { 00060 WINFO winfo; 00061 ER ercd; 00062 00063 LOG_SLP_TSK_ENTER(); 00064 CHECK_DISPATCH(); 00065 00066 retry: 00067 T_ACQUIRE_LOCK_AND_CHECK_RUNNABLE(); 00068 if (runtsk->wupcnt) { 00069 runtsk->wupcnt = FALSE; 00070 RELEASE_LOCK(runccb->tsk_lock); 00071 ercd = E_OK; 00072 } 00073 else { 00074 runtsk->tstat = (TS_WAITING | TS_WAIT_SLEEP); 00075 make_wait(&winfo); 00076 LOG_TSKSTAT(runtsk); 00077 RELEASE_LOCK(runccb->tsk_lock); 00078 dispatch(); 00079 ercd = winfo.wercd; 00080 } 00081 t_unlock_cpu(); 00082 00083 exit: 00084 LOG_SLP_TSK_LEAVE(ercd); 00085 return(ercd); 00086 } 00087 00088 #endif /* __slp_tsk */ 00089 00093 #ifdef __tslp_tsk 00094 00095 SYSCALL ER 00096 tslp_tsk(TMO tmout) 00097 { 00098 WINFO winfo; 00099 TMEVTB tmevtb; 00100 ER ercd; 00101 00102 LOG_TSLP_TSK_ENTER(tmout); 00103 CHECK_DISPATCH(); 00104 CHECK_TMOUT(tmout); 00105 00106 retry: 00107 T_ACQUIRE_LOCK_AND_CHECK_RUNNABLE(); 00108 if (runtsk->wupcnt) { 00109 runtsk->wupcnt = FALSE; 00110 RELEASE_LOCK(runccb->tsk_lock); 00111 ercd = E_OK; 00112 } 00113 else if (tmout == TMO_POL) { 00114 RELEASE_LOCK(runccb->tsk_lock); 00115 ercd = E_TMOUT; 00116 } 00117 else { 00118 runtsk->tstat = (TS_WAITING | TS_WAIT_SLEEP); 00119 make_wait_tmout(&winfo, &tmevtb, tmout); 00120 LOG_TSKSTAT(runtsk); 00121 RELEASE_LOCK(runccb->tsk_lock); 00122 dispatch(); 00123 ercd = winfo.wercd; 00124 } 00125 t_unlock_cpu(); 00126 00127 exit: 00128 LOG_TSLP_TSK_LEAVE(ercd); 00129 return(ercd); 00130 } 00131 00132 #endif /* __tslp_tsk */ 00133 00137 #ifdef __wup_tsk 00138 00139 SYSCALL ER 00140 wup_tsk(ID tskid) 00141 { 00142 TCB *tcb; 00143 UINT tstat; 00144 ER ercd; 00145 CCB *ccb; 00146 BOOL dspreq = FALSE; 00147 00148 LOG_WUP_TSK_ENTER(tskid); 00149 CHECK_TSKCTX_UNL(); 00150 ccb = T_CHECK_CLSID_CCB(tskid); 00151 tskid = remove_clsid(tskid); 00152 CHECK_TSKID_SELF(ccb, tskid); 00153 tcb = get_tcb_self(ccb, tskid); 00154 00155 retry: 00156 T_ACQUIRE_LOCK(ccb->tsk_lock); 00157 if (TSTAT_DORMANT(tstat = tcb->tstat) || (tcb == runtsk && tcb->terflg)) { 00158 ercd = E_OBJ; 00159 } 00160 else if ((tstat & TS_WAIT_SLEEP) != 0) { 00161 if (wait_complete(ccb, tcb)) { 00162 dspreq = dispatch_request(ccb->prcid); 00163 } 00164 ercd = E_OK; 00165 } 00166 else if (!(tcb->wupcnt)) { 00167 tcb->wupcnt = TRUE; 00168 ercd = E_OK; 00169 } 00170 else { 00171 ercd = E_QOVR; 00172 } 00173 T_RELEASE_LOCK_AND_DISPATCH(ccb->tsk_lock, dspreq); 00174 00175 exit: 00176 LOG_WUP_TSK_LEAVE(ercd); 00177 return(ercd); 00178 } 00179 00180 #endif /* __wup_tsk */ 00181 00185 #ifdef __iwup_tsk 00186 00187 SYSCALL ER 00188 iwup_tsk(ID tskid) 00189 { 00190 TCB *tcb; 00191 UINT tstat; 00192 ER ercd; 00193 CCB *ccb; 00194 00195 LOG_IWUP_TSK_ENTER(tskid); 00196 CHECK_INTCTX_UNL(); 00197 ccb = I_CHECK_CLSID_CCB(tskid); 00198 tskid = remove_clsid(tskid); 00199 CHECK_TSKID(ccb, tskid); 00200 tcb = get_tcb(ccb, tskid); 00201 00202 retry: 00203 I_ACQUIRE_LOCK(ccb->tsk_lock); 00204 if (TSTAT_DORMANT(tstat = tcb->tstat)) { 00205 ercd = E_OBJ; 00206 } 00207 else if ((tstat & TS_WAIT_SLEEP) != 0) { 00208 if (wait_complete(ccb, tcb)) { 00209 if (dispatch_request(ccb->prcid)) { 00210 reqflg = TRUE; 00211 } 00212 } 00213 ercd = E_OK; 00214 } 00215 else if (!(tcb->wupcnt)) { 00216 tcb->wupcnt = TRUE; 00217 ercd = E_OK; 00218 } 00219 else { 00220 ercd = E_QOVR; 00221 } 00222 I_RELEASE_LOCK(ccb->tsk_lock); 00223 00224 exit: 00225 LOG_IWUP_TSK_LEAVE(ercd); 00226 return(ercd); 00227 } 00228 00229 #endif /* __iwup_tsk */ 00230 00234 #ifdef __can_wup 00235 00236 SYSCALL ER_UINT 00237 can_wup(ID tskid) 00238 { 00239 TCB *tcb; 00240 CCB *ccb; 00241 ER_UINT ercd; 00242 00243 LOG_CAN_WUP_ENTER(tskid); 00244 CHECK_TSKCTX_UNL(); 00245 ccb = T_CHECK_CLSID_CCB(tskid); 00246 tskid = remove_clsid(tskid); 00247 CHECK_TSKID_SELF(ccb, tskid); 00248 tcb = get_tcb_self(ccb, tskid); 00249 00250 retry: 00251 T_ACQUIRE_LOCK(ccb->tsk_lock); 00252 if (TSTAT_DORMANT(tcb->tstat) || (tcb == runtsk && tcb->terflg)) { 00253 ercd = E_OBJ; 00254 } 00255 else { 00256 ercd = tcb->wupcnt ? 1 : 0; 00257 tcb->wupcnt = FALSE; 00258 } 00259 T_RELEASE_LOCK(ccb->tsk_lock); 00260 00261 exit: 00262 LOG_CAN_WUP_LEAVE(ercd); 00263 return(ercd); 00264 } 00265 00266 #endif /* __can_wup */ 00267 00271 #ifdef __rel_wai 00272 00273 SYSCALL ER 00274 rel_wai(ID tskid) 00275 { 00276 TCB *tcb; 00277 ER ercd; 00278 CCB *ccb, *occb; 00279 BOOL dspreq = FALSE; 00280 00281 LOG_REL_WAI_ENTER(tskid); 00282 CHECK_TSKCTX_UNL(); 00283 ccb = T_CHECK_CLSID_CCB(tskid); 00284 tskid = remove_clsid(tskid); 00285 CHECK_TSKID(ccb, tskid); 00286 tcb = get_tcb(ccb, tskid); 00287 00288 retry: 00289 T_ACQUIRE_LOCK(ccb->tsk_lock); 00290 if (!(TSTAT_WAITING(tcb->tstat))) { 00291 ercd = E_OBJ; 00292 } 00293 else { 00294 if ((tcb->tstat & TS_WAIT_WOBJ) == 0) { 00295 dspreq = wait_release(ccb, tcb); 00296 } 00297 else { 00298 /* 00299 * オブジェクト待ちの場合 00300 * デッドロック回避のため,ロックを取得し直す 00301 */ 00302 occb = ((WINFO_WOBJ *)(tcb->winfo))->ccb; 00303 tcb->pend_relwai = TRUE; 00304 RELEASE_LOCK(ccb->tsk_lock); 00305 00306 /* 00307 * あらためて 00308 * オブジェクトロック -> タスクロック 00309 * の順でロックを取得 00310 */ 00311 if (ACQUIRE_LOCK(occb->obj_lock)) { 00312 t_unlock_cpu(); 00313 goto retry; 00314 } 00315 T_ACQUIRE_NESTED_LOCK(ccb->tsk_lock, occb->obj_lock); 00316 00317 /* タスクの状態が変化していないかチェック */ 00318 if (!(tcb->pend_relwai)) { 00319 /* 既に他の箇所で待ち解除処理がなされた */ 00320 T_RELEASE_NESTED_LOCK(ccb->tsk_lock, occb->obj_lock); 00321 T_RELEASE_LOCK(occb->obj_lock); 00322 ercd = E_OBJ; 00323 goto exit; 00324 } 00325 tcb->pend_relwai = FALSE; 00326 dspreq = wait_release(ccb, tcb); 00327 RELEASE_LOCK(occb->obj_lock); 00328 } 00329 if (dspreq){ 00330 dspreq = dispatch_request(ccb->prcid); 00331 } 00332 ercd = E_OK; 00333 } 00334 T_RELEASE_LOCK_AND_DISPATCH(ccb->tsk_lock, dspreq); 00335 00336 exit: 00337 LOG_REL_WAI_LEAVE(ercd); 00338 return(ercd); 00339 } 00340 00341 #endif /* __rel_wai */ 00342 00346 #ifdef __irel_wai 00347 00348 SYSCALL ER 00349 irel_wai(ID tskid) 00350 { 00351 TCB *tcb; 00352 ER ercd; 00353 CCB *ccb, *occb; 00354 BOOL dspreq = FALSE; 00355 00356 LOG_IREL_WAI_ENTER(tskid); 00357 CHECK_INTCTX_UNL(); 00358 ccb = I_CHECK_CLSID_CCB(tskid); 00359 tskid = remove_clsid(tskid); 00360 CHECK_TSKID(ccb, tskid); 00361 tcb = get_tcb(ccb, tskid); 00362 00363 retry: 00364 I_ACQUIRE_LOCK(ccb->tsk_lock); 00365 if (!(TSTAT_WAITING(tcb->tstat))) { 00366 ercd = E_OBJ; 00367 } 00368 else { 00369 if ((tcb->tstat & TS_WAIT_WOBJ) == 0) { 00370 dspreq = wait_release(ccb, tcb); 00371 } 00372 else { 00373 /* 00374 * オブジェクト待ちの場合 00375 * デッドロック回避のため,ロックを取得し直す 00376 */ 00377 occb = ((WINFO_WOBJ *)(tcb->winfo))->ccb; 00378 tcb->pend_relwai = TRUE; 00379 RELEASE_LOCK(ccb->tsk_lock); 00380 00381 if (ACQUIRE_LOCK(occb->obj_lock)) { 00382 i_unlock_cpu(); 00383 goto retry; 00384 } 00385 I_ACQUIRE_NESTED_LOCK(ccb->tsk_lock, occb->obj_lock); 00386 00387 /* 状態チェック */ 00388 if (!(tcb->pend_relwai)) { 00389 I_RELEASE_NESTED_LOCK(ccb->tsk_lock, occb->obj_lock); 00390 I_RELEASE_LOCK(occb->obj_lock); 00391 ercd = E_OBJ; 00392 goto exit; 00393 } 00394 tcb->pend_relwai = FALSE; 00395 dspreq = wait_release(ccb, tcb); 00396 RELEASE_LOCK(occb->obj_lock); 00397 } 00398 if (dspreq){ 00399 reqflg = TRUE; 00400 } 00401 ercd = E_OK; 00402 } 00403 I_RELEASE_LOCK(ccb->tsk_lock); 00404 00405 exit: 00406 LOG_IREL_WAI_LEAVE(ercd); 00407 return(ercd); 00408 } 00409 00410 #endif /* __irel_wai */ 00411 00419 #ifdef __sus_tsk 00420 00421 SYSCALL ER 00422 sus_tsk(ID tskid) 00423 { 00424 TCB *tcb; 00425 UINT tstat; 00426 ER ercd; 00427 CCB *ccb; 00428 BOOL dspreq = FALSE; 00429 00430 LOG_SUS_TSK_ENTER(tskid); 00431 CHECK_TSKCTX_UNL(); 00432 ccb = T_CHECK_CLSID_CCB(tskid); 00433 tskid = remove_clsid(tskid); 00434 CHECK_TSKID_SELF(ccb, tskid); 00435 tcb = get_tcb_self(ccb, tskid); 00436 00437 retry: 00438 T_ACQUIRE_LOCK(ccb->tsk_lock); 00439 if (tcb == runtsk && !(enadsp)) { 00440 /* 自分がディスパッチ禁止状態でsus_tskを発行するとエラー */ 00441 ercd = E_CTX; 00442 } 00443 else if (TSTAT_DORMANT(tstat = tcb->tstat)) { 00444 ercd = E_OBJ; 00445 } 00446 else if (TSTAT_RUNNABLE(tstat)) { 00447 /* 00448 * 実行できる状態から強制待ち状態への遷移 00449 */ 00450 tcb->tstat = TS_SUSPENDED; 00451 LOG_TSKSTAT(tcb); 00452 if (make_non_runnable(ccb, tcb)) { 00453 dspreq = dispatch_request(ccb->prcid); 00454 } 00455 ercd = E_OK; 00456 } 00457 else if (TSTAT_SUSPENDED(tstat)) { 00458 ercd = E_QOVR; 00459 } 00460 else { 00461 /* 00462 * 待ち状態から二重待ち状態への遷移 00463 */ 00464 tcb->tstat |= TS_SUSPENDED; 00465 LOG_TSKSTAT(tcb); 00466 ercd = E_OK; 00467 } 00468 T_RELEASE_LOCK_AND_DISPATCH(ccb->tsk_lock, dspreq); 00469 00470 exit: 00471 LOG_SUS_TSK_LEAVE(ercd); 00472 return(ercd); 00473 } 00474 00475 #endif /* __sus_tsk */ 00476 00480 #ifdef __rsm_tsk 00481 00482 SYSCALL ER 00483 rsm_tsk(ID tskid) 00484 { 00485 TCB *tcb; 00486 UINT tstat; 00487 ER ercd; 00488 CCB *ccb; 00489 BOOL dspreq = FALSE; 00490 00491 LOG_RSM_TSK_ENTER(tskid); 00492 CHECK_TSKCTX_UNL(); 00493 ccb = T_CHECK_CLSID_CCB(tskid); 00494 tskid = remove_clsid(tskid); 00495 CHECK_TSKID(ccb, tskid); 00496 tcb = get_tcb(ccb, tskid); 00497 00498 retry: 00499 T_ACQUIRE_LOCK(ccb->tsk_lock); 00500 if (!(TSTAT_SUSPENDED(tstat = tcb->tstat)) || (tcb == runtsk && tcb->terflg)) { 00501 ercd = E_OBJ; 00502 } 00503 else if (!(TSTAT_WAITING(tstat))) { 00504 /* 00505 * 強制待ち状態から実行できる状態への遷移 00506 */ 00507 if (make_runnable(ccb, tcb)) { 00508 dspreq = dispatch_request(ccb->prcid); 00509 } 00510 ercd = E_OK; 00511 } 00512 else { 00513 /* 00514 * 二重待ち状態から待ち状態への遷移 00515 */ 00516 tcb->tstat &= ~TS_SUSPENDED; 00517 LOG_TSKSTAT(tcb); 00518 ercd = E_OK; 00519 } 00520 T_RELEASE_LOCK_AND_DISPATCH(ccb->tsk_lock, dspreq); 00521 00522 exit: 00523 LOG_RSM_TSK_LEAVE(ercd); 00524 return(ercd); 00525 } 00526 00527 #endif /* __rsm_tsk */ 00528 00539 #ifdef __frsm_tsk 00540 00541 SYSCALL ER 00542 frsm_tsk(ID tskid) 00543 { 00544 ER ercd; 00545 00546 LOG_FRSM_TSK_ENTER(tskid); 00547 ercd = rsm_tsk(tskid); 00548 LOG_FRSM_TSK_LEAVE(ercd); 00549 return(ercd); 00550 } 00551 00552 #endif /* __frsm_tsk */ 00553 00557 #ifdef __dly_tsk 00558 00559 SYSCALL ER 00560 dly_tsk(RELTIM dlytim) 00561 { 00562 WINFO winfo; 00563 TMEVTB tmevtb; 00564 ER ercd; 00565 00566 LOG_DLY_TSK_ENTER(dlytim); 00567 CHECK_DISPATCH(); 00568 CHECK_PAR(dlytim <= TMAX_RELTIM); 00569 00570 retry: 00571 T_ACQUIRE_LOCK_AND_CHECK_RUNNABLE(); 00572 runtsk->tstat = TS_WAITING; 00573 make_non_runnable(runccb, runtsk); 00574 runtsk->winfo = &winfo; 00575 winfo.tmevtb = &tmevtb; 00576 tmevtb_enqueue(runccb, &tmevtb, dlytim, (CBACK) wait_tmout_ok, (VP) runtsk); 00577 LOG_TSKSTAT(runtsk); 00578 RELEASE_LOCK(runccb->tsk_lock); 00579 dispatch(); 00580 ercd = winfo.wercd; 00581 t_unlock_cpu(); 00582 00583 exit: 00584 LOG_DLY_TSK_LEAVE(ercd); 00585 return(ercd); 00586 } 00587 00588 #endif /* __dly_tsk */ Copyright © 2006 by TAKAGI Nobuhisa. このページは Mon Apr 3 23:49:13 2006 に Doxygen によって生成されました。 |