gonzui


Format: Advanced Search

mtkernel_3/kernel/tkernel/mailbox.cbare sourcepermlink (0.04 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    micro T-Kernel 3.00.00
    4:  *
    5:  *    Copyright (C) 2006-2019 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.1.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2019/12/11.
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: 
   14: /*
   15:  *      mailbox.c
   16:  *      Mailbox
   17:  */
   18: 
   19: #include "kernel.h"
   20: #include "wait.h"
   21: #include "check.h"
   22: #include "mailbox.h"
   23: 
   24: #if USE_MAILBOX == 1
   25: 
   26: Noinit(EXPORT MBXCB     knl_mbxcb_table[NUM_MBXID]);        /* Mailbox control block */
   27: Noinit(EXPORT QUEUE     knl_free_mbxcb);    /* FreeQue */
   28: 
   29: 
   30: /*
   31:  * Initialization of mailbox control block 
   32:  */
   33: EXPORT ER knl_mailbox_initialize( void )
   34: {
   35:         MBXCB  *mbxcb, *end;
   36: 
   37:         /* Get system information */
   38:         if ( NUM_MBXID < 1 ) {
   39:                 return E_SYS;
   40:         }
   41: 
   42:         /* Register all control blocks onto FreeQue */
   43:         QueInit(&knl_free_mbxcb);
   44:         end = knl_mbxcb_table + NUM_MBXID;
   45:         for ( mbxcb = knl_mbxcb_table; mbxcb < end; mbxcb++ ) {
   46:                 mbxcb->mbxid = 0;
   47:                 QueInsert(&mbxcb->wait_queue, &knl_free_mbxcb);
   48:         }
   49: 
   50:         return E_OK;
   51: }
   52: 
   53: 
   54: /*
   55:  * Create mailbox
   56:  */
   57: SYSCALL ID tk_cre_mbx( CONST T_CMBX *pk_cmbx )
   58: {
   59: #if CHK_RSATR
   60:         const ATR VALID_MBXATR = {
   61:                  TA_MPRI
   62:                 |TA_TPRI
   63: #if USE_OBJECT_NAME
   64:                 |TA_DSNAME
   65: #endif
   66:         };
   67: #endif
   68:         MBXCB  *mbxcb;
   69:         ID     mbxid;
   70:         ER     ercd;
   71: 
   72:         CHECK_RSATR(pk_cmbx->mbxatr, VALID_MBXATR);
   73: 
   74:         BEGIN_CRITICAL_SECTION;
   75:         /* Get control block from FreeQue */
   76:         mbxcb = (MBXCB*)QueRemoveNext(&knl_free_mbxcb);
   77:         if ( mbxcb == NULL ) {
   78:                 ercd = E_LIMIT;
   79:         } else {
   80:                 mbxid = ID_MBX(mbxcb - knl_mbxcb_table);
   81: 
   82:                 /* Initialize control block */
   83:                 QueInit(&mbxcb->wait_queue);
   84:                 mbxcb->mbxid  = mbxid;
   85:                 mbxcb->exinf  = pk_cmbx->exinf;
   86:                 mbxcb->mbxatr = pk_cmbx->mbxatr;
   87:                 mbxcb->mq_head.msgque[0] = NULL;
   88: #if USE_OBJECT_NAME
   89:                 if ( (pk_cmbx->mbxatr & TA_DSNAME) != 0 ) {
   90:                         knl_strncpy((char*)mbxcb->name, (char*)pk_cmbx->dsname,
   91:                                 OBJECT_NAME_LENGTH);
   92:                 }
   93: #endif
   94:                 ercd = mbxid;
   95:         }
   96:         END_CRITICAL_SECTION;
   97: 
   98:         return ercd;
   99: }
  100: 
  101: #ifdef USE_FUNC_TK_DEL_MBX
  102: /*
  103:  * Delete mailbox
  104:  */
  105: SYSCALL ER tk_del_mbx( ID mbxid )
  106: {
  107:         MBXCB  *mbxcb;
  108:         ER     ercd = E_OK;
  109: 
  110:         CHECK_MBXID(mbxid);
  111: 
  112:         mbxcb = get_mbxcb(mbxid);
  113: 
  114:         BEGIN_CRITICAL_SECTION;
  115:         if ( mbxcb->mbxid == 0 ) {
  116:                 ercd = E_NOEXS;
  117:         } else {
  118:                 /* Release wait state of task (E_DLT) */
  119:                 knl_wait_delete(&mbxcb->wait_queue);
  120: 
  121:                 /* Return to FreeQue */
  122:                 QueInsert(&mbxcb->wait_queue, &knl_free_mbxcb);
  123:                 mbxcb->mbxid = 0;
  124:         }
  125:         END_CRITICAL_SECTION;
  126: 
  127:         return ercd;
  128: }
  129: #endif /* USE_FUNC_TK_DEL_MBX */
  130: 
  131: /*
  132:  * Send to mailbox
  133:  */
  134: SYSCALL ER tk_snd_mbx( ID mbxid, T_MSG *pk_msg )
  135: {
  136:         MBXCB  *mbxcb;
  137:         TCB    *tcb;
  138:         ER     ercd = E_OK;
  139: 
  140:         CHECK_MBXID(mbxid);
  141: 
  142:         mbxcb = get_mbxcb(mbxid);
  143: 
  144:         BEGIN_CRITICAL_SECTION;
  145:         if (mbxcb->mbxid == 0) {
  146:                 ercd = E_NOEXS;
  147:                 goto error_exit;
  148:         }
  149: 
  150:         if ( (mbxcb->mbxatr & TA_MPRI) != 0 ) {
  151:                 if ( ((T_MSG_PRI*)pk_msg)->msgpri <= 0 ) {
  152:                         ercd = E_PAR;
  153:                         goto error_exit;
  154:                 }
  155:         }
  156: 
  157:         if ( !isQueEmpty(&mbxcb->wait_queue) ) {
  158:                 /* Directly send to receive wait task */
  159:                 tcb = (TCB*)(mbxcb->wait_queue.next);
  160:                 *tcb->winfo.mbx.ppk_msg = pk_msg;
  161:                 knl_wait_release_ok(tcb);
  162: 
  163:         } else {
  164:                 /* Connect message to queue */
  165:                 if ( (mbxcb->mbxatr & TA_MPRI) != 0 ) {
  166:                         /* Connect message to queue following priority */
  167:                         knl_queue_insert_mpri((T_MSG_PRI*)pk_msg, &mbxcb->mq_head);
  168:                 } else {
  169:                         /* Connect to end of queue */
  170:                         nextmsg(pk_msg) = NULL;
  171:                         if ( headmsg(mbxcb) == NULL ) {
  172:                                 headmsg(mbxcb) = pk_msg;
  173:                         } else {
  174:                                 nextmsg(mbxcb->mq_tail) = pk_msg;
  175:                         }
  176:                         mbxcb->mq_tail = pk_msg;
  177:                 }
  178:         }
  179: 
  180:     error_exit:
  181:         END_CRITICAL_SECTION;
  182: 
  183:         return ercd;
  184: }
  185: 
  186: /*
  187:  * Processing if the priority of wait task changes
  188:  */
  189: LOCAL void mbx_chg_pri( TCB *tcb, INT oldpri )
  190: {
  191:         MBXCB  *mbxcb;
  192: 
  193:         mbxcb = get_mbxcb(tcb->wid);
  194:         knl_gcb_change_priority((GCB*)mbxcb, tcb);
  195: }
  196: 
  197: /*
  198:  * Definition of mailbox wait specification
  199:  */
  200: LOCAL CONST WSPEC knl_wspec_mbx_tfifo = { TTW_MBX, NULL, NULL };
  201: LOCAL CONST WSPEC knl_wspec_mbx_tpri  = { TTW_MBX, mbx_chg_pri, NULL };
  202: 
  203: /*
  204:  * Receive from mailbox
  205:  */
  206: SYSCALL ER tk_rcv_mbx( ID mbxid, T_MSG **ppk_msg, TMO tmout )
  207: {
  208:         MBXCB  *mbxcb;
  209:         ER     ercd = E_OK;
  210: 
  211:         CHECK_MBXID(mbxid);
  212:         CHECK_TMOUT(tmout);
  213:         CHECK_DISPATCH();
  214: 
  215:         mbxcb = get_mbxcb(mbxid);
  216: 
  217:         BEGIN_CRITICAL_SECTION;
  218:         if ( mbxcb->mbxid == 0 ) {
  219:                 ercd = E_NOEXS;
  220:                 goto error_exit;
  221:         }
  222: 
  223:         if ( headmsg(mbxcb) != NULL ) {
  224:                 /* Get message from head of queue */
  225:                 *ppk_msg = headmsg(mbxcb);
  226:                 headmsg(mbxcb) = nextmsg(*ppk_msg);
  227:         } else {
  228:                 /* Ready for receive wait */
  229:                 knl_ctxtsk->wspec = ( (mbxcb->mbxatr & TA_TPRI) != 0 )?
  230:                                         &knl_wspec_mbx_tpri: &knl_wspec_mbx_tfifo;
  231:                 knl_ctxtsk->wercd = &ercd;
  232:                 knl_ctxtsk->winfo.mbx.ppk_msg = ppk_msg;
  233:                 knl_gcb_make_wait((GCB*)mbxcb, tmout);
  234:         }
  235: 
  236:     error_exit:
  237:         END_CRITICAL_SECTION;
  238: 
  239:         return ercd;
  240: }
  241: 
  242: #ifdef USE_FUNC_TK_REF_MBX
  243: /*
  244:  * Refer mailbox state 
  245:  */
  246: SYSCALL ER tk_ref_mbx( ID mbxid, T_RMBX *pk_rmbx )
  247: {
  248:         MBXCB  *mbxcb;
  249:         ER     ercd = E_OK;
  250: 
  251:         CHECK_MBXID(mbxid);
  252: 
  253:         mbxcb = get_mbxcb(mbxid);
  254: 
  255:         BEGIN_CRITICAL_SECTION;
  256:         if ( mbxcb->mbxid == 0 ) {
  257:                 ercd = E_NOEXS;
  258:         } else {
  259:                 pk_rmbx->exinf = mbxcb->exinf;
  260:                 pk_rmbx->wtsk = knl_wait_tskid(&mbxcb->wait_queue);
  261:                 pk_rmbx->pk_msg = headmsg(mbxcb);
  262:         }
  263:         END_CRITICAL_SECTION;
  264: 
  265:         return ercd;
  266: }
  267: #endif /* USE_FUNC_TK_REF_MBX */
  268: 
  269: /* ------------------------------------------------------------------------ */
  270: /*
  271:  *      Debugger support function
  272:  */
  273: #if USE_DBGSPT
  274: 
  275: #if USE_OBJECT_NAME
  276: /*
  277:  * Get object name from control block
  278:  */
  279: EXPORT ER knl_mailbox_getname(ID id, UB **name)
  280: {
  281:         MBXCB  *mbxcb;
  282:         ER     ercd = E_OK;
  283: 
  284:         CHECK_MBXID(id);
  285: 
  286:         BEGIN_DISABLE_INTERRUPT;
  287:         mbxcb = get_mbxcb(id);
  288:         if ( mbxcb->mbxid == 0 ) {
  289:                 ercd = E_NOEXS;
  290:                 goto error_exit;
  291:         }
  292:         if ( (mbxcb->mbxatr & TA_DSNAME) == 0 ) {
  293:                 ercd = E_OBJ;
  294:                 goto error_exit;
  295:         }
  296:         *name = mbxcb->name;
  297: 
  298:     error_exit:
  299:         END_DISABLE_INTERRUPT;
  300: 
  301:         return ercd;
  302: }
  303: #endif /* USE_OBJECT_NAME */
  304: 
  305: #ifdef USE_FUNC_TD_LST_MBX
  306: /*
  307:  * Refer mailbox usage state
  308:  */
  309: SYSCALL INT td_lst_mbx( ID list[], INT nent )
  310: {
  311:         MBXCB  *mbxcb, *end;
  312:         INT    n = 0;
  313: 
  314:         BEGIN_DISABLE_INTERRUPT;
  315:         end = knl_mbxcb_table + NUM_MBXID;
  316:         for ( mbxcb = knl_mbxcb_table; mbxcb < end; mbxcb++ ) {
  317:                 if ( mbxcb->mbxid == 0 ) {
  318:                         continue;
  319:                 }
  320: 
  321:                 if ( n++ < nent ) {
  322:                         *list++ = mbxcb->mbxid;
  323:                 }
  324:         }
  325:         END_DISABLE_INTERRUPT;
  326: 
  327:         return n;
  328: }
  329: #endif /* USE_FUNC_TD_LST_MBX */
  330: 
  331: #ifdef USE_FUNC_TD_REF_MBX
  332: /*
  333:  * Refer mailbox state
  334:  */
  335: SYSCALL ER td_ref_mbx( ID mbxid, TD_RMBX *pk_rmbx )
  336: {
  337:         MBXCB  *mbxcb;
  338:         ER     ercd = E_OK;
  339: 
  340:         CHECK_MBXID(mbxid);
  341: 
  342:         mbxcb = get_mbxcb(mbxid);
  343: 
  344:         BEGIN_DISABLE_INTERRUPT;
  345:         if ( mbxcb->mbxid == 0 ) {
  346:                 ercd = E_NOEXS;
  347:         } else {
  348:                 pk_rmbx->exinf = mbxcb->exinf;
  349:                 pk_rmbx->wtsk = knl_wait_tskid(&mbxcb->wait_queue);
  350:                 pk_rmbx->pk_msg = headmsg(mbxcb);
  351:         }
  352:         END_DISABLE_INTERRUPT;
  353: 
  354:         return ercd;
  355: }
  356: #endif /* USE_FUNC_TD_REF_MBX */
  357: 
  358: #ifdef USE_FUNC_TD_MBX_QUE
  359: /*
  360:  * Refer mailbox wait queue
  361:  */
  362: SYSCALL INT td_mbx_que( ID mbxid, ID list[], INT nent )
  363: {
  364:         MBXCB  *mbxcb;
  365:         QUEUE  *q;
  366:         ER     ercd = E_OK;
  367: 
  368:         CHECK_MBXID(mbxid);
  369: 
  370:         mbxcb = get_mbxcb(mbxid);
  371: 
  372:         BEGIN_DISABLE_INTERRUPT;
  373:         if ( mbxcb->mbxid == 0 ) {
  374:                 ercd = E_NOEXS;
  375:         } else {
  376:                 INT n = 0;
  377:                 for ( q = mbxcb->wait_queue.next; q != &mbxcb->wait_queue; q = q->next ) {
  378:                         if ( n++ < nent ) {
  379:                                 *list++ = ((TCB*)q)->tskid;
  380:                         }
  381:                 }
  382:                 ercd = n;
  383:         }
  384:         END_DISABLE_INTERRUPT;
  385: 
  386:         return ercd;
  387: }
  388: #endif /* USE_FUNC_TD_MBX_QUE */
  389: 
  390: #endif /* USE_DBGSPT */
  391: #endif /* USE_MAILBOX */