dataqueue.c

説明を見る。
00001 /*
00002  *  TOPPERS/JSP Kernel
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      Just Standard Profile Kernel
00005  * 
00006  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
00007  *                              Toyohashi Univ. of Technology, JAPAN
00008  * 
00009  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
00010  *  によって公表されている GNU General Public License の Version 2 に記
00011  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
00012  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
00013  *  利用と呼ぶ)することを無償で許諾する.
00014  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00015  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00016  *      スコード中に含まれていること.
00017  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00018  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00019  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00020  *      の無保証規定を掲載すること.
00021  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00022  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00023  *      と.
00024  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00025  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00026  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00027  *        報告すること.
00028  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00029  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00030  * 
00031  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00032  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
00033  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
00034  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
00035  * 
00036  *  @(#) $Id: dataqueue.c,v 1.9 2003/06/04 01:46:16 hiro Exp $
00037  */
00038 
00039 /*
00040  *      データキュー機能
00041  */
00042 
00043 #include "jsp_kernel.h"
00044 #include "check.h"
00045 #include "task.h"
00046 #include "wait.h"
00047 #include "dataqueue.h"
00048 
00049 /*
00050  *  データキューIDの最大値(kernel_cfg.c)
00051  */
00052 extern const ID tmax_dtqid;
00053 
00054 /*
00055  *  データキュー初期化ブロックのエリア(kernel_cfg.c)
00056  */
00057 extern const DTQINIB    dtqinib_table[];
00058 
00059 /*
00060  *  データキューの数
00061  */
00062 #define TNUM_DTQ        ((UINT)(tmax_dtqid - TMIN_DTQID + 1))
00063 
00064 /*
00065  *  データキュー管理ブロックのエリア(kernel_cfg.c)
00066  */
00067 extern DTQCB    dtqcb_table[];
00068 
00069 /*
00070  *  データキューIDからデータキュー管理ブロックを取り出すためのマクロ
00071  */
00072 #define INDEX_DTQ(dtqid)        ((UINT)((dtqid) - TMIN_DTQID))
00073 #define get_dtqcb(dtqid)        (&(dtqcb_table[INDEX_DTQ(dtqid)]))
00074 
00075 /*
00076  *  データキュー待ち情報ブロックの定義
00077  *
00078  *  データキューへの送信待ちとデータキューからの受信待ちで,同じ待ち情
00079  *  報ブロックを使う.
00080  */
00081 typedef struct dataqueue_waiting_information {
00082         WINFO   winfo;          /* 標準の待ち情報ブロック */
00083         WOBJCB  *wobjcb;        /* 待ちオブジェクトの管理ブロック */
00084         VP_INT  data;           /* 送受信データ  */
00085 } WINFO_DTQ;
00086 
00087 /*
00088  *  データキュー機能の初期化
00089  */
00090 #ifdef __dtqini
00091 
00092 void
00093 dataqueue_initialize(void)
00094 {
00095         UINT    i;
00096         DTQCB   *dtqcb;
00097 
00098         for (dtqcb = dtqcb_table, i = 0; i < TNUM_DTQ; dtqcb++, i++) {
00099                 queue_initialize(&(dtqcb->swait_queue));
00100                 dtqcb->dtqinib = &(dtqinib_table[i]);
00101                 queue_initialize(&(dtqcb->rwait_queue));
00102                 dtqcb->count = 0;
00103                 dtqcb->head = 0;
00104                 dtqcb->tail = 0;
00105         }
00106 }
00107 
00108 #endif /* __dtqini */
00109 
00110 /*
00111  *  データキュー領域にデータを格納
00112  */
00113 #ifdef __dtqenq
00114 
00115 BOOL
00116 enqueue_data(DTQCB *dtqcb, VP_INT data)
00117 {
00118         if (dtqcb->count < dtqcb->dtqinib->dtqcnt) {
00119                 *((VP_INT *)(dtqcb->dtqinib->dtq) + dtqcb->tail) = data;
00120                 dtqcb->count++;
00121                 dtqcb->tail++;
00122                 if (dtqcb->tail >= dtqcb->dtqinib->dtqcnt) {
00123                         dtqcb->tail = 0;
00124                 }
00125                 return(TRUE);
00126         }
00127         return(FALSE);
00128 }
00129 
00130 #endif /* __dtqenq */
00131 
00132 /*
00133  *  データキュー領域にデータを強制格納
00134  */
00135 #ifdef __dtqfenq
00136 
00137 void
00138 force_enqueue_data(DTQCB *dtqcb, VP_INT data)
00139 {
00140         *((VP_INT *)(dtqcb->dtqinib->dtq) + dtqcb->tail) = data;
00141         dtqcb->tail++;
00142         if (dtqcb->tail >= dtqcb->dtqinib->dtqcnt) {
00143                 dtqcb->tail = 0;
00144         }
00145         if (dtqcb->count < dtqcb->dtqinib->dtqcnt) {
00146                 dtqcb->count++;
00147         }
00148         else {
00149                 dtqcb->head = dtqcb->tail;
00150         }
00151 }
00152 
00153 #endif /* __dtqfenq */
00154 
00155 /*
00156  *  データキュー領域からデータを取出し
00157  */
00158 #ifdef __dtqdeq
00159 
00160 BOOL
00161 dequeue_data(DTQCB *dtqcb, VP_INT *p_data)
00162 {
00163         if (dtqcb->count > 0) {
00164                 *p_data = *((VP_INT *)(dtqcb->dtqinib->dtq) + dtqcb->head);
00165                 dtqcb->count--;
00166                 dtqcb->head++;
00167                 if (dtqcb->head >= dtqcb->dtqinib->dtqcnt) {
00168                         dtqcb->head = 0;
00169                 }
00170                 return(TRUE);
00171         }
00172         return(FALSE);
00173 }
00174 
00175 #endif /* __dtqdeq */
00176 
00177 /*
00178  *  受信待ちキューの先頭タスクへのデータ送信
00179  */
00180 #ifdef __dtqsnd
00181 
00182 TCB *
00183 send_data_rwait(DTQCB *dtqcb, VP_INT data)
00184 {
00185         TCB     *tcb;
00186 
00187         if (!(queue_empty(&(dtqcb->rwait_queue)))) {
00188                 tcb = (TCB *) queue_delete_next(&(dtqcb->rwait_queue));
00189                 ((WINFO_DTQ *)(tcb->winfo))->data = data;
00190                 return(tcb);
00191         }
00192         return(NULL);
00193 }
00194 
00195 #endif /* __dtqsnd */
00196 
00197 /*
00198  *  送信待ちキューの先頭タスクからのデータ受信
00199  */
00200 #ifdef __dtqrcv
00201 
00202 TCB *
00203 receive_data_swait(DTQCB *dtqcb, VP_INT *p_data)
00204 {
00205         TCB     *tcb;
00206 
00207         if (!(queue_empty(&(dtqcb->swait_queue)))) {
00208                 tcb = (TCB *) queue_delete_next(&(dtqcb->swait_queue));
00209                 *p_data = ((WINFO_DTQ *)(tcb->winfo))->data;
00210                 return(tcb);
00211         }
00212         return(NULL);
00213 }
00214 
00215 #endif /* __dtqrcv */
00216 
00217 /*
00218  *  データキューへの送信
00219  */
00220 #ifdef __snd_dtq
00221 
00222 SYSCALL ER
00223 snd_dtq(ID dtqid, VP_INT data)
00224 {
00225         DTQCB   *dtqcb;
00226         WINFO_DTQ winfo;
00227         TCB     *tcb;
00228         ER      ercd;
00229 
00230         LOG_SND_DTQ_ENTER(dtqid, data);
00231         CHECK_DISPATCH();
00232         CHECK_DTQID(dtqid);
00233         dtqcb = get_dtqcb(dtqid);
00234 
00235         t_lock_cpu();
00236         if ((tcb = send_data_rwait(dtqcb, data)) != NULL) {
00237                 if (wait_complete(tcb)) {
00238                         dispatch();
00239                 }
00240                 ercd = E_OK;
00241         }
00242         else if (enqueue_data(dtqcb, data)) {
00243                 ercd = E_OK;
00244         }
00245         else {
00246                 winfo.data = data;
00247                 wobj_make_wait((WOBJCB *) dtqcb, (WINFO_WOBJ *) &winfo);
00248                 dispatch();
00249                 ercd = winfo.winfo.wercd;
00250         }
00251         t_unlock_cpu();
00252 
00253     exit:
00254         LOG_SND_DTQ_LEAVE(ercd);
00255         return(ercd);
00256 }
00257 
00258 #endif /* __snd_dtq */
00259 
00260 /*
00261  *  データキューへの送信(ポーリング)
00262  */
00263 #ifdef __psnd_dtq
00264 
00265 SYSCALL ER
00266 psnd_dtq(ID dtqid, VP_INT data)
00267 {
00268         DTQCB   *dtqcb;
00269         TCB     *tcb;
00270         ER      ercd;
00271 
00272         LOG_PSND_DTQ_ENTER(dtqid, data);
00273         CHECK_TSKCTX_UNL();
00274         CHECK_DTQID(dtqid);
00275         dtqcb = get_dtqcb(dtqid);
00276 
00277         t_lock_cpu();
00278         if ((tcb = send_data_rwait(dtqcb, data)) != NULL) {
00279                 if (wait_complete(tcb)) {
00280                         dispatch();
00281                 }
00282                 ercd = E_OK;
00283         }
00284         else if (enqueue_data(dtqcb, data)) {
00285                 ercd = E_OK;
00286         }
00287         else {
00288                 ercd = E_TMOUT;
00289         }
00290         t_unlock_cpu();
00291 
00292     exit:
00293         LOG_PSND_DTQ_LEAVE(ercd);
00294         return(ercd);
00295 }
00296 
00297 #endif /* __psnd_dtq */
00298 
00299 /*
00300  *  データキューへの送信(ポーリング,非タスクコンテキスト用)
00301  */
00302 #ifdef __ipsnd_dtq
00303 
00304 SYSCALL ER
00305 ipsnd_dtq(ID dtqid, VP_INT data)
00306 {
00307         DTQCB   *dtqcb;
00308         TCB     *tcb;
00309         ER      ercd;
00310 
00311         LOG_IPSND_DTQ_ENTER(dtqid, data);
00312         CHECK_INTCTX_UNL();
00313         CHECK_DTQID(dtqid);
00314         dtqcb = get_dtqcb(dtqid);
00315 
00316         i_lock_cpu();
00317         if ((tcb = send_data_rwait(dtqcb, data)) != NULL) {
00318                 if (wait_complete(tcb)) {
00319                         reqflg = TRUE;
00320                 }
00321                 ercd = E_OK;
00322         }
00323         else if (enqueue_data(dtqcb, data)) {
00324                 ercd = E_OK;
00325         }
00326         else {
00327                 ercd = E_TMOUT;
00328         }
00329         i_unlock_cpu();
00330 
00331     exit:
00332         LOG_IPSND_DTQ_LEAVE(ercd);
00333         return(ercd);
00334 }
00335 
00336 #endif /* __ipsnd_dtq */
00337 
00338 /*
00339  *  データキューへの送信(タイムアウトあり)
00340  */
00341 #ifdef __tsnd_dtq
00342 
00343 SYSCALL ER
00344 tsnd_dtq(ID dtqid, VP_INT data, TMO tmout)
00345 {
00346         DTQCB   *dtqcb;
00347         WINFO_DTQ winfo;
00348         TMEVTB  tmevtb;
00349         TCB     *tcb;
00350         ER      ercd;
00351 
00352         LOG_TSND_DTQ_ENTER(dtqid, data, tmout);
00353         CHECK_DISPATCH();
00354         CHECK_DTQID(dtqid);
00355         CHECK_TMOUT(tmout);
00356         dtqcb = get_dtqcb(dtqid);
00357 
00358         t_lock_cpu();
00359         if ((tcb = send_data_rwait(dtqcb, data)) != NULL) {
00360                 if (wait_complete(tcb)) {
00361                         dispatch();
00362                 }
00363                 ercd = E_OK;
00364         }
00365         else if (enqueue_data(dtqcb, data)) {
00366                 ercd = E_OK;
00367         }
00368         else if (tmout == TMO_POL) {
00369                 ercd = E_TMOUT;
00370         }
00371         else {
00372                 winfo.data = data;
00373                 wobj_make_wait_tmout((WOBJCB *) dtqcb, (WINFO_WOBJ *) &winfo,
00374                                                 &tmevtb, tmout);
00375                 dispatch();
00376                 ercd = winfo.winfo.wercd;
00377         }
00378         t_unlock_cpu();
00379 
00380     exit:
00381         LOG_TSND_DTQ_LEAVE(ercd);
00382         return(ercd);
00383 }
00384 
00385 #endif /* __tsnd_dtq */
00386 
00387 /*
00388  *  データキューへの強制送信
00389  */
00390 #ifdef __fsnd_dtq
00391 
00392 SYSCALL ER
00393 fsnd_dtq(ID dtqid, VP_INT data)
00394 {
00395         DTQCB   *dtqcb; 
00396         TCB     *tcb;
00397         ER      ercd;
00398 
00399         LOG_FSND_DTQ_ENTER(dtqid, data);
00400         CHECK_TSKCTX_UNL();
00401         CHECK_DTQID(dtqid);
00402         dtqcb = get_dtqcb(dtqid);
00403         CHECK_ILUSE(dtqcb->dtqinib->dtqcnt > 0);
00404 
00405         t_lock_cpu();
00406         if ((tcb = send_data_rwait(dtqcb, data)) != NULL) {
00407                 if (wait_complete(tcb)) {
00408                         dispatch();
00409                 }
00410         }
00411         else {
00412                 force_enqueue_data(dtqcb, data);
00413         }
00414         ercd = E_OK;
00415         t_unlock_cpu();
00416 
00417     exit:
00418         LOG_FSND_DTQ_LEAVE(ercd);
00419         return(ercd);
00420 }
00421 
00422 #endif /* __fsnd_dtq */
00423 
00424 /*
00425  *  データキューへの強制送信(非タスクコンテキスト用)
00426  */
00427 #ifdef __ifsnd_dtq
00428 
00429 SYSCALL ER
00430 ifsnd_dtq(ID dtqid, VP_INT data)
00431 {
00432         DTQCB   *dtqcb;
00433         TCB     *tcb;
00434         ER      ercd;
00435 
00436         LOG_IFSND_DTQ_ENTER(dtqid, data);
00437         CHECK_INTCTX_UNL();
00438         CHECK_DTQID(dtqid);
00439         dtqcb = get_dtqcb(dtqid);
00440         CHECK_ILUSE(dtqcb->dtqinib->dtqcnt > 0);
00441 
00442         i_lock_cpu();
00443         if ((tcb = send_data_rwait(dtqcb, data)) != NULL) {
00444                 if (wait_complete(tcb)) {
00445                         reqflg = TRUE;
00446                 }
00447         }
00448         else {
00449                 force_enqueue_data(dtqcb, data);
00450         }
00451         ercd = E_OK;
00452         i_unlock_cpu();
00453 
00454     exit:
00455         LOG_IFSND_DTQ_LEAVE(ercd);
00456         return(ercd);
00457 }
00458 
00459 #endif /* __ifsnd_dtq */
00460 
00461 /*
00462  *  データキューからの受信
00463  */
00464 #ifdef __rcv_dtq
00465 
00466 SYSCALL ER
00467 rcv_dtq(ID dtqid, VP_INT *p_data)
00468 {
00469         DTQCB   *dtqcb;
00470         WINFO_DTQ winfo;
00471         TCB     *tcb;
00472         VP_INT  data;
00473         ER      ercd;
00474 
00475         LOG_RCV_DTQ_ENTER(dtqid, p_data);
00476         CHECK_DISPATCH();
00477         CHECK_DTQID(dtqid);
00478         dtqcb = get_dtqcb(dtqid);
00479 
00480         t_lock_cpu();
00481         if (dequeue_data(dtqcb, p_data)) {
00482                 if ((tcb = receive_data_swait(dtqcb, &data)) != NULL) {
00483                         enqueue_data(dtqcb, data);
00484                         if (wait_complete(tcb)) {
00485                                 dispatch();
00486                         }
00487                 }
00488                 ercd = E_OK;
00489         }
00490         else if ((tcb = receive_data_swait(dtqcb, p_data)) != NULL) {
00491                 if (wait_complete(tcb)) {
00492                         dispatch();
00493                 }
00494                 ercd = E_OK;
00495         }
00496         else {
00497                 runtsk->tstat = (TS_WAITING | TS_WAIT_WOBJ);
00498                 make_wait(&(winfo.winfo));
00499                 queue_insert_prev(&(dtqcb->rwait_queue),
00500                                         &(runtsk->task_queue));
00501                 winfo.wobjcb = (WOBJCB *) dtqcb;
00502                 LOG_TSKSTAT(runtsk);
00503                 dispatch();
00504                 ercd = winfo.winfo.wercd;
00505                 if (ercd == E_OK) {
00506                         *p_data = winfo.data;
00507                 }
00508         }
00509         t_unlock_cpu();
00510 
00511     exit:
00512         LOG_RCV_DTQ_LEAVE(ercd, *p_data);
00513         return(ercd);
00514 }
00515 
00516 #endif /* __rcv_dtq */
00517 
00518 /*
00519  *  データキューからの受信(ポーリング)
00520  */
00521 #ifdef __prcv_dtq
00522 
00523 SYSCALL ER
00524 prcv_dtq(ID dtqid, VP_INT *p_data)
00525 {
00526         DTQCB   *dtqcb;
00527         TCB     *tcb;
00528         VP_INT  data;
00529         ER      ercd;
00530 
00531         LOG_PRCV_DTQ_ENTER(dtqid, p_data);
00532         CHECK_TSKCTX_UNL();
00533         CHECK_DTQID(dtqid);
00534         dtqcb = get_dtqcb(dtqid);
00535 
00536         t_lock_cpu();
00537         if (dequeue_data(dtqcb, p_data)) {
00538                 if ((tcb = receive_data_swait(dtqcb, &data)) != NULL) {
00539                         enqueue_data(dtqcb, data);
00540                         if (wait_complete(tcb)) {
00541                                 dispatch();
00542                         }
00543                 }
00544                 ercd = E_OK;
00545         }
00546         else if ((tcb = receive_data_swait(dtqcb, p_data)) != NULL) {
00547                 if (wait_complete(tcb)) {
00548                         dispatch();
00549                 }
00550                 ercd = E_OK;
00551         }
00552         else {
00553                 ercd = E_TMOUT;
00554         }
00555         t_unlock_cpu();
00556 
00557     exit:
00558         LOG_PRCV_DTQ_LEAVE(ercd, *p_data);
00559         return(ercd);
00560 }
00561 
00562 #endif /* __prcv_dtq */
00563 
00564 /*
00565  *  データキューからの受信(タイムアウトあり)
00566  */
00567 #ifdef __trcv_dtq
00568 
00569 SYSCALL ER
00570 trcv_dtq(ID dtqid, VP_INT *p_data, TMO tmout)
00571 {
00572         DTQCB   *dtqcb;
00573         WINFO_DTQ winfo;
00574         TMEVTB  tmevtb;
00575         TCB     *tcb;
00576         VP_INT  data;
00577         ER      ercd;
00578 
00579         LOG_TRCV_DTQ_ENTER(dtqid, p_data, tmout);
00580         CHECK_DISPATCH();
00581         CHECK_DTQID(dtqid);
00582         CHECK_TMOUT(tmout);
00583         dtqcb = get_dtqcb(dtqid);
00584 
00585         t_lock_cpu();
00586         if (dequeue_data(dtqcb, p_data)) {
00587                 if ((tcb = receive_data_swait(dtqcb, &data)) != NULL) {
00588                         enqueue_data(dtqcb, data);
00589                         if (wait_complete(tcb)) {
00590                                 dispatch();
00591                         }
00592                 }
00593                 ercd = E_OK;
00594         }
00595         else if ((tcb = receive_data_swait(dtqcb, p_data)) != NULL) {
00596                 if (wait_complete(tcb)) {
00597                         dispatch();
00598                 }
00599                 ercd = E_OK;
00600         }
00601         else if (tmout == TMO_POL) {
00602                 ercd = E_TMOUT;
00603         }
00604         else {
00605                 runtsk->tstat = (TS_WAITING | TS_WAIT_WOBJ);
00606                 make_wait_tmout(&(winfo.winfo), &tmevtb, tmout);
00607                 queue_insert_prev(&(dtqcb->rwait_queue),
00608                                         &(runtsk->task_queue));
00609                 winfo.wobjcb = (WOBJCB *) dtqcb;
00610                 LOG_TSKSTAT(runtsk);
00611                 dispatch();
00612                 ercd = winfo.winfo.wercd;
00613                 if (ercd == E_OK) {
00614                         *p_data = winfo.data;
00615                 }
00616         }
00617         t_unlock_cpu();
00618 
00619     exit:
00620         LOG_TRCV_DTQ_LEAVE(ercd, *p_data);
00621         return(ercd);
00622 }
00623 
00624 #endif /* __trcv_dtq */
00625 

Copyright © 2006 by TAKAGI Nobuhisa.
Copyright © 2006 by Kijineko Inc..
このページは Mon Dec 18 17:18:39 2006 に Doxygen によって生成されました。
データ入力からプログラム開発まで!様々なスキルを持ったメンバーが登録しています【@SOHO】