mailbox.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: mailbox.c,v 1.3 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 #include "mailbox.h"
00050 
00054 extern const ID tmax_mbxid;
00055 
00059 extern const MBXINIB    mbxinib_table[];
00060 
00064 extern MBXCB    mbxcb_table[];
00065 
00069 #define TNUM_MBX    ((UINT)(tmax_mbxid - TMIN_ID + 1))
00070 
00074 #define INDEX_MBX(mbxid)    ((UINT)((mbxid) - TMIN_ID))
00075 #define get_mbxcb(ccb, mbxid)   (&(((MBXCB *)(ccb->mbx.cb_table))[INDEX_MBX(mbxid)]))
00076 
00080 typedef struct mailbox_waiting_information {
00081     WINFO   winfo;      /* 標準の待ち情報ブロック */
00082     WOBJCB  *wobjcb;    /* 待ちオブジェクトの管理ブロック */
00083     CCB     *ccb;       /* オブジェクトが所属するクラスID */
00084     T_MSG   *pk_msg;    /* 受信したメッセージ */
00085 } WINFO_MBX;
00086 
00090 #ifdef __mbxini
00091 
00092 void
00093 mailbox_initialize()
00094 {
00095     UINT    i;
00096     MBXCB   *mbxcb;
00097 
00098     for (mbxcb = mbxcb_table, i = 0; i < TNUM_MBX; mbxcb++, i++) {
00099         queue_initialize(&(mbxcb->wait_queue));
00100         mbxcb->mbxinib = &(mbxinib_table[i]);
00101         mbxcb->head = NULL;
00102     }
00103 
00104     my_local_exccb->mbx.cb_table = &mbxcb_table[0];
00105     my_local_exccb->mbx.max_id   = tmax_mbxid;
00106 }
00107 
00108 #endif /* __mbxini */
00109 
00113 #define MSGPRI(pk_msg)  (((T_MSG_PRI *) pk_msg)->msgpri)
00114 
00118 Inline void
00119 enqueue_msg_pri(T_MSG **p_prevmsg_next, T_MSG *pk_msg)
00120 {
00121     T_MSG   *pk_nextmsg;
00122 
00123     while ((pk_nextmsg = *p_prevmsg_next) != NULL) {
00124         if (MSGPRI(pk_nextmsg) > MSGPRI(pk_msg)) {
00125             break;
00126         }
00127         p_prevmsg_next = &(pk_nextmsg->next);
00128     }
00129     pk_msg->next = pk_nextmsg;
00130     *p_prevmsg_next = pk_msg;
00131 }
00132 
00133 
00137 #ifdef __snd_mbx
00138 
00139 SYSCALL ER
00140 snd_mbx(ID mbxid, T_MSG *pk_msg)
00141 {
00142     MBXCB   *mbxcb;
00143     TCB     *tcb;
00144     ER      ercd;
00145     CCB     *ccb, *tccb;
00146     BOOL    dspreq = FALSE;
00147     
00148     LOG_SND_MBX_ENTER(mbxid, pk_msg);
00149     CHECK_TSKCTX_UNL();
00150     ccb = T_CHECK_CLSID_CCB(mbxid);
00151     mbxid = remove_clsid(mbxid);
00152     CHECK_MBXID(ccb, mbxid);
00153     mbxcb = get_mbxcb(ccb, mbxid);
00154     CHECK_PAR((mbxcb->mbxinib->mbxatr & TA_MPRI) == 0
00155         || (TMIN_MPRI <= MSGPRI(pk_msg)
00156             && MSGPRI(pk_msg) <= mbxcb->mbxinib->maxmpri));
00157 
00158   retry:
00159     T_ACQUIRE_LOCK(ccb->obj_lock);
00160     if (!(queue_empty(&(mbxcb->wait_queue)))) {
00161         tcb = (TCB *) (mbxcb->wait_queue.next);
00162         tccb = get_ccb(tcb->clsid);
00163         ((WINFO_MBX *)(tcb->winfo))->pk_msg = pk_msg;
00164         /*
00165          * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00166          * 繰り返し実行するため,この間非破壊コードでなければならない.
00167          */              
00168         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00169         /* 待ちキューから削除する */
00170         queue_delete_next(&(mbxcb->wait_queue));
00171         if (wait_complete(tccb, tcb)) {
00172             dspreq = dispatch_request(tccb->prcid);
00173         }
00174         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00175         ercd = E_OK;
00176     }
00177     else if ((mbxcb->mbxinib->mbxatr & TA_MPRI) != 0) {
00178         enqueue_msg_pri(&(mbxcb->head), pk_msg);
00179         ercd = E_OK;
00180     }
00181     else {
00182         pk_msg->next = NULL;
00183         if (mbxcb->head != NULL) {
00184             mbxcb->last->next = pk_msg;
00185         }
00186         else {
00187             mbxcb->head = pk_msg;
00188         }
00189         mbxcb->last = pk_msg;
00190         ercd = E_OK;
00191     }
00192     T_RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq); 
00193 
00194   exit:
00195     LOG_SND_MBX_LEAVE(ercd);
00196     return(ercd);
00197 }
00198 
00199 #endif /* __snd_mbx */
00200 
00204 #ifdef __rcv_mbx
00205 
00206 SYSCALL ER
00207 rcv_mbx(ID mbxid, T_MSG **ppk_msg)
00208 {
00209     MBXCB   *mbxcb;
00210     WINFO_MBX winfo;
00211     ER      ercd;
00212     CCB     *ccb;
00213     
00214     LOG_RCV_MBX_ENTER(mbxid, ppk_msg);
00215     CHECK_DISPATCH();
00216     ccb = T_CHECK_CLSID_CCB(mbxid);
00217     mbxid = remove_clsid(mbxid);
00218     CHECK_MBXID(ccb, mbxid);
00219     mbxcb = get_mbxcb(ccb, mbxid);  
00220 
00221   retry:
00222     T_ACQUIRE_LOCK(ccb->obj_lock);
00223     if (mbxcb->head != NULL) {
00224         *ppk_msg = mbxcb->head;
00225         mbxcb->head = (*ppk_msg)->next;
00226         RELEASE_LOCK(ccb->obj_lock);
00227         ercd = E_OK;
00228     }
00229     else {
00230         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00231         wobj_make_wait(ccb, (WOBJCB *) mbxcb, (WINFO_WOBJ *) &winfo);
00232         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00233         RELEASE_LOCK(ccb->obj_lock);
00234         dispatch();
00235         ercd = winfo.winfo.wercd;
00236         if (ercd == E_OK) {
00237             *ppk_msg = winfo.pk_msg;
00238         }
00239     }
00240     t_unlock_cpu();
00241 
00242   exit:
00243     LOG_RCV_MBX_LEAVE(ercd, *ppk_msg);
00244     return(ercd);
00245 }
00246 
00247 #endif /* __rcv_mbx */
00248 
00252 #ifdef __prcv_mbx
00253 
00254 SYSCALL ER
00255 prcv_mbx(ID mbxid, T_MSG **ppk_msg)
00256 {
00257     MBXCB   *mbxcb;
00258     ER      ercd;
00259     CCB     *ccb;
00260     
00261     LOG_PRCV_MBX_ENTER(mbxid, ppk_msg);
00262     CHECK_TSKCTX_UNL();
00263     ccb = T_CHECK_CLSID_CCB(mbxid);
00264     mbxid = remove_clsid(mbxid);
00265     CHECK_MBXID(ccb, mbxid);
00266     mbxcb = get_mbxcb(ccb, mbxid);
00267 
00268   retry:
00269     T_ACQUIRE_LOCK(ccb->obj_lock);
00270     if (mbxcb->head != NULL) {
00271         *ppk_msg = mbxcb->head;
00272         mbxcb->head = (*ppk_msg)->next;
00273         ercd = E_OK;
00274     }
00275     else {
00276         ercd = E_TMOUT;
00277     }
00278     T_RELEASE_LOCK(ccb->obj_lock);
00279 
00280   exit:
00281     LOG_PRCV_MBX_LEAVE(ercd, *ppk_msg);
00282     return(ercd);
00283 }
00284 
00285 #endif /* __prcv_mbx */
00286 
00290 #ifdef __trcv_mbx
00291 
00292 SYSCALL ER
00293 trcv_mbx(ID mbxid, T_MSG **ppk_msg, TMO tmout)
00294 {
00295     MBXCB   *mbxcb;
00296     WINFO_MBX winfo;
00297     TMEVTB  tmevtb;
00298     ER      ercd;
00299     CCB     *ccb;
00300     
00301     LOG_TRCV_MBX_ENTER(mbxid, ppk_msg, tmout);
00302     CHECK_DISPATCH();
00303     ccb = T_CHECK_CLSID_CCB(mbxid);
00304     mbxid = remove_clsid(mbxid);
00305     CHECK_MBXID(ccb, mbxid);
00306     CHECK_TMOUT(tmout);
00307     mbxcb = get_mbxcb(ccb, mbxid);
00308 
00309   retry:
00310     T_ACQUIRE_LOCK(ccb->obj_lock);
00311     if (mbxcb->head != NULL) {
00312         *ppk_msg = mbxcb->head;
00313         mbxcb->head = (*ppk_msg)->next;
00314         RELEASE_LOCK(ccb->obj_lock);
00315         ercd = E_OK;
00316     }
00317     else if (tmout == TMO_POL) {
00318         RELEASE_LOCK(ccb->obj_lock);
00319         ercd = E_TMOUT;
00320     }
00321     else {
00322         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00323         wobj_make_wait_tmout(ccb, (WOBJCB *) mbxcb, (WINFO_WOBJ *) &winfo,
00324                         &tmevtb, tmout);
00325         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00326         RELEASE_LOCK(ccb->obj_lock);
00327         dispatch();
00328         ercd = winfo.winfo.wercd;
00329         if (ercd == E_OK) {
00330             *ppk_msg = winfo.pk_msg;
00331         }
00332     }
00333     t_unlock_cpu();
00334 
00335   exit:
00336     LOG_TRCV_MBX_LEAVE(ercd, *ppk_msg);
00337     return(ercd);
00338 }
00339 
00340 #endif /* __trcv_mbx */

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