eventflag.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: eventflag.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 "task.h"
00049 #include "wait.h"
00050 #include "eventflag.h"
00051 
00055 extern const ID tmax_flgid;
00056 
00060 extern const FLGINIB    flginib_table[];
00061 
00065 extern FLGCB    flgcb_table[];
00066 
00070 #define TNUM_FLG    ((UINT)(tmax_flgid - TMIN_ID + 1))
00071 
00072 /*
00073  *  イベントフラグIDからイベントフラグ管理ブロックを取り出すためのマクロ
00074  */
00075 #define INDEX_FLG(flgid)    ((UINT)((flgid) - TMIN_ID))
00076 #define get_flgcb(ccb, flgid)   (&(((FLGCB *)(ccb->flg.cb_table))[INDEX_FLG(flgid)]))
00077 
00084 typedef struct eventflag_waiting_information {
00085     WINFO   winfo;      /* 標準の待ち情報ブロック */
00086     WOBJCB  *wobjcb;    /* 待ちオブジェクトの管理ブロック */
00087     CCB     *ccb;       /* オブジェクトが所属するCCB */
00088     FLGPTN  waiptn;     /* 待ちパターン */
00089     MODE    wfmode;     /* 待ちモード */
00090     FLGPTN  flgptn;     /* 待ち解除時のパターン */
00091 } WINFO_FLG;
00092 
00096 #ifdef __flgini
00097 
00098 void
00099 eventflag_initialize(void)
00100 {
00101     UINT    i;
00102     FLGCB   *flgcb;
00103 
00104     for (flgcb = flgcb_table, i = 0; i < TNUM_FLG; flgcb++, i++) {
00105         queue_initialize(&(flgcb->wait_queue));
00106         flgcb->flginib = &(flginib_table[i]);
00107         flgcb->flgptn = flgcb->flginib->iflgptn;
00108     }
00109     
00110     my_local_exccb->flg.cb_table = &flgcb_table[0];
00111     my_local_exccb->flg.max_id = tmax_flgid;
00112 }
00113 
00114 #endif /* __flgini */
00115 
00119 #ifdef __flgcnd
00120 
00121 BOOL
00122 eventflag_cond(FLGCB *flgcb, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
00123 {
00124     if ((wfmode & TWF_ORW) != 0 ? (flgcb->flgptn & waiptn) != 0
00125                 : (flgcb->flgptn & waiptn) == waiptn) {
00126         *p_flgptn = flgcb->flgptn;
00127         if ((flgcb->flginib->flgatr & TA_CLR) != 0) {
00128             flgcb->flgptn = 0;
00129         }
00130         return(TRUE);
00131     }
00132     return(FALSE);
00133 }
00134 
00135 #endif /* __flgcnd */
00136 
00140 #ifdef __set_flg
00141 
00142 SYSCALL ER
00143 set_flg(ID flgid, FLGPTN setptn)
00144 {
00145     FLGCB   *flgcb;
00146     TCB     *tcb;
00147     WINFO_FLG *winfo;
00148     ER      ercd;
00149     CCB     *ccb, *tccb;
00150     BOOL    dspreq = FALSE;
00151 
00152     LOG_SET_FLG_ENTER(flgid, setptn);
00153     CHECK_TSKCTX_UNL();
00154     ccb = T_CHECK_CLSID_CCB(flgid);
00155     flgid = remove_clsid(flgid);
00156     CHECK_FLGID(ccb, flgid);
00157     flgcb = get_flgcb(ccb, flgid);
00158 
00159   retry:
00160     T_ACQUIRE_LOCK(ccb->obj_lock);
00161     if (!(queue_empty(&(flgcb->wait_queue)))) {
00162         tcb = (TCB *)(flgcb->wait_queue.next);
00163         tccb = get_ccb(tcb->clsid);
00164         winfo = (WINFO_FLG *)(tcb->winfo);
00165         /*
00166          * eventflag_cond() がTRUEの場合のみロックを取得すればよいが,
00167          * eventflag_cond() が破壊的コードであるため(flgcb->flgptn = 0)
00168          * 実行前にロックを取得する.
00169          */ 
00170         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00171         flgcb->flgptn |= setptn;
00172         if (eventflag_cond(flgcb, winfo->waiptn,
00173                     winfo->wfmode, &(winfo->flgptn))) {
00174             queue_delete(&(tcb->task_queue));
00175             if (wait_complete(tccb, tcb)) {
00176                 dspreq = dispatch_request(tccb->prcid);
00177             }
00178 
00179         }
00180         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00181     }
00182     else {
00183         flgcb->flgptn |= setptn;
00184     }
00185     T_RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00186     ercd = E_OK;
00187 
00188   exit:
00189     LOG_SET_FLG_LEAVE(ercd);
00190     return(ercd);
00191 }
00192 
00193 #endif /* __set_flg */
00194 
00198 #ifdef __iset_flg
00199 
00200 SYSCALL ER
00201 iset_flg(ID flgid, FLGPTN setptn)
00202 {
00203     FLGCB   *flgcb;
00204     TCB     *tcb;
00205     WINFO_FLG *winfo;
00206     ER      ercd;
00207     CCB     *ccb, *tccb;
00208     
00209     LOG_ISET_FLG_ENTER(flgid, setptn);
00210     CHECK_INTCTX_UNL();
00211     ccb = I_CHECK_CLSID_CCB(flgid);
00212     flgid = remove_clsid(flgid);
00213     CHECK_FLGID(ccb, flgid);
00214     flgcb = get_flgcb(ccb, flgid);
00215 
00216   retry:
00217     I_ACQUIRE_LOCK(ccb->obj_lock);
00218     if (!(queue_empty(&(flgcb->wait_queue)))) {
00219         tcb = (TCB *)(flgcb->wait_queue.next);
00220         tccb = get_ccb(tcb->clsid);
00221         winfo = (WINFO_FLG *)(tcb->winfo);
00222         /*
00223          * eventflag_cond() がTRUEの場合のみロックを取得すればよいが,
00224          * eventflag_cond() が破壊的コードであるため(flgcb->flgptn = 0)
00225          * 実行前にロックを取得する. 
00226          */      
00227         I_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00228         flgcb->flgptn |= setptn;
00229         if (eventflag_cond(flgcb, winfo->waiptn,
00230                     winfo->wfmode, &(winfo->flgptn))) {
00231             queue_delete(&(tcb->task_queue));
00232             if (wait_complete(ccb, tcb)) {
00233                 if (dispatch_request(tccb->prcid)) {
00234                     reqflg = TRUE;
00235                 }
00236             }
00237         }
00238         I_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00239     }
00240     else {
00241         flgcb->flgptn |= setptn;
00242     }
00243     I_RELEASE_LOCK(ccb->obj_lock);
00244     ercd = E_OK;
00245 
00246   exit:
00247     LOG_ISET_FLG_LEAVE(ercd);
00248     return(ercd);
00249 }
00250 
00251 #endif /* __iset_flg */
00252 
00256 #ifdef __clr_flg
00257 
00258 SYSCALL ER
00259 clr_flg(ID flgid, FLGPTN clrptn)
00260 {
00261     FLGCB   *flgcb;
00262     ER      ercd;
00263     CCB     *ccb;
00264 
00265     LOG_CLR_FLG_ENTER(flgid, clrptn);
00266     CHECK_TSKCTX_UNL();
00267     ccb = T_CHECK_CLSID_CCB(flgid);
00268     flgid = remove_clsid(flgid);
00269     CHECK_FLGID(ccb, flgid);
00270     flgcb = get_flgcb(ccb, flgid);
00271 
00272   retry:
00273     T_ACQUIRE_LOCK(ccb->obj_lock);
00274     flgcb->flgptn &= clrptn; 
00275     T_RELEASE_LOCK(ccb->obj_lock);
00276     ercd = E_OK;
00277     
00278   exit:
00279     LOG_CLR_FLG_LEAVE(ercd);
00280     return(ercd);
00281 }
00282 
00283 #endif /* __clr_flg */
00284 
00288 #ifdef __wai_flg
00289 
00290 SYSCALL ER
00291 wai_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
00292 {
00293     FLGCB   *flgcb;
00294     WINFO_FLG winfo;
00295     ER      ercd;
00296     CCB     *ccb;
00297 
00298     LOG_WAI_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn);
00299     CHECK_DISPATCH();
00300     ccb = T_CHECK_CLSID_CCB(flgid);
00301     flgid = remove_clsid(flgid);
00302     CHECK_FLGID(ccb, flgid);
00303     CHECK_PAR(waiptn != 0);
00304     CHECK_PAR((wfmode & ~TWF_ORW) == 0);
00305     flgcb = get_flgcb(ccb, flgid);
00306 
00307   retry:
00308     T_ACQUIRE_LOCK(ccb->obj_lock);
00309     if (!(queue_empty(&(flgcb->wait_queue)))) {
00310         RELEASE_LOCK(ccb->obj_lock);
00311         ercd = E_ILUSE;
00312     }
00313     else if (eventflag_cond(flgcb, waiptn, wfmode, p_flgptn)) {
00314         RELEASE_LOCK(ccb->obj_lock);
00315         ercd = E_OK;
00316     }
00317     else {
00318         winfo.waiptn = waiptn;
00319         winfo.wfmode = wfmode;
00320         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00321         wobj_make_wait(ccb, (WOBJCB *) flgcb, (WINFO_WOBJ *) &winfo);
00322         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00323         RELEASE_LOCK(ccb->obj_lock);
00324         dispatch();
00325         ercd = winfo.winfo.wercd;
00326         if (ercd == E_OK) {
00327             *p_flgptn = winfo.flgptn;
00328         }       
00329     }
00330     t_unlock_cpu();
00331 
00332   exit:
00333     LOG_WAI_FLG_LEAVE(ercd, *p_flgptn);
00334     return(ercd);
00335 }
00336 
00337 #endif /* __wai_flg */
00338 
00342 #ifdef __pol_flg
00343 
00344 SYSCALL ER
00345 pol_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
00346 {
00347     FLGCB   *flgcb;
00348     ER      ercd;
00349     CCB     *ccb;
00350 
00351     LOG_POL_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn);
00352     CHECK_TSKCTX_UNL();
00353     ccb = T_CHECK_CLSID_CCB(flgid);
00354     flgid = remove_clsid(flgid);
00355     CHECK_FLGID(ccb, flgid);
00356     CHECK_PAR(waiptn != 0);
00357     CHECK_PAR((wfmode & ~TWF_ORW) == 0);
00358     flgcb = get_flgcb(ccb, flgid);
00359 
00360   retry:
00361     T_ACQUIRE_LOCK(ccb->obj_lock);
00362     if (!(queue_empty(&(flgcb->wait_queue)))) {
00363         ercd = E_ILUSE;
00364     }
00365     else if (eventflag_cond(flgcb, waiptn, wfmode, p_flgptn)) {
00366         ercd = E_OK;
00367     }
00368     else {
00369         ercd = E_TMOUT;
00370     }
00371     T_RELEASE_LOCK(ccb->obj_lock);
00372 
00373   exit:
00374     LOG_POL_FLG_LEAVE(ercd, *p_flgptn);
00375     return(ercd);
00376 }
00377 
00378 #endif /* __pol_flg */
00379 
00383 #ifdef __twai_flg
00384 
00385 SYSCALL ER
00386 twai_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn, TMO tmout)
00387 {
00388     FLGCB   *flgcb;
00389     WINFO_FLG winfo;
00390     TMEVTB  tmevtb;
00391     ER      ercd = E_OK;
00392     CCB     *ccb;
00393 
00394     LOG_TWAI_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn, tmout);
00395     CHECK_DISPATCH();
00396     ccb = T_CHECK_CLSID_CCB(flgid);
00397     flgid = remove_clsid(flgid);
00398     CHECK_FLGID(ccb, flgid);
00399     CHECK_PAR(waiptn != 0);
00400     CHECK_PAR((wfmode & ~TWF_ORW) == 0);
00401     CHECK_TMOUT(tmout);
00402     flgcb = get_flgcb(ccb, flgid);
00403 
00404   retry:
00405     T_ACQUIRE_LOCK(ccb->obj_lock);
00406     if (!(queue_empty(&(flgcb->wait_queue)))) {
00407         RELEASE_LOCK(ccb->obj_lock);
00408         ercd = E_ILUSE;
00409     }
00410     else if (eventflag_cond(flgcb, waiptn, wfmode, p_flgptn)) {
00411         RELEASE_LOCK(ccb->obj_lock);
00412         ercd = E_OK;
00413     }
00414     else if (tmout == TMO_POL) {
00415         RELEASE_LOCK(ccb->obj_lock);
00416         ercd = E_TMOUT;
00417     }
00418     else {
00419         winfo.waiptn = waiptn;
00420         winfo.wfmode = wfmode;
00421         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00422         wobj_make_wait_tmout(ccb, (WOBJCB *) flgcb, (WINFO_WOBJ *) &winfo,
00423                         &tmevtb, tmout);
00424         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00425         RELEASE_LOCK(ccb->obj_lock);
00426         dispatch();
00427         ercd = winfo.winfo.wercd;
00428         if (ercd == E_OK) {
00429             *p_flgptn = winfo.flgptn;
00430         }
00431     }
00432     t_unlock_cpu();
00433 
00434   exit:
00435     LOG_TWAI_FLG_LEAVE(ercd, *p_flgptn);
00436     return(ercd);
00437 }
00438 
00439 #endif /* __twai_flg */

Copyright © 2006 by TAKAGI Nobuhisa.
このページは Mon Apr 3 23:49:12 2006 に Doxygen によって生成されました。