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 によって生成されました。