gonzui


Format: Advanced Search

tkernel_2/kernel/tkernel/src/rendezvous.cbare sourcepermlink (0.09 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by T-Engine Forum at 2012/10/24.
   11:  *    Modified by T-Engine Forum at 2014/09/10.
   12:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   13:  *
   14:  *----------------------------------------------------------------------
   15:  */
   16: 
   17: /*
   18:  *      rendezvous.c (T-Kernel/OS)
   19:  *      Rendezvous
   20:  */
   21: 
   22: #include "kernel.h"
   23: #include "task.h"
   24: #include "wait.h"
   25: #include "check.h"
   26: #include <sys/rominfo.h>
   27: 
   28: #ifdef NUM_PORID
   29: 
   30: EXPORT ID       max_porid;    /* Maximum rendezvous port ID */
   31: 
   32: /*
   33:  * Rendezvous port control block
   34:  */
   35: typedef struct port_control_block {
   36:         QUEUE  call_queue;      /* Port call wait queue */
   37:         ID     porid;              /* Port ID */
   38:         void   *exinf;           /* Extended information */
   39:         ATR    poratr;            /* Port attribute */
   40:         QUEUE  accept_queue;    /* Port accept wait queue */
   41:         INT    maxcmsz;   /* Maximum length of call message */
   42:         INT    maxrmsz;   /* Maximum length of reply message */
   43: #if USE_OBJECT_NAME
   44:         UB     name[OBJECT_NAME_LENGTH];   /* name */
   45: #endif
   46: } PORCB;
   47: 
   48: LOCAL PORCB     *porcb_table;       /* Rendezvous port control block */
   49: LOCAL QUEUE     free_porcb; /* FreeQue */
   50: 
   51: #define get_porcb(id)   ( &porcb_table[INDEX_POR(id)] )
   52: 
   53: 
   54: /*
   55:  * Initialization of port control block
   56:  */
   57: EXPORT ER rendezvous_initialize( void )
   58: {
   59:         PORCB  *porcb, *end;
   60:         W      n;
   61: 
   62:         /* Get system information */
   63:         n = _tk_get_cfn(SCTAG_TMAXPORID, &max_porid, 1);
   64:         if ( n < 1 || NUM_PORID < 1 ) {
   65:                 return E_SYS;
   66:         }
   67: 
   68:         /* Create port control block */
   69:         porcb_table = Imalloc((UINT)NUM_PORID * sizeof(PORCB));
   70:         if ( porcb_table == NULL ) {
   71:                 return E_NOMEM;
   72:         }
   73: 
   74:         /* Register all control blocks onto FreeQue */
   75:         QueInit(&free_porcb);
   76:         end = porcb_table + NUM_PORID;
   77:         for ( porcb = porcb_table; porcb < end; porcb++ ) {
   78:                 porcb->porid = 0;
   79:                 QueInsert(&porcb->call_queue, &free_porcb);
   80:         }
   81: 
   82:         return E_OK;
   83: }
   84: 
   85: 
   86: #define RDVNO_SHIFT     16
   87: 
   88: /*
   89:  * Create rendezvous number
   90:  */
   91: Inline RNO gen_rdvno( TCB *tcb )
   92: {
   93:         RNO    rdvno;
   94: 
   95:         rdvno = tcb->wrdvno;
   96:         tcb->wrdvno += (1 << RDVNO_SHIFT);
   97: 
   98:         return rdvno;
   99: }
  100: 
  101: /*
  102:  * Get task ID from rendezvous number
  103:  */
  104: Inline ID get_tskid_rdvno( RNO rdvno )
  105: {
  106:         return (ID)((UINT)rdvno & ((1 << RDVNO_SHIFT) - 1));
  107: }
  108: 
  109: /*
  110:  * Check validity of rendezvous number
  111:  */
  112: #define CHECK_RDVNO(rdvno) {                                    \
  113:         if ( !CHK_TSKID(get_tskid_rdvno(rdvno)) ) {            \
  114:                 return E_OBJ;                                 \
  115:         }                                                      \
  116: }
  117: 
  118: 
  119: /*
  120:  * Processing if the priority of send wait task changes
  121:  */
  122: LOCAL void cal_chg_pri( TCB *tcb, INT oldpri )
  123: {
  124:         PORCB  *porcb;
  125: 
  126:         porcb = get_porcb(tcb->wid);
  127:         gcb_change_priority((GCB*)porcb, tcb);
  128: }
  129: 
  130: /*
  131:  * Definition of rendezvous wait specification
  132:  */
  133: LOCAL CONST WSPEC wspec_cal_tfifo = { TTW_CAL, NULL, NULL };
  134: LOCAL CONST WSPEC wspec_cal_tpri  = { TTW_CAL, cal_chg_pri, NULL };
  135: LOCAL CONST WSPEC wspec_acp       = { TTW_ACP, NULL, NULL };
  136: LOCAL CONST WSPEC wspec_rdv       = { TTW_RDV, NULL, NULL };
  137: 
  138: 
  139: /*
  140:  * Create rendezvous port
  141:  */
  142: SYSCALL ID _tk_cre_por( CONST T_CPOR *pk_cpor )
  143: {
  144: #if CHK_RSATR
  145:         const ATR VALID_PORATR = {
  146:                  TA_TPRI
  147:                 |TA_NODISWAI
  148: #if USE_OBJECT_NAME
  149:                 |TA_DSNAME
  150: #endif
  151:         };
  152: #endif
  153:         PORCB  *porcb;
  154:         ID     porid;
  155:         ER     ercd;
  156: 
  157:         CHECK_RSATR(pk_cpor->poratr, VALID_PORATR);
  158:         CHECK_PAR(pk_cpor->maxcmsz >= 0);
  159:         CHECK_PAR(pk_cpor->maxrmsz >= 0);
  160:         CHECK_INTSK();
  161: 
  162:         BEGIN_CRITICAL_SECTION;
  163:         /* Get control block from FreeQue */
  164:         porcb = (PORCB*)QueRemoveNext(&free_porcb);
  165:         if ( porcb == NULL ) {
  166:                 ercd = E_LIMIT;
  167:         } else {
  168:                 porid = ID_POR(porcb - porcb_table);
  169: 
  170:                 /* Initialize control block */
  171:                 QueInit(&porcb->call_queue);
  172:                 porcb->porid = porid;
  173:                 porcb->exinf = pk_cpor->exinf;
  174:                 porcb->poratr = pk_cpor->poratr;
  175:                 QueInit(&porcb->accept_queue);
  176:                 porcb->maxcmsz = pk_cpor->maxcmsz;
  177:                 porcb->maxrmsz = pk_cpor->maxrmsz;
  178: #if USE_OBJECT_NAME
  179:                 if ( (pk_cpor->poratr & TA_DSNAME) != 0 ) {
  180:                         STRNCPY((char*)porcb->name, (char*)pk_cpor->dsname,
  181:                                 OBJECT_NAME_LENGTH);
  182:                 }
  183: #endif
  184:                 ercd = porid;
  185:         }
  186:         END_CRITICAL_SECTION;
  187: 
  188:         return ercd;
  189: }
  190: 
  191: /*
  192:  * Delete rendezvous port
  193:  */
  194: SYSCALL ER _tk_del_por( ID porid )
  195: {
  196:         PORCB  *porcb;
  197:         ER     ercd = E_OK;
  198: 
  199:         CHECK_PORID(porid);
  200:         CHECK_INTSK();
  201: 
  202:         porcb = get_porcb(porid);
  203: 
  204:         BEGIN_CRITICAL_SECTION;
  205:         if ( porcb->porid == 0 ) {
  206:                 ercd = E_NOEXS;
  207:         } else {
  208:                 /* Release wait state of task (E_DLT) */
  209:                 wait_delete(&porcb->call_queue);
  210:                 wait_delete(&porcb->accept_queue);
  211: 
  212:                 /* Return to FreeQue */
  213:                 QueInsert(&porcb->call_queue, &free_porcb);
  214:                 porcb->porid = 0;
  215:         }
  216:         END_CRITICAL_SECTION;
  217: 
  218:         return ercd;
  219: }
  220: 
  221: /*
  222:  * Call rendezvous
  223:  */
  224: SYSCALL INT _tk_cal_por( ID porid, UINT calptn, void *msg, INT cmsgsz, TMO tmout )
  225: {
  226:         return _tk_cal_por_u(porid, calptn, msg, cmsgsz, to_usec_tmo(tmout));
  227: }
  228: 
  229: SYSCALL INT _tk_cal_por_u( ID porid, UINT calptn, void *msg, INT cmsgsz, TMO_U tmout )
  230: {
  231:         PORCB  *porcb;
  232:         TCB    *tcb;
  233:         QUEUE  *queue;
  234:         RNO    rdvno;
  235:         INT    rmsgsz;
  236:         ER     ercd = E_OK;
  237: 
  238:         CHECK_PORID(porid);
  239:         CHECK_PAR(calptn != 0);
  240:         CHECK_PAR(cmsgsz >= 0);
  241:         CHECK_TMOUT(tmout);
  242:         CHECK_DISPATCH();
  243: 
  244:         porcb = get_porcb(porid);
  245: 
  246:         BEGIN_CRITICAL_SECTION;
  247:         if ( porcb->porid == 0 ) {
  248:                 ercd = E_NOEXS;
  249:                 goto error_exit;
  250:         }
  251: #if CHK_PAR
  252:         if ( cmsgsz > porcb->maxcmsz ) {
  253:                 ercd = E_PAR;
  254:                 goto error_exit;
  255:         }
  256: #endif
  257: 
  258:         /* Search accept wait task */
  259:         queue = porcb->accept_queue.next;
  260:         while ( queue != &porcb->accept_queue ) {
  261:                 tcb = (TCB*)queue;
  262:                 queue = queue->next;
  263:                 if ( (calptn & tcb->winfo.acp.acpptn) == 0 ) {
  264:                         continue;
  265:                 }
  266: 
  267:                 /* Check rendezvous call wait disable */
  268:                 if ( is_diswai((GCB*)porcb, ctxtsk, TTW_CAL) ) {
  269:                         ercd = E_DISWAI;
  270:                         goto error_exit;
  271:                 }
  272: 
  273:                 /* Send message */
  274:                 rdvno = gen_rdvno(ctxtsk);
  275:                 if ( cmsgsz > 0 ) {
  276:                         MEMCPY(tcb->winfo.acp.msg, msg, (UINT)cmsgsz);
  277:                 }
  278:                 *tcb->winfo.acp.p_rdvno = rdvno;
  279:                 *tcb->winfo.acp.p_cmsgsz = cmsgsz;
  280:                 wait_release_ok(tcb);
  281: 
  282:                 /* Check rendezvous end wait disable */
  283:                 if ( is_diswai((GCB*)porcb, ctxtsk, TTW_RDV) ) {
  284:                         ercd = E_DISWAI;
  285:                         goto error_exit;
  286:                 }
  287: 
  288:                 /* Ready for rendezvous end wait */
  289:                 ercd = E_TMOUT;
  290:                 ctxtsk->wspec = &wspec_rdv;
  291:                 ctxtsk->wid = 0;
  292:                 ctxtsk->wercd = &ercd;
  293:                 ctxtsk->winfo.rdv.rdvno = rdvno;
  294:                 ctxtsk->winfo.rdv.msg = msg;
  295:                 ctxtsk->winfo.rdv.maxrmsz = porcb->maxrmsz;
  296:                 ctxtsk->winfo.rdv.p_rmsgsz = &rmsgsz;
  297:                 make_wait(TMO_FEVR, porcb->poratr);
  298:                 QueInit(&ctxtsk->tskque);
  299: 
  300:                 goto error_exit;
  301:         }
  302: 
  303:         /* Ready for rendezvous call wait */
  304:         ctxtsk->wspec = ( (porcb->poratr & TA_TPRI) != 0 )?
  305:                                         &wspec_cal_tpri: &wspec_cal_tfifo;
  306:         ctxtsk->wercd = &ercd;
  307:         ctxtsk->winfo.cal.calptn = calptn;
  308:         ctxtsk->winfo.cal.msg = msg;
  309:         ctxtsk->winfo.cal.cmsgsz = cmsgsz;
  310:         ctxtsk->winfo.cal.p_rmsgsz = &rmsgsz;
  311:         gcb_make_wait_with_diswai((GCB*)porcb, tmout);
  312: 
  313:     error_exit:
  314:         END_CRITICAL_SECTION;
  315: 
  316:         return ( ercd < E_OK )? ercd: rmsgsz;
  317: }
  318: 
  319: /*
  320:  * Accept rendezvous
  321:  */
  322: SYSCALL INT _tk_acp_por( ID porid, UINT acpptn, RNO *p_rdvno, void *msg, TMO tmout )
  323: {
  324:         return _tk_acp_por_u(porid, acpptn, p_rdvno, msg, to_usec_tmo(tmout));
  325: }
  326: 
  327: SYSCALL INT _tk_acp_por_u( ID porid, UINT acpptn, RNO *p_rdvno, void *msg, TMO_U tmout )
  328: {
  329:         PORCB  *porcb;
  330:         TCB    *tcb;
  331:         QUEUE  *queue;
  332:         RNO    rdvno;
  333:         INT    cmsgsz;
  334:         ER     ercd = E_OK;
  335: 
  336:         CHECK_PORID(porid);
  337:         CHECK_PAR(acpptn != 0);
  338:         CHECK_TMOUT(tmout);
  339:         CHECK_DISPATCH();
  340: 
  341:         porcb = get_porcb(porid);
  342:  
  343:         BEGIN_CRITICAL_SECTION;
  344:         if ( porcb->porid == 0 ) {
  345:                 ercd = E_NOEXS;
  346:                 goto error_exit;
  347:         }
  348: 
  349:         /* Search call wait task */
  350:         queue = porcb->call_queue.next;
  351:         while ( queue != &porcb->call_queue ) {
  352:                 tcb = (TCB*)queue;
  353:                 queue = queue->next;
  354:                 if ( (acpptn & tcb->winfo.cal.calptn) == 0 ) {
  355:                         continue;
  356:                 }
  357: 
  358:                 /* Check rendezvous accept wait disable */
  359:                 if ( is_diswai((GCB*)porcb, ctxtsk, TTW_ACP) ) {
  360:                         ercd = E_DISWAI;
  361:                         goto error_exit;
  362:                 }
  363: 
  364:                 /* Receive message */
  365:                 *p_rdvno = rdvno = gen_rdvno(tcb);
  366:                 cmsgsz = tcb->winfo.cal.cmsgsz;
  367:                 if ( cmsgsz > 0 ) {
  368:                         MEMCPY(msg, tcb->winfo.cal.msg, (UINT)cmsgsz);
  369:                 }
  370: 
  371:                 /* Check rendezvous end wait disable */
  372:                 if ( is_diswai((GCB*)porcb, tcb, TTW_RDV) ) {
  373:                         wait_release_ng(tcb, E_DISWAI);
  374:                         goto error_exit;
  375:                 }
  376:                 wait_cancel(tcb);
  377: 
  378:                 /* Make the other task at rendezvous end wait state */
  379:                 tcb->wspec = &wspec_rdv;
  380:                 tcb->wid = 0;
  381:                 tcb->winfo.rdv.rdvno = rdvno;
  382:                 tcb->winfo.rdv.msg = tcb->winfo.cal.msg;
  383:                 tcb->winfo.rdv.maxrmsz = porcb->maxrmsz;
  384:                 tcb->winfo.rdv.p_rmsgsz = tcb->winfo.cal.p_rmsgsz;
  385:                 timer_insert(&tcb->wtmeb, TMO_FEVR,
  386:                                         (CBACK)wait_release_tmout, tcb);
  387:                 QueInit(&tcb->tskque);
  388: 
  389:                 goto error_exit;
  390:         }
  391: 
  392:         /* Check rendezvous accept wait disable */
  393:         if ( is_diswai((GCB*)porcb, ctxtsk, TTW_ACP) ) {
  394:                 ercd = E_DISWAI;
  395:                 goto error_exit;
  396:         }
  397: 
  398:         ercd = E_TMOUT;
  399:         if ( tmout != TMO_POL ) {
  400:                 /* Ready for rendezvous accept wait */
  401:                 ctxtsk->wspec = &wspec_acp;
  402:                 ctxtsk->wid = porid;
  403:                 ctxtsk->wercd = &ercd;
  404:                 ctxtsk->winfo.acp.acpptn = acpptn;
  405:                 ctxtsk->winfo.acp.msg = msg;
  406:                 ctxtsk->winfo.acp.p_rdvno = p_rdvno;
  407:                 ctxtsk->winfo.acp.p_cmsgsz = &cmsgsz;
  408:                 make_wait(tmout, porcb->poratr);
  409:                 QueInsert(&ctxtsk->tskque, &porcb->accept_queue);
  410:         }
  411: 
  412:     error_exit:
  413:         END_CRITICAL_SECTION;
  414: 
  415:         return ( ercd < E_OK )? ercd: cmsgsz;
  416: }
  417: 
  418: /*
  419:  * Forward Rendezvous to Other Port
  420:  */
  421: SYSCALL ER _tk_fwd_por( ID porid, UINT calptn, RNO rdvno, CONST void *msg, INT cmsgsz )
  422: {
  423:         PORCB  *porcb;
  424:         TCB    *caltcb, *tcb;
  425:         QUEUE  *queue;
  426:         RNO    new_rdvno;
  427:         ER     ercd = E_OK;
  428: 
  429:         CHECK_PORID(porid);
  430:         CHECK_PAR(calptn != 0);
  431:         CHECK_RDVNO(rdvno);
  432:         CHECK_PAR(cmsgsz >= 0);
  433:         CHECK_INTSK();
  434: 
  435:         porcb = get_porcb(porid);
  436:         caltcb = get_tcb(get_tskid_rdvno(rdvno));
  437: 
  438:         BEGIN_CRITICAL_SECTION;
  439:         if ( porcb->porid == 0 ) {
  440:                 ercd = E_NOEXS;
  441:                 goto error_exit;
  442:         }
  443: #if CHK_PAR
  444:         if ( cmsgsz > porcb->maxcmsz ) {
  445:                 ercd = E_PAR;
  446:                 goto error_exit;
  447:         }
  448: #endif
  449:         if ( (caltcb->state & TS_WAIT) == 0
  450:           || caltcb->wspec != &wspec_rdv
  451:           || rdvno != caltcb->winfo.rdv.rdvno ) {
  452:                 ercd = E_OBJ;
  453:                 goto error_exit;
  454:         }
  455:         if ( porcb->maxrmsz > caltcb->winfo.rdv.maxrmsz ) {
  456:                 ercd = E_OBJ;
  457:                 goto error_exit;
  458:         }
  459: #if CHK_PAR
  460:         if ( cmsgsz > caltcb->winfo.rdv.maxrmsz ) {
  461:                 ercd = E_PAR;
  462:                 goto error_exit;
  463:         }
  464: #endif
  465: 
  466:         /* Search accept wait task */
  467:         queue = porcb->accept_queue.next;
  468:         while ( queue != &porcb->accept_queue ) {
  469:                 tcb = (TCB*)queue;
  470:                 queue = queue->next;
  471:                 if ( (calptn & tcb->winfo.acp.acpptn) == 0 ) {
  472:                         continue;
  473:                 }
  474: 
  475:                 /* Check rendezvous accept wait disable */
  476:                 if ( is_diswai((GCB*)porcb, caltcb, TTW_CAL) ) {
  477:                         wait_release_ng(caltcb, E_DISWAI);
  478:                         ercd = E_DISWAI;
  479:                         goto error_exit;
  480:                 }
  481: 
  482:                 /* Send message */
  483:                 new_rdvno = gen_rdvno(caltcb);
  484:                 if ( cmsgsz > 0 ) {
  485:                         MEMCPY(tcb->winfo.acp.msg, msg, (UINT)cmsgsz);
  486:                 }
  487:                 *tcb->winfo.acp.p_rdvno = new_rdvno;
  488:                 *tcb->winfo.acp.p_cmsgsz = cmsgsz;
  489:                 wait_release_ok(tcb);
  490: 
  491:                 /* Check rendezvous end wait disable */
  492:                 if ( is_diswai((GCB*)porcb, caltcb, TTW_RDV) ) {
  493:                         wait_release_ng(caltcb, E_DISWAI);
  494:                         ercd = E_DISWAI;
  495:                         goto error_exit;
  496:                 }
  497: 
  498:                 /* Change rendezvous end wait of the other task */
  499:                 caltcb->winfo.rdv.rdvno = new_rdvno;
  500:                 caltcb->winfo.rdv.msg = caltcb->winfo.cal.msg;
  501:                 caltcb->winfo.rdv.maxrmsz = porcb->maxrmsz;
  502:                 caltcb->winfo.rdv.p_rmsgsz = caltcb->winfo.cal.p_rmsgsz;
  503:                 caltcb->nodiswai = ( (porcb->poratr & TA_NODISWAI) != 0 )? TRUE: FALSE;
  504:                 goto error_exit;
  505:         }
  506: 
  507:         /* Check rendezvous accept wait disable */
  508:         if ( is_diswai((GCB*)porcb, caltcb, TTW_CAL) ) {
  509:                 wait_release_ng(caltcb, E_DISWAI);
  510:                 ercd = E_DISWAI;
  511:                 goto error_exit;
  512:         }
  513: 
  514:         /* Change the other task to rendezvous call wait */
  515:         caltcb->wspec = ( (porcb->poratr & TA_TPRI) != 0 )?
  516:                                 &wspec_cal_tpri: &wspec_cal_tfifo;
  517:         caltcb->wid = porid;
  518:         caltcb->winfo.cal.calptn = calptn;
  519:         caltcb->winfo.cal.msg = caltcb->winfo.rdv.msg;
  520:         caltcb->winfo.cal.cmsgsz = cmsgsz;
  521:         caltcb->winfo.cal.p_rmsgsz = caltcb->winfo.rdv.p_rmsgsz;
  522:         caltcb->nodiswai = ( (porcb->poratr & TA_NODISWAI) != 0 )? TRUE: FALSE;
  523:         timer_insert(&caltcb->wtmeb, TMO_FEVR,
  524:                         (CBACK)wait_release_tmout, caltcb);
  525:         if ( (porcb->poratr & TA_TPRI) != 0 ) {
  526:                 queue_insert_tpri(caltcb, &porcb->call_queue);
  527:         } else {
  528:                 QueInsert(&caltcb->tskque, &porcb->call_queue);
  529:         }
  530: 
  531:         if ( cmsgsz > 0 ) {
  532:                 MEMCPY(caltcb->winfo.cal.msg, msg, (UINT)cmsgsz);
  533:         }
  534: 
  535:     error_exit:
  536:         END_CRITICAL_SECTION;
  537: 
  538:         return ercd;
  539: }
  540: 
  541: /*
  542:  * Reply rendezvous
  543:  */
  544: SYSCALL ER _tk_rpl_rdv( RNO rdvno, CONST void *msg, INT rmsgsz )
  545: {
  546:         TCB    *caltcb;
  547:         ER     ercd = E_OK;
  548: 
  549:         CHECK_RDVNO(rdvno);
  550:         CHECK_PAR(rmsgsz >= 0);
  551:         CHECK_INTSK();
  552: 
  553:         caltcb = get_tcb(get_tskid_rdvno(rdvno));
  554: 
  555:         BEGIN_CRITICAL_SECTION;
  556:         if ( (caltcb->state & TS_WAIT) == 0
  557:           || caltcb->wspec != &wspec_rdv
  558:           || rdvno != caltcb->winfo.rdv.rdvno ) {
  559:                 ercd = E_OBJ;
  560:                 goto error_exit;
  561:         }
  562: #if CHK_PAR
  563:         if ( rmsgsz > caltcb->winfo.rdv.maxrmsz ) {
  564:                 ercd = E_PAR;
  565:                 goto error_exit;
  566:         }
  567: #endif
  568: 
  569:         /* Send message */
  570:         if ( rmsgsz > 0 ) {
  571:                 MEMCPY(caltcb->winfo.rdv.msg, msg, (UINT)rmsgsz);
  572:         }
  573:         *caltcb->winfo.rdv.p_rmsgsz = rmsgsz;
  574:         wait_release_ok(caltcb);
  575: 
  576:     error_exit:
  577:         END_CRITICAL_SECTION;
  578: 
  579:         return ercd;
  580: }
  581: 
  582: /*
  583:  * Refer rendezvous port
  584:  */
  585: SYSCALL ER _tk_ref_por( ID porid, T_RPOR *pk_rpor )
  586: {
  587:         PORCB  *porcb;
  588:         ER     ercd = E_OK;
  589: 
  590:         CHECK_PORID(porid);
  591: 
  592:         porcb = get_porcb(porid);
  593: 
  594:         BEGIN_CRITICAL_SECTION;
  595:         if ( porcb->porid == 0 ) {
  596:                 ercd = E_NOEXS;
  597:         } else {
  598:                 pk_rpor->exinf = porcb->exinf;
  599:                 pk_rpor->wtsk = wait_tskid(&porcb->call_queue);
  600:                 pk_rpor->atsk = wait_tskid(&porcb->accept_queue);
  601:                 pk_rpor->maxcmsz = porcb->maxcmsz;
  602:                 pk_rpor->maxrmsz = porcb->maxrmsz;
  603:         }
  604:         END_CRITICAL_SECTION;
  605: 
  606:         return ercd;
  607: }
  608: 
  609: /* ------------------------------------------------------------------------ */
  610: /*
  611:  *      Debugger support function
  612:  */
  613: #if USE_DBGSPT
  614: 
  615: /*
  616:  * Get object name from control block
  617:  */
  618: #if USE_OBJECT_NAME
  619: EXPORT ER rendezvous_getname(ID id, UB **name)
  620: {
  621:         PORCB  *porcb;
  622:         ER     ercd = E_OK;
  623: 
  624:         CHECK_PORID(id);
  625: 
  626:         BEGIN_DISABLE_INTERRUPT;
  627:         porcb = get_porcb(id);
  628:         if ( porcb->porid == 0 ) {
  629:                 ercd = E_NOEXS;
  630:                 goto error_exit;
  631:         }
  632:         if ( (porcb->poratr & TA_DSNAME) == 0 ) {
  633:                 ercd = E_OBJ;
  634:                 goto error_exit;
  635:         }
  636:         *name = porcb->name;
  637: 
  638:     error_exit:
  639:         END_DISABLE_INTERRUPT;
  640: 
  641:         return ercd;
  642: }
  643: #endif /* USE_OBJECT_NAME */
  644: 
  645: /*
  646:  * Refer rendezvous port usage state
  647:  */
  648: SYSCALL INT _td_lst_por( ID list[], INT nent )
  649: {
  650:         PORCB  *porcb, *end;
  651:         INT    n = 0;
  652: 
  653:         BEGIN_DISABLE_INTERRUPT;
  654:         end = porcb_table + NUM_PORID;
  655:         for ( porcb = porcb_table; porcb < end; porcb++ ) {
  656:                 if ( porcb->porid == 0 ) {
  657:                         continue;
  658:                 }
  659: 
  660:                 if ( n++ < nent ) {
  661:                         *list++ = porcb->porid;
  662:                 }
  663:         }
  664:         END_DISABLE_INTERRUPT;
  665: 
  666:         return n;
  667: }
  668: 
  669: /*
  670:  * Refer rendezvous port
  671:  */
  672: SYSCALL ER _td_ref_por( ID porid, TD_RPOR *pk_rpor )
  673: {
  674:         PORCB  *porcb;
  675:         ER     ercd = E_OK;
  676: 
  677:         CHECK_PORID(porid);
  678: 
  679:         porcb = get_porcb(porid);
  680: 
  681:         BEGIN_DISABLE_INTERRUPT;
  682:         if ( porcb->porid == 0 ) {
  683:                 ercd = E_NOEXS;
  684:         } else {
  685:                 pk_rpor->exinf = porcb->exinf;
  686:                 pk_rpor->wtsk = wait_tskid(&porcb->call_queue);
  687:                 pk_rpor->atsk = wait_tskid(&porcb->accept_queue);
  688:                 pk_rpor->maxcmsz = porcb->maxcmsz;
  689:                 pk_rpor->maxrmsz = porcb->maxrmsz;
  690:         }
  691:         END_DISABLE_INTERRUPT;
  692: 
  693:         return ercd;
  694: }
  695: 
  696: /*
  697:  * Refer rendezvous call wait queue
  698:  */
  699: SYSCALL INT _td_cal_que( ID porid, ID list[], INT nent )
  700: {
  701:         PORCB  *porcb;
  702:         QUEUE  *q;
  703:         ER     ercd = E_OK;
  704: 
  705:         CHECK_PORID(porid);
  706: 
  707:         porcb = get_porcb(porid);
  708: 
  709:         BEGIN_DISABLE_INTERRUPT;
  710:         if ( porcb->porid == 0 ) {
  711:                 ercd = E_NOEXS;
  712:         } else {
  713:                 INT n = 0;
  714:                 for ( q = porcb->call_queue.next; q != &porcb->call_queue; q = q->next ) {
  715:                         if ( n++ < nent ) {
  716:                                 *list++ = ((TCB*)q)->tskid;
  717:                         }
  718:                 }
  719:                 ercd = n;
  720:         }
  721:         END_DISABLE_INTERRUPT;
  722: 
  723:         return ercd;
  724: }
  725: 
  726: /*
  727:  * Refer rendezvous accept wait queue
  728:  */
  729: SYSCALL INT _td_acp_que( ID porid, ID list[], INT nent )
  730: {
  731:         PORCB  *porcb;
  732:         QUEUE  *q;
  733:         ER     ercd = E_OK;
  734: 
  735:         CHECK_PORID(porid);
  736: 
  737:         porcb = get_porcb(porid);
  738: 
  739:         BEGIN_DISABLE_INTERRUPT;
  740:         if ( porcb->porid == 0 ) {
  741:                 ercd = E_NOEXS;
  742:         } else {
  743:                 INT n = 0;
  744:                 for ( q = porcb->accept_queue.next; q != &porcb->accept_queue; q = q->next ) {
  745:                         if ( n++ < nent ) {
  746:                                 *list++ = ((TCB*)q)->tskid;
  747:                         }
  748:                 }
  749:                 ercd = n;
  750:         }
  751:         END_DISABLE_INTERRUPT;
  752: 
  753:         return ercd;
  754: }
  755: 
  756: #endif /* USE_DBGSPT */
  757: #endif /* NUM_PORID */