gonzui


Format: Advanced Search

mtkernel_3/kernel/tkernel/eventflag.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:  *      eventflag.c
   16:  *      Event Flag
   17:  */
   18: 
   19: #include "kernel.h"
   20: #include "wait.h"
   21: #include "check.h"
   22: #include "eventflag.h"
   23: 
   24: #if USE_EVENTFLAG == 1
   25: 
   26: Noinit(EXPORT FLGCB     knl_flgcb_table[NUM_FLGID]);        /* Event flag control block */
   27: Noinit(EXPORT QUEUE     knl_free_flgcb);    /* FreeQue */
   28: 
   29: 
   30: /*
   31:  * Initialization of event flag control block 
   32:  */
   33: EXPORT ER knl_eventflag_initialize( void )
   34: {
   35:         FLGCB  *flgcb, *end;
   36: 
   37:         /* Get system information */
   38:         if ( NUM_FLGID < 1 ) {
   39:                 return E_SYS;
   40:         }
   41: 
   42:         /* Register all control blocks onto FreeQue */
   43:         QueInit(&knl_free_flgcb);
   44:         end = knl_flgcb_table + NUM_FLGID;
   45:         for ( flgcb = knl_flgcb_table; flgcb < end; flgcb++ ) {
   46:                 flgcb->flgid = 0;
   47:                 QueInsert(&flgcb->wait_queue, &knl_free_flgcb);
   48:         }
   49: 
   50:         return E_OK;
   51: }
   52: 
   53: /*
   54:  * Create event flag
   55:  */
   56: SYSCALL ID tk_cre_flg( CONST T_CFLG *pk_cflg )
   57: {
   58: #if CHK_RSATR
   59:         const ATR VALID_FLGATR = {
   60:                  TA_TPRI
   61:                 |TA_WMUL
   62: #if USE_OBJECT_NAME
   63:                 |TA_DSNAME
   64: #endif
   65:         };
   66: #endif
   67:         FLGCB  *flgcb;
   68:         ID     flgid;
   69:         ER     ercd;
   70: 
   71:         CHECK_RSATR(pk_cflg->flgatr, VALID_FLGATR);
   72: 
   73:         BEGIN_CRITICAL_SECTION;
   74:         /* Get control block from FreeQue */
   75:         flgcb = (FLGCB*)QueRemoveNext(&knl_free_flgcb);
   76:         if ( flgcb == NULL ) {
   77:                 ercd = E_LIMIT;
   78:         } else {
   79:                 flgid = ID_FLG(flgcb - knl_flgcb_table);
   80: 
   81:                 /* Initialize control block */
   82:                 QueInit(&flgcb->wait_queue);
   83:                 flgcb->flgid = flgid;
   84:                 flgcb->exinf = pk_cflg->exinf;
   85:                 flgcb->flgatr = pk_cflg->flgatr;
   86:                 flgcb->flgptn = pk_cflg->iflgptn;
   87: #if USE_OBJECT_NAME
   88:                 if ( (pk_cflg->flgatr & TA_DSNAME) != 0 ) {
   89:                         knl_strncpy((char*)flgcb->name, (char*)pk_cflg->dsname,
   90:                                 OBJECT_NAME_LENGTH);
   91:                 }
   92: #endif
   93:                 ercd = flgid;
   94:         }
   95:         END_CRITICAL_SECTION;
   96: 
   97:         return ercd;
   98: }
   99: 
  100: #ifdef USE_FUNC_TK_DEL_FLG
  101: /*
  102:  * Delete event flag
  103:  */
  104: SYSCALL ER tk_del_flg( ID flgid )
  105: {
  106:         FLGCB  *flgcb;
  107:         ER     ercd = E_OK;
  108: 
  109:         CHECK_FLGID(flgid);
  110: 
  111:         flgcb = get_flgcb(flgid);
  112: 
  113:         BEGIN_CRITICAL_SECTION;
  114:         if ( flgcb->flgid == 0 ) {
  115:                 ercd = E_NOEXS;
  116:         } else {
  117:                 /* Release wait state of task (E_DLT) */
  118:                 knl_wait_delete(&flgcb->wait_queue);
  119: 
  120:                 /* Return to FreeQue */
  121:                 QueInsert(&flgcb->wait_queue, &knl_free_flgcb);
  122:                 flgcb->flgid = 0;
  123:         }
  124:         END_CRITICAL_SECTION;
  125: 
  126:         return ercd;
  127: }
  128: #endif /* USE_FUNC_TK_DEL_FLG */
  129: 
  130: /*
  131:  * Event flag set
  132:  */
  133: SYSCALL ER tk_set_flg( ID flgid, UINT setptn )
  134: {
  135:         FLGCB  *flgcb;
  136:         TCB    *tcb;
  137:         QUEUE  *queue;
  138:         UINT   wfmode, waiptn;
  139:         ER     ercd = E_OK;
  140: 
  141:         CHECK_FLGID(flgid);
  142: 
  143:         flgcb = get_flgcb(flgid);
  144: 
  145:         BEGIN_CRITICAL_SECTION;
  146:         if ( flgcb->flgid == 0 ) {
  147:                 ercd = E_NOEXS;
  148:                 goto error_exit;
  149:         }
  150: 
  151:         /* Set event flag */
  152:         flgcb->flgptn |= setptn;
  153: 
  154:         /* Search task which should be released */
  155:         queue = flgcb->wait_queue.next;
  156:         while ( queue != &flgcb->wait_queue ) {
  157:                 tcb = (TCB*)queue;
  158:                 queue = queue->next;
  159: 
  160:                 /* Meet condition for release wait? */
  161:                 waiptn = tcb->winfo.flg.waiptn;
  162:                 wfmode = tcb->winfo.flg.wfmode;
  163:                 if ( knl_eventflag_cond(flgcb, waiptn, wfmode) ) {
  164: 
  165:                         /* Release wait */
  166:                         *tcb->winfo.flg.p_flgptn = flgcb->flgptn;
  167:                         knl_wait_release_ok(tcb);
  168: 
  169:                         /* Clear event flag */
  170:                         if ( (wfmode & TWF_BITCLR) != 0 ) {
  171:                                 if ( (flgcb->flgptn &= ~waiptn) == 0 ) {
  172:                                         break;
  173:                                 }
  174:                         }
  175:                         if ( (wfmode & TWF_CLR) != 0 ) {
  176:                                 flgcb->flgptn = 0;
  177:                                 break;
  178:                         }
  179:                 }
  180:         }
  181: 
  182:     error_exit:
  183:         END_CRITICAL_SECTION;
  184: 
  185:         return ercd;
  186: }
  187: 
  188: /*
  189:  * Clear event flag 
  190:  */
  191: SYSCALL ER tk_clr_flg( ID flgid, UINT clrptn )
  192: {
  193:         FLGCB  *flgcb;
  194:         ER     ercd = E_OK;
  195: 
  196:         CHECK_FLGID(flgid);
  197: 
  198:         flgcb = get_flgcb(flgid);
  199: 
  200:         BEGIN_CRITICAL_SECTION;
  201:         if ( flgcb->flgid == 0 ) {
  202:                 ercd = E_NOEXS;
  203:         } else {
  204:                 flgcb->flgptn &= clrptn;
  205:         }
  206:         END_CRITICAL_SECTION;
  207: 
  208:         return ercd;
  209: }
  210: 
  211: /*
  212:  * Processing if the priority of wait task changes
  213:  */
  214: LOCAL void flg_chg_pri( TCB *tcb, INT oldpri )
  215: {
  216:         FLGCB  *flgcb;
  217: 
  218:         flgcb = get_flgcb(tcb->wid);
  219:         knl_gcb_change_priority((GCB*)flgcb, tcb);
  220: }
  221: 
  222: /*
  223:  * Definition of event flag wait specification
  224:  */
  225: LOCAL CONST WSPEC knl_wspec_flg_tfifo = { TTW_FLG, NULL, NULL };
  226: LOCAL CONST WSPEC knl_wspec_flg_tpri  = { TTW_FLG, flg_chg_pri, NULL };
  227: 
  228: /*
  229:  * Event flag wait
  230:  */
  231: SYSCALL ER tk_wai_flg( ID flgid, UINT waiptn, UINT wfmode, UINT *p_flgptn, TMO tmout )
  232: {
  233:         FLGCB  *flgcb;
  234:         ER     ercd = E_OK;
  235: 
  236:         CHECK_FLGID(flgid);
  237:         CHECK_PAR(waiptn != 0);
  238:         CHECK_PAR((wfmode & ~(TWF_ORW|TWF_CLR|TWF_BITCLR)) == 0);
  239:         CHECK_TMOUT(tmout);
  240:         CHECK_DISPATCH();
  241: 
  242:         flgcb = get_flgcb(flgid);
  243: 
  244:         BEGIN_CRITICAL_SECTION;
  245:         if ( flgcb->flgid == 0 ) {
  246:                 ercd = E_NOEXS;
  247:                 goto error_exit;
  248:         }
  249:         if ( (flgcb->flgatr & TA_WMUL) == 0 && !isQueEmpty(&flgcb->wait_queue) ) {
  250:                 /* Disable multiple tasks wait */
  251:                 ercd = E_OBJ;
  252:                 goto error_exit;
  253:         }
  254: 
  255:         /* Meet condition for release wait? */
  256:         if ( knl_eventflag_cond(flgcb, waiptn, wfmode) ) {
  257:                 *p_flgptn = flgcb->flgptn;
  258: 
  259:                 /* Clear event flag */
  260:                 if ( (wfmode & TWF_BITCLR) != 0 ) {
  261:                         flgcb->flgptn &= ~waiptn;
  262:                 }
  263:                 if ( (wfmode & TWF_CLR) != 0 ) {
  264:                         flgcb->flgptn = 0;
  265:                 }
  266:         } else {
  267:                 /* Ready for wait */
  268:                 knl_ctxtsk->wspec = ( (flgcb->flgatr & TA_TPRI) != 0 )?
  269:                                         &knl_wspec_flg_tpri: &knl_wspec_flg_tfifo;
  270:                 knl_ctxtsk->wercd = &ercd;
  271:                 knl_ctxtsk->winfo.flg.waiptn = waiptn;
  272:                 knl_ctxtsk->winfo.flg.wfmode = wfmode;
  273:                 knl_ctxtsk->winfo.flg.p_flgptn = p_flgptn;
  274:                 knl_gcb_make_wait((GCB*)flgcb, tmout);
  275:         }
  276: 
  277:     error_exit:
  278:         END_CRITICAL_SECTION;
  279: 
  280:         return ercd;
  281: }
  282: 
  283: #ifdef USE_FUNC_TK_REF_FLG
  284: /*
  285:  * Check event flag state
  286:  */
  287: SYSCALL ER tk_ref_flg( ID flgid, T_RFLG *pk_rflg )
  288: {
  289:         FLGCB  *flgcb;
  290:         ER     ercd = E_OK;
  291: 
  292:         CHECK_FLGID(flgid);
  293: 
  294:         flgcb = get_flgcb(flgid);
  295: 
  296:         BEGIN_CRITICAL_SECTION;
  297:         if ( flgcb->flgid == 0 ) {
  298:                 ercd = E_NOEXS;
  299:         } else {
  300:                 pk_rflg->exinf = flgcb->exinf;
  301:                 pk_rflg->wtsk = knl_wait_tskid(&flgcb->wait_queue);
  302:                 pk_rflg->flgptn = flgcb->flgptn;
  303:         }
  304:         END_CRITICAL_SECTION;
  305: 
  306:         return ercd;
  307: }
  308: #endif /* USE_FUNC_TK_REF_FLG */
  309: 
  310: /* ------------------------------------------------------------------------ */
  311: /*
  312:  *      Debugger support function
  313:  */
  314: #if USE_DBGSPT
  315: 
  316: #if USE_OBJECT_NAME
  317: /*
  318:  * Get object name from control block
  319:  */
  320: EXPORT ER knl_eventflag_getname(ID id, UB **name)
  321: {
  322:         FLGCB  *flgcb;
  323:         ER     ercd = E_OK;
  324: 
  325:         CHECK_FLGID(id);
  326: 
  327:         BEGIN_DISABLE_INTERRUPT;
  328:         flgcb = get_flgcb(id);
  329:         if ( flgcb->flgid == 0 ) {
  330:                 ercd = E_NOEXS;
  331:                 goto error_exit;
  332:         }
  333:         if ( (flgcb->flgatr & TA_DSNAME) == 0 ) {
  334:                 ercd = E_OBJ;
  335:                 goto error_exit;
  336:         }
  337:         *name = flgcb->name;
  338: 
  339:     error_exit:
  340:         END_DISABLE_INTERRUPT;
  341: 
  342:         return ercd;
  343: }
  344: #endif /* USE_OBJECT_NAME */
  345: 
  346: #ifdef USE_FUNC_TD_LST_FLG
  347: /*
  348:  * Refer event flag usage state
  349:  */
  350: SYSCALL INT td_lst_flg( ID list[], INT nent )
  351: {
  352:         FLGCB  *flgcb, *end;
  353:         INT    n = 0;
  354: 
  355:         BEGIN_DISABLE_INTERRUPT;
  356:         end = knl_flgcb_table + NUM_FLGID;
  357:         for ( flgcb = knl_flgcb_table; flgcb < end; flgcb++ ) {
  358:                 if ( flgcb->flgid == 0 ) {
  359:                         continue;
  360:                 }
  361: 
  362:                 if ( n++ < nent ) {
  363:                         *list++ = flgcb->flgid;
  364:                 }
  365:         }
  366:         END_DISABLE_INTERRUPT;
  367: 
  368:         return n;
  369: }
  370: #endif /* USE_FUNC_TD_LST_FLG */
  371: 
  372: #ifdef USE_FUNC_TD_REF_FLG
  373: /*
  374:  * Refer event flag state
  375:  */
  376: SYSCALL ER td_ref_flg( ID flgid, TD_RFLG *pk_rflg )
  377: {
  378:         FLGCB  *flgcb;
  379:         ER     ercd = E_OK;
  380: 
  381:         CHECK_FLGID(flgid);
  382: 
  383:         flgcb = get_flgcb(flgid);
  384: 
  385:         BEGIN_DISABLE_INTERRUPT;
  386:         if ( flgcb->flgid == 0 ) {
  387:                 ercd = E_NOEXS;
  388:         } else {
  389:                 pk_rflg->exinf = flgcb->exinf;
  390:                 pk_rflg->wtsk = knl_wait_tskid(&flgcb->wait_queue);
  391:                 pk_rflg->flgptn = flgcb->flgptn;
  392:         }
  393:         END_DISABLE_INTERRUPT;
  394: 
  395:         return ercd;
  396: }
  397: #endif /* USE_FUNC_TD_REF_FLG */
  398: 
  399: #ifdef USE_FUNC_TD_FLG_QUE
  400: /*
  401:  * Refer event flag wait queue
  402:  */
  403: SYSCALL INT td_flg_que( ID flgid, ID list[], INT nent )
  404: {
  405:         FLGCB  *flgcb;
  406:         QUEUE  *q;
  407:         ER     ercd = E_OK;
  408: 
  409:         CHECK_FLGID(flgid);
  410: 
  411:         flgcb = get_flgcb(flgid);
  412: 
  413:         BEGIN_DISABLE_INTERRUPT;
  414:         if ( flgcb->flgid == 0 ) {
  415:                 ercd = E_NOEXS;
  416:         } else {
  417:                 INT n = 0;
  418:                 for ( q = flgcb->wait_queue.next; q != &flgcb->wait_queue; q = q->next ) {
  419:                         if ( n++ < nent ) {
  420:                                 *list++ = ((TCB*)q)->tskid;
  421:                         }
  422:                 }
  423:                 ercd = n;
  424:         }
  425:         END_DISABLE_INTERRUPT;
  426: 
  427:         return ercd;
  428: }
  429: #endif /* USE_FUNC_TD_FLG_QUE */
  430: 
  431: #endif /* USE_DBGSPT */
  432: #endif /* USE_EVENTFLAG */