dataqueue.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: dataqueue.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 "dataqueue.h"
00051 
00055 extern const ID tmax_dtqid;
00056 
00060 extern const DTQINIB    dtqinib_table[];
00061 
00065 #define TNUM_DTQ    ((UINT)(tmax_dtqid - TMIN_ID + 1))
00066 
00070 extern DTQCB    dtqcb_table[];
00071 
00072 /*
00073  *  データキューIDからデータキュー管理ブロックを取り出すためのマクロ
00074  */
00075 #define INDEX_DTQ(dtqid)    ((UINT)((dtqid) - TMIN_ID))
00076 #define get_dtqcb(ccb, dtqid)   (&(((DTQCB *)(ccb->dtq.cb_table))[INDEX_DTQ(dtqid)]))
00077 
00078 
00085 typedef struct dataqueue_waiting_information {
00086     WINFO   winfo;      /* 標準の待ち情報ブロック */
00087     WOBJCB  *wobjcb;    /* 待ちオブジェクトの管理ブロック */
00088     CCB     *ccb;       /* オブジェクトが所属するCCBへのポインタ */
00089     VP_INT  data;       /* 送受信データ  */
00090 } WINFO_DTQ;
00091 
00095 #ifdef __dtqini
00096 
00097 void
00098 dataqueue_initialize(void)
00099 {
00100     UINT    i;
00101     DTQCB   *dtqcb;
00102 
00103     for (dtqcb = dtqcb_table, i = 0; i < TNUM_DTQ; dtqcb++, i++) {
00104         queue_initialize(&(dtqcb->swait_queue));
00105         dtqcb->dtqinib = &(dtqinib_table[i]);
00106         queue_initialize(&(dtqcb->rwait_queue));
00107         dtqcb->count = 0;
00108         dtqcb->head = 0;
00109         dtqcb->tail = 0;
00110     }
00111 
00112     my_local_exccb->dtq.cb_table = &dtqcb_table[0];
00113     my_local_exccb->dtq.max_id   = tmax_dtqid;
00114 }
00115 
00116 #endif /* __dtqini */
00117 
00121 #ifdef __dtqenq
00122 
00123 BOOL
00124 enqueue_data(DTQCB *dtqcb, VP_INT data)
00125 {
00126     if (dtqcb->count < dtqcb->dtqinib->dtqcnt) {
00127         *((VP_INT *)(dtqcb->dtqinib->dtq) + dtqcb->tail) = data;
00128         dtqcb->count++;
00129         dtqcb->tail++;
00130         if (dtqcb->tail >= dtqcb->dtqinib->dtqcnt) {
00131             dtqcb->tail = 0;
00132         }
00133         return(TRUE);
00134     }
00135     return(FALSE);
00136 }
00137 
00138 #endif /* __dtqenq */
00139 
00143 #ifdef __dtqfenq
00144 
00145 void
00146 force_enqueue_data(DTQCB *dtqcb, VP_INT data)
00147 {
00148     *((VP_INT *)(dtqcb->dtqinib->dtq) + dtqcb->tail) = data;
00149     dtqcb->tail++;
00150     if (dtqcb->tail >= dtqcb->dtqinib->dtqcnt) {
00151         dtqcb->tail = 0;
00152     }
00153     if (dtqcb->count < dtqcb->dtqinib->dtqcnt) {
00154         dtqcb->count++;
00155     }
00156     else {
00157         dtqcb->head = dtqcb->tail;
00158     }
00159 }
00160 
00161 #endif /* __dtqfenq */
00162 
00166 #ifdef __dtqdeq
00167 
00168 void
00169 dequeue_data(DTQCB *dtqcb, VP_INT *p_data)
00170 {   
00171     *p_data = *((VP_INT *)(dtqcb->dtqinib->dtq) + dtqcb->head);
00172     dtqcb->count--;
00173     dtqcb->head++;
00174     if (dtqcb->head >= dtqcb->dtqinib->dtqcnt) {
00175         dtqcb->head = 0;
00176     }   
00177 }
00178 
00179 #endif /* __dtqdeq */
00180 
00185 #ifdef __snd_dtq
00186 
00187 SYSCALL ER
00188 snd_dtq(ID dtqid, VP_INT data)
00189 {
00190     DTQCB   *dtqcb;
00191     WINFO_DTQ winfo;
00192     TCB     *tcb;
00193     ER      ercd;
00194     CCB     *ccb, *tccb;
00195     BOOL    dspreq = FALSE; 
00196 
00197     LOG_SND_DTQ_ENTER(dtqid, data);
00198     ccb = T_CHECK_CLSID_CCB(dtqid);
00199     dtqid = remove_clsid(dtqid);
00200     CHECK_DTQID(ccb, dtqid);
00201     dtqcb = get_dtqcb(ccb, dtqid);
00202 
00203   retry:
00204     T_ACQUIRE_LOCK(ccb->obj_lock);
00205     /*
00206      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00207      * 繰り返し実行するため,この間非破壊コードでなければならない.
00208      */
00209     if (!(queue_empty(&(dtqcb->rwait_queue)))) {
00210         tcb = (TCB *)(dtqcb->rwait_queue.next);
00211         tccb = get_ccb(tcb->clsid);
00212         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00213         /* 待ちキューの先頭タスクへデータ送信 */
00214         queue_delete((QUEUE *) tcb);
00215         ((WINFO_DTQ *)(tcb->winfo))->data = data;
00216         if (wait_complete(tccb, tcb)) {
00217             dspreq = dispatch_request(tccb->prcid);
00218         }
00219         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00220         RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00221         ercd = E_OK;
00222     }
00223     else if (enqueue_data(dtqcb, data)) {
00224         RELEASE_LOCK(ccb->obj_lock);
00225         ercd = E_OK;
00226     }
00227     else {
00228         winfo.data = data;
00229         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00230         wobj_make_wait(ccb, (WOBJCB *) dtqcb, (WINFO_WOBJ *) &winfo);
00231         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00232         RELEASE_LOCK(ccb->obj_lock);
00233         dispatch();
00234         ercd = winfo.winfo.wercd;
00235     }
00236     t_unlock_cpu();
00237 
00238   exit:
00239     LOG_SND_DTQ_LEAVE(ercd);
00240     return(ercd);
00241 }
00242 
00243 #endif /* __snd_dtq */
00244 
00248 #ifdef __psnd_dtq
00249 
00250 SYSCALL ER
00251 psnd_dtq(ID dtqid, VP_INT data)
00252 {
00253     DTQCB   *dtqcb;
00254     TCB     *tcb;
00255     ER      ercd;
00256     CCB     *ccb, *tccb;
00257     BOOL    dspreq = FALSE;
00258     
00259     LOG_PSND_DTQ_ENTER(dtqid, data);
00260     CHECK_TSKCTX_UNL();
00261     ccb = T_CHECK_CLSID_CCB(dtqid);
00262     dtqid = remove_clsid(dtqid);
00263     CHECK_DTQID(ccb, dtqid);
00264     dtqcb = get_dtqcb(ccb, dtqid);
00265 
00266   retry:
00267     T_ACQUIRE_LOCK(ccb->obj_lock);
00268     /*
00269      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00270      * 繰り返し実行するため,この間非破壊コードでなければならない.
00271      */
00272     if (!(queue_empty(&(dtqcb->rwait_queue)))) {
00273         tcb = (TCB *)(dtqcb->rwait_queue.next);
00274         tccb = get_ccb(tcb->clsid);
00275         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00276         /* 待ちキューの先頭タスクへデータ送信 */
00277         queue_delete((QUEUE *) tcb);
00278         ((WINFO_DTQ *)(tcb->winfo))->data = data;
00279         if (wait_complete(tccb, tcb)) {
00280             dspreq = dispatch_request(tccb->prcid);
00281         }
00282         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00283         ercd = E_OK;
00284     }
00285     else if (enqueue_data(dtqcb, data)) {
00286         ercd = E_OK;
00287     }
00288     else {
00289         ercd = E_TMOUT;
00290     }
00291     T_RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00292 
00293   exit:
00294     LOG_PSND_DTQ_LEAVE(ercd);
00295     return(ercd);
00296 }
00297 
00298 #endif /* __psnd_dtq */
00299 
00303 #ifdef __ipsnd_dtq
00304 
00305 SYSCALL ER
00306 ipsnd_dtq(ID dtqid, VP_INT data)
00307 {
00308     DTQCB   *dtqcb;
00309     TCB     *tcb;
00310     ER      ercd;
00311     CCB     *ccb, *tccb;
00312 
00313     LOG_IPSND_DTQ_ENTER(dtqid, data);
00314     CHECK_INTCTX_UNL();
00315     ccb = I_CHECK_CLSID_CCB(dtqid);
00316     dtqid = remove_clsid(dtqid);
00317     CHECK_DTQID(ccb, dtqid);
00318     dtqcb = get_dtqcb(ccb, dtqid);
00319 
00320   retry:
00321     I_ACQUIRE_LOCK(ccb->obj_lock);
00322     /*
00323      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00324      * 繰り返し実行するため,この間非破壊コードでなければならない.
00325      */
00326     if (!(queue_empty(&(dtqcb->rwait_queue)))) {    
00327         tcb = (TCB *)(dtqcb->rwait_queue.next);
00328         tccb = get_ccb(tcb->clsid);
00329         I_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00330         /* 待ちキューの先頭タスクへデータ送信 */
00331         queue_delete((QUEUE *) tcb);
00332         ((WINFO_DTQ *)(tcb->winfo))->data = data;
00333         if (wait_complete(tccb, tcb)) {
00334             if (dispatch_request(tccb->prcid)) {
00335                 reqflg = TRUE;
00336             }
00337         }
00338         I_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00339         ercd = E_OK;
00340     }
00341     else if (enqueue_data(dtqcb, data)) {
00342         ercd = E_OK;
00343     }
00344     else {
00345         ercd = E_TMOUT;
00346     }
00347     I_RELEASE_LOCK(ccb->obj_lock);
00348 
00349   exit:
00350     LOG_IPSND_DTQ_LEAVE(ercd);
00351     return(ercd);
00352 }
00353 
00354 #endif /* __ipsnd_dtq */
00355 
00359 #ifdef __tsnd_dtq
00360 
00361 SYSCALL ER
00362 tsnd_dtq(ID dtqid, VP_INT data, TMO tmout)
00363 {
00364     DTQCB   *dtqcb;
00365     WINFO_DTQ winfo;
00366     TMEVTB  tmevtb;
00367     TCB     *tcb;
00368     ER      ercd;
00369     CCB     *ccb, *tccb;
00370     BOOL    dspreq = FALSE;
00371     
00372     LOG_TSND_DTQ_ENTER(dtqid, data, tmout);
00373     CHECK_DISPATCH();
00374     ccb = T_CHECK_CLSID_CCB(dtqid);
00375     dtqid = remove_clsid(dtqid);
00376     CHECK_DTQID(ccb, dtqid);
00377     CHECK_TMOUT(tmout);
00378     dtqcb = get_dtqcb(ccb, dtqid);
00379 
00380   retry:
00381     T_ACQUIRE_LOCK(ccb->obj_lock);
00382     /*
00383      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00384      * 繰り返し実行するため,この間非破壊コードでなければならない.
00385      */
00386     if (!(queue_empty(&(dtqcb->rwait_queue)))) {
00387         tcb = (TCB *)(dtqcb->rwait_queue.next);
00388         tccb = get_ccb(tcb->clsid);
00389         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00390         /* 待ちキューの先頭タスクへデータ送信 */
00391         queue_delete((QUEUE *) tcb);
00392         ((WINFO_DTQ *)(tcb->winfo))->data = data;
00393         if (wait_complete(tccb, tcb)) {
00394             dspreq = dispatch_request(tccb->prcid);
00395         }
00396         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00397         RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00398         ercd = E_OK;
00399     }
00400     else if (enqueue_data(dtqcb, data)) {
00401         RELEASE_LOCK(ccb->obj_lock);
00402         ercd = E_OK;
00403     }
00404     else if (tmout == TMO_POL) {
00405         RELEASE_LOCK(ccb->obj_lock);
00406         ercd = E_TMOUT;
00407     }
00408     else {
00409         winfo.data = data;
00410         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00411         wobj_make_wait_tmout(ccb, (WOBJCB *) dtqcb, (WINFO_WOBJ *) &winfo,
00412                         &tmevtb, tmout);
00413         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00414         RELEASE_LOCK(ccb->obj_lock);
00415         dispatch();
00416         ercd = winfo.winfo.wercd;
00417     }
00418     t_unlock_cpu();
00419 
00420   exit:
00421     LOG_TSND_DTQ_LEAVE(ercd);
00422     return(ercd);
00423 }
00424 
00425 #endif /* __tsnd_dtq */
00426 
00427 /*
00428  *  データキューへの強制送信
00429  * 
00430  */
00431 #ifdef __fsnd_dtq
00432 
00433 SYSCALL ER
00434 fsnd_dtq(ID dtqid, VP_INT data)
00435 {
00436     DTQCB   *dtqcb; 
00437     TCB     *tcb;
00438     ER      ercd;
00439     CCB     *ccb, *tccb;
00440     BOOL    dspreq = FALSE;
00441     
00442     LOG_FSND_DTQ_ENTER(dtqid, data);
00443     CHECK_TSKCTX_UNL();
00444     ccb = T_CHECK_CLSID_CCB(dtqid);
00445     dtqid = remove_clsid(dtqid);
00446     CHECK_DTQID(ccb, dtqid);
00447     dtqcb = get_dtqcb(ccb, dtqid);
00448     CHECK_ILUSE(dtqcb->dtqinib->dtqcnt > 0);
00449 
00450   retry:
00451     T_ACQUIRE_LOCK(ccb->obj_lock);
00452     /*
00453      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00454      * 繰り返し実行するため,この間非破壊コードでなければならない.
00455      */
00456     if (!(queue_empty(&(dtqcb->rwait_queue)))) {
00457         tcb = (TCB *)(dtqcb->rwait_queue.next);
00458         tccb = get_ccb(tcb->clsid);
00459         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00460         /* 待ちキューの先頭タスクへデータ送信 */
00461         queue_delete((QUEUE *) tcb);
00462         ((WINFO_DTQ *)(tcb->winfo))->data = data;
00463         if (wait_complete(tccb, tcb)) {
00464             dspreq = dispatch_request(tccb->prcid);
00465         }
00466         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00467     }
00468     else {
00469         force_enqueue_data(dtqcb, data);
00470     }
00471     T_RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq)
00472     ercd = E_OK;
00473 
00474   exit:
00475     LOG_FSND_DTQ_LEAVE(ercd);
00476     return(ercd);
00477 }
00478 
00479 #endif /* __fsnd_dtq */
00480 
00484 #ifdef __ifsnd_dtq
00485 
00486 SYSCALL ER
00487 ifsnd_dtq(ID dtqid, VP_INT data)
00488 {
00489     DTQCB   *dtqcb;
00490     TCB     *tcb;
00491     ER      ercd;
00492     CCB     *ccb, *tccb;
00493 
00494     LOG_IFSND_DTQ_ENTER(dtqid, data);
00495     CHECK_INTCTX_UNL();
00496     ccb = I_CHECK_CLSID_CCB(dtqid);
00497     dtqid = remove_clsid(dtqid);
00498     CHECK_DTQID(ccb, dtqid);
00499     dtqcb = get_dtqcb(ccb, dtqid);
00500     CHECK_ILUSE(dtqcb->dtqinib->dtqcnt > 0);
00501 
00502   retry:
00503     I_ACQUIRE_LOCK(ccb->obj_lock);
00504     /*
00505      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00506      * 繰り返し実行するため,この間非破壊コードでなければならない.
00507      */
00508     if (!(queue_empty(&(dtqcb->rwait_queue)))) {
00509         tcb = (TCB*) (dtqcb->rwait_queue.next);
00510         tccb = get_ccb(tcb->clsid);
00511         I_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00512         /* 待ちキューの先頭タスクへデータ送信 */
00513         queue_delete((QUEUE *) tcb);
00514         ((WINFO_DTQ *)(tcb->winfo))->data = data;
00515         if (wait_complete(tccb, tcb)) {
00516             if (dispatch_request(tccb->prcid)) {
00517                 reqflg = TRUE;
00518             }
00519         }
00520         I_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00521     }
00522     else {
00523         force_enqueue_data(dtqcb, data);
00524     }
00525     I_RELEASE_LOCK(ccb->obj_lock);
00526     ercd = E_OK;
00527 
00528   exit:
00529     LOG_IFSND_DTQ_LEAVE(ercd);
00530     return(ercd);
00531 }
00532 
00533 #endif /* __ifsnd_dtq */
00534 
00538 #ifdef __rcv_dtq
00539 
00540 SYSCALL ER
00541 rcv_dtq(ID dtqid, VP_INT *p_data)
00542 {
00543     DTQCB   *dtqcb;
00544     WINFO_DTQ winfo;
00545     TCB     *tcb;
00546     ER      ercd;
00547     CCB     *ccb, *tccb;
00548     BOOL    dspreq = FALSE;
00549 
00550     LOG_RCV_DTQ_ENTER(dtqid, p_data);
00551     CHECK_DISPATCH();
00552     ccb = T_CHECK_CLSID_CCB(dtqid);
00553     dtqid = remove_clsid(dtqid);
00554     CHECK_DTQID(ccb, dtqid);
00555     dtqcb = get_dtqcb(ccb, dtqid);
00556     
00557   retry:
00558     T_ACQUIRE_LOCK(ccb->obj_lock);
00559     /*
00560      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00561      * 繰り返し実行するため,この間非破壊コードでなければならない.
00562      */ 
00563     if (!(queue_empty(&(dtqcb->swait_queue)))) {
00564         /* 送信待ちタスクあり */
00565         tcb = (TCB *)(dtqcb->swait_queue.next);
00566         tccb = get_ccb(tcb->clsid);
00567         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00568         queue_delete((QUEUE *) tcb);
00569         if (dtqcb->count > 0) {
00570             dequeue_data(dtqcb, p_data);
00571             enqueue_data(dtqcb, ((WINFO_DTQ *)(tcb->winfo))->data);
00572         }
00573         else {
00574             *p_data = ((WINFO_DTQ *)(tcb->winfo))->data;
00575         }
00576         if (wait_complete(tccb, tcb)) {
00577             dspreq = dispatch_request(tccb->prcid);
00578         }
00579         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00580         RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00581         ercd = E_OK;
00582     }
00583     else if (dtqcb->count > 0) {
00584         /* バッファにデータがあり,送信待ちタスクなし */
00585         dequeue_data(dtqcb, p_data);
00586         RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00587         ercd = E_OK;
00588     }
00589     else {
00590         /* バッファが空 かつ送信待ちタスクなし */
00591         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00592         runtsk->tstat = (TS_WAITING | TS_WAIT_WOBJ);
00593         make_wait(&(winfo.winfo));
00594         queue_insert_prev(&(dtqcb->rwait_queue),
00595                           &(runtsk->task_queue));
00596         winfo.ccb = ccb;
00597         winfo.wobjcb = (WOBJCB *) dtqcb;
00598         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00599         RELEASE_LOCK(ccb->obj_lock);
00600         dispatch();
00601         ercd = winfo.winfo.wercd;
00602         if (ercd == E_OK) {
00603             *p_data = winfo.data;
00604         }
00605     }
00606     t_unlock_cpu();
00607 
00608   exit:
00609     LOG_RCV_DTQ_LEAVE(ercd, *p_data);
00610     return(ercd);
00611 }
00612 
00613 #endif /* __rcv_dtq */
00614 
00618 #ifdef __prcv_dtq
00619 
00620 SYSCALL ER
00621 prcv_dtq(ID dtqid, VP_INT *p_data)
00622 {
00623     DTQCB   *dtqcb;
00624     TCB     *tcb;
00625     ER      ercd;
00626     CCB     *ccb, *tccb;
00627     BOOL    dspreq = FALSE;
00628 
00629     LOG_PRCV_DTQ_ENTER(dtqid, p_data);
00630     CHECK_TSKCTX_UNL();
00631     ccb = T_CHECK_CLSID_CCB(dtqid);
00632     dtqid = remove_clsid(dtqid);
00633     CHECK_DTQID(ccb, dtqid);
00634     dtqcb = get_dtqcb(ccb, dtqid);
00635 
00636   retry:
00637     T_ACQUIRE_LOCK(ccb->obj_lock);
00638     /*
00639      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00640      * 繰り返し実行するため,この間非破壊コードでなければならない.
00641      */ 
00642     if (!(queue_empty(&(dtqcb->swait_queue)))) {
00643         /* 送信待ちタスクあり */
00644         tcb = (TCB *)(dtqcb->swait_queue.next);
00645         tccb = get_ccb(tcb->clsid);
00646         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00647         queue_delete((QUEUE *) tcb);
00648         if (dtqcb->count > 0) {
00649             dequeue_data(dtqcb, p_data);
00650             enqueue_data(dtqcb, ((WINFO_DTQ *)(tcb->winfo))->data);
00651         }
00652         else {
00653             *p_data = ((WINFO_DTQ *)(tcb->winfo))->data;
00654         }
00655         if (wait_complete(tccb, tcb)) {
00656             dspreq = dispatch_request(tccb->prcid);
00657         }
00658         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00659         ercd = E_OK;
00660     }
00661     else if (dtqcb->count > 0) {
00662         /* バッファにデータがあり,送信待ちタスクなし */
00663         dequeue_data(dtqcb, p_data);
00664         ercd = E_OK;
00665     }
00666     else {
00667         ercd = E_TMOUT;
00668     }
00669     T_RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00670 
00671   exit:
00672     LOG_PRCV_DTQ_LEAVE(ercd, *p_data);
00673     return(ercd);
00674 }
00675 
00676 #endif /* __prcv_dtq */
00677 
00681 #ifdef __trcv_dtq
00682 
00683 SYSCALL ER
00684 trcv_dtq(ID dtqid, VP_INT *p_data, TMO tmout)
00685 {
00686     DTQCB   *dtqcb;
00687     WINFO_DTQ winfo;
00688     TMEVTB  tmevtb;
00689     TCB     *tcb;
00690     ER      ercd;
00691     CCB     *ccb, *tccb;
00692     BOOL    dspreq = FALSE;
00693 
00694     LOG_TRCV_DTQ_ENTER(dtqid, p_data, tmout);
00695     CHECK_DISPATCH();
00696     ccb = T_CHECK_CLSID_CCB(dtqid);
00697     dtqid = remove_clsid(dtqid);
00698     CHECK_DTQID(ccb, dtqid);
00699     CHECK_TMOUT(tmout);
00700     dtqcb = get_dtqcb(ccb, dtqid);
00701 
00702   retry:
00703     T_ACQUIRE_LOCK(ccb->obj_lock);
00704     /*
00705      * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00706      * 繰り返し実行するため,この間非破壊コードでなければならない.
00707      */ 
00708     if (!(queue_empty(&(dtqcb->swait_queue)))) {
00709         /* 送信待ちタスクあり */
00710         tcb = (TCB *)(dtqcb->swait_queue.next);
00711         tccb = get_ccb(tcb->clsid);
00712         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00713         queue_delete((QUEUE *) tcb);
00714         if (dtqcb->count > 0) {
00715             dequeue_data(dtqcb, p_data);
00716             enqueue_data(dtqcb, ((WINFO_DTQ *)(tcb->winfo))->data);
00717         }
00718         else {
00719             *p_data = ((WINFO_DTQ *)(tcb->winfo))->data;
00720         }
00721         if (wait_complete(tccb, tcb)) {
00722             dspreq = dispatch_request(tccb->prcid);
00723         }
00724         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00725         RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00726         ercd = E_OK;
00727     }
00728     else if (dtqcb->count > 0) {
00729         /* バッファにデータがあり,送信待ちタスクなし */
00730         dequeue_data(dtqcb, p_data);
00731         RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00732         ercd = E_OK;
00733     }
00734     else if (tmout == TMO_POL) {
00735         RELEASE_LOCK(ccb->obj_lock);
00736         ercd = E_TMOUT;
00737     }
00738     else {
00739         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00740         runtsk->tstat = (TS_WAITING | TS_WAIT_WOBJ);
00741         make_wait_tmout(&(winfo.winfo), &tmevtb, tmout);
00742         queue_insert_prev(&(dtqcb->rwait_queue),
00743                           &(runtsk->task_queue));
00744         winfo.ccb = ccb;
00745         winfo.wobjcb = (WOBJCB *) dtqcb;
00746         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00747         RELEASE_LOCK(ccb->obj_lock);
00748         dispatch();
00749         ercd = winfo.winfo.wercd;
00750         if (ercd == E_OK) {
00751             *p_data = winfo.data;
00752         }
00753     }
00754     t_unlock_cpu();
00755 
00756   exit:
00757     LOG_TRCV_DTQ_LEAVE(ercd, *p_data);
00758     return(ercd);
00759 }
00760 
00761 #endif /* __trcv_dtq */

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