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