gonzui


Format: Advanced Search

tkernel_2/kernel/tkernel/src/eventflag.cbare sourcepermlink (0.03 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:  *      eventflag.c (T-Kernel/OS)
   19:  *      Event Flag
   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_FLGID
   29: 
   30: EXPORT ID       max_flgid;    /* Maximum event flag ID */
   31: 
   32: /*
   33:  * Event flag control block
   34:  */
   35: typedef struct eventflag_control_block {
   36:         QUEUE  wait_queue;      /* Event flag wait queue */
   37:         ID     flgid;              /* Event flag ID */
   38:         void   *exinf;           /* Extended information */
   39:         ATR    flgatr;            /* Event flag attribute */
   40:         UINT   flgptn;           /* Event flag current pattern */
   41: #if USE_OBJECT_NAME
   42:         UB     name[OBJECT_NAME_LENGTH];   /* name */
   43: #endif
   44: } FLGCB;
   45: 
   46: LOCAL FLGCB     *flgcb_table;       /* Event flag control block */
   47: LOCAL QUEUE     free_flgcb; /* FreeQue */
   48: 
   49: #define get_flgcb(id)   ( &flgcb_table[INDEX_FLG(id)] )
   50: 
   51: 
   52: /*
   53:  * Initialization of event flag control block
   54:  */
   55: EXPORT ER eventflag_initialize( void )
   56: {
   57:         FLGCB  *flgcb, *end;
   58:         W      n;
   59: 
   60:         /* Get system information */
   61:         n = _tk_get_cfn(SCTAG_TMAXFLGID, &max_flgid, 1);
   62:         if ( n < 1 || NUM_FLGID < 1 ) {
   63:                 return E_SYS;
   64:         }
   65: 
   66:         /* Create event flag control block */
   67:         flgcb_table = Imalloc((UINT)NUM_FLGID * sizeof(FLGCB));
   68:         if ( flgcb_table == NULL ) {
   69:                 return E_NOMEM;
   70:         }
   71: 
   72:         /* Register all control blocks onto FreeQue */
   73:         QueInit(&free_flgcb);
   74:         end = flgcb_table + NUM_FLGID;
   75:         for ( flgcb = flgcb_table; flgcb < end; flgcb++ ) {
   76:                 flgcb->flgid = 0;
   77:                 QueInsert(&flgcb->wait_queue, &free_flgcb);
   78:         }
   79: 
   80:         return E_OK;
   81: }
   82: 
   83: /*
   84:  * Check for event flag wait release condition
   85:  */
   86: Inline BOOL eventflag_cond( FLGCB *flgcb, UINT waiptn, UINT wfmode )
   87: {
   88:         if ( (wfmode & TWF_ORW) != 0 ) {
   89:                 return ( (flgcb->flgptn & waiptn) != 0 );
   90:         } else {
   91:                 return ( (flgcb->flgptn & waiptn) == waiptn );
   92:         }
   93: }
   94: 
   95: /*
   96:  * Processing if the priority of wait task changes
   97:  */
   98: LOCAL void flg_chg_pri( TCB *tcb, INT oldpri )
   99: {
  100:         FLGCB  *flgcb;
  101: 
  102:         flgcb = get_flgcb(tcb->wid);
  103:         gcb_change_priority((GCB*)flgcb, tcb);
  104: }
  105: 
  106: /*
  107:  * Definition of event flag wait specification
  108:  */
  109: LOCAL CONST WSPEC wspec_flg_tfifo = { TTW_FLG, NULL, NULL };
  110: LOCAL CONST WSPEC wspec_flg_tpri  = { TTW_FLG, flg_chg_pri, NULL };
  111: 
  112: 
  113: /*
  114:  * Create event flag
  115:  */
  116: SYSCALL ID _tk_cre_flg( CONST T_CFLG *pk_cflg )
  117: {
  118: #if CHK_RSATR
  119:         const ATR VALID_FLGATR = {
  120:                  TA_TPRI
  121:                 |TA_WMUL
  122:                 |TA_NODISWAI
  123: #if USE_OBJECT_NAME
  124:                 |TA_DSNAME
  125: #endif
  126:         };
  127: #endif
  128:         FLGCB  *flgcb;
  129:         ID     flgid;
  130:         ER     ercd;
  131: 
  132:         CHECK_RSATR(pk_cflg->flgatr, VALID_FLGATR);
  133: 
  134:         BEGIN_CRITICAL_SECTION;
  135:         /* Get control block from FreeQue */
  136:         flgcb = (FLGCB*)QueRemoveNext(&free_flgcb);
  137:         if ( flgcb == NULL ) {
  138:                 ercd = E_LIMIT;
  139:         } else {
  140:                 flgid = ID_FLG(flgcb - flgcb_table);
  141: 
  142:                 /* Initialize control block */
  143:                 QueInit(&flgcb->wait_queue);
  144:                 flgcb->flgid = flgid;
  145:                 flgcb->exinf = pk_cflg->exinf;
  146:                 flgcb->flgatr = pk_cflg->flgatr;
  147:                 flgcb->flgptn = pk_cflg->iflgptn;
  148: #if USE_OBJECT_NAME
  149:                 if ( (pk_cflg->flgatr & TA_DSNAME) != 0 ) {
  150:                         STRNCPY((char*)flgcb->name, (char*)pk_cflg->dsname,
  151:                                 OBJECT_NAME_LENGTH);
  152:                 }
  153: #endif
  154:                 ercd = flgid;
  155:         }
  156:         END_CRITICAL_SECTION;
  157: 
  158:         return ercd;
  159: }
  160: 
  161: /*
  162:  * Delete event flag
  163:  */
  164: SYSCALL ER _tk_del_flg( ID flgid )
  165: {
  166:         FLGCB  *flgcb;
  167:         ER     ercd = E_OK;
  168: 
  169:         CHECK_FLGID(flgid);
  170: 
  171:         flgcb = get_flgcb(flgid);
  172: 
  173:         BEGIN_CRITICAL_SECTION;
  174:         if ( flgcb->flgid == 0 ) {
  175:                 ercd = E_NOEXS;
  176:         } else {
  177:                 /* Release wait state of task (E_DLT) */
  178:                 wait_delete(&flgcb->wait_queue);
  179: 
  180:                 /* Return to FreeQue */
  181:                 QueInsert(&flgcb->wait_queue, &free_flgcb);
  182:                 flgcb->flgid = 0;
  183:         }
  184:         END_CRITICAL_SECTION;
  185: 
  186:         return ercd;
  187: }
  188: 
  189: /*
  190:  * Event flag set
  191:  */
  192: SYSCALL ER _tk_set_flg( ID flgid, UINT setptn )
  193: {
  194:         FLGCB  *flgcb;
  195:         TCB    *tcb;
  196:         QUEUE  *queue;
  197:         UINT   wfmode, waiptn;
  198:         ER     ercd = E_OK;
  199: 
  200:         CHECK_FLGID(flgid);
  201: 
  202:         flgcb = get_flgcb(flgid);
  203: 
  204:         BEGIN_CRITICAL_SECTION;
  205:         if ( flgcb->flgid == 0 ) {
  206:                 ercd = E_NOEXS;
  207:                 goto error_exit;
  208:         }
  209: 
  210:         /* Set event flag */
  211:         flgcb->flgptn |= setptn;
  212: 
  213:         /* Search task which should be released */
  214:         queue = flgcb->wait_queue.next;
  215:         while ( queue != &flgcb->wait_queue ) {
  216:                 tcb = (TCB*)queue;
  217:                 queue = queue->next;
  218: 
  219:                 /* Meet condition for release wait? */
  220:                 waiptn = tcb->winfo.flg.waiptn;
  221:                 wfmode = tcb->winfo.flg.wfmode;
  222:                 if ( eventflag_cond(flgcb, waiptn, wfmode) ) {
  223: 
  224:                         /* Release wait */
  225:                         *tcb->winfo.flg.p_flgptn = flgcb->flgptn;
  226:                         wait_release_ok(tcb);
  227: 
  228:                         /* Clear event flag */
  229:                         if ( (wfmode & TWF_BITCLR) != 0 ) {
  230:                                 if ( (flgcb->flgptn &= ~waiptn) == 0 ) {
  231:                                         break;
  232:                                 }
  233:                         }
  234:                         if ( (wfmode & TWF_CLR) != 0 ) {
  235:                                 flgcb->flgptn = 0;
  236:                                 break;
  237:                         }
  238:                 }
  239:         }
  240: 
  241:     error_exit:
  242:         END_CRITICAL_SECTION;
  243: 
  244:         return ercd;
  245: }
  246: 
  247: /*
  248:  * Clear event flag
  249:  */
  250: SYSCALL ER _tk_clr_flg( ID flgid, UINT clrptn )
  251: {
  252:         FLGCB  *flgcb;
  253:         ER     ercd = E_OK;
  254: 
  255:         CHECK_FLGID(flgid);
  256: 
  257:         flgcb = get_flgcb(flgid);
  258: 
  259:         BEGIN_CRITICAL_SECTION;
  260:         if ( flgcb->flgid == 0 ) {
  261:                 ercd = E_NOEXS;
  262:         } else {
  263:                 flgcb->flgptn &= clrptn;
  264:         }
  265:         END_CRITICAL_SECTION;
  266: 
  267:         return ercd;
  268: }
  269: 
  270: /*
  271:  * Event flag wait
  272:  */
  273: SYSCALL ER _tk_wai_flg( ID flgid, UINT waiptn, UINT wfmode, UINT *p_flgptn, TMO tmout )
  274: {
  275:         return _tk_wai_flg_u(flgid, waiptn, wfmode, p_flgptn, to_usec_tmo(tmout));
  276: }
  277: 
  278: SYSCALL ER _tk_wai_flg_u( ID flgid, UINT waiptn, UINT wfmode, UINT *p_flgptn, TMO_U tmout )
  279: {
  280:         FLGCB  *flgcb;
  281:         ER     ercd = E_OK;
  282: 
  283:         CHECK_FLGID(flgid);
  284:         CHECK_PAR(waiptn != 0);
  285:         CHECK_PAR((wfmode & ~(TWF_ORW|TWF_CLR|TWF_BITCLR)) == 0);
  286:         CHECK_TMOUT(tmout);
  287:         CHECK_DISPATCH();
  288: 
  289:         flgcb = get_flgcb(flgid);
  290: 
  291:         BEGIN_CRITICAL_SECTION;
  292:         if ( flgcb->flgid == 0 ) {
  293:                 ercd = E_NOEXS;
  294:                 goto error_exit;
  295:         }
  296:         if ( (flgcb->flgatr & TA_WMUL) == 0 && !isQueEmpty(&flgcb->wait_queue) ) {
  297:                 /* Disable multiple tasks wait */
  298:                 ercd = E_OBJ;
  299:                 goto error_exit;
  300:         }
  301: 
  302:         /* Check wait disable */
  303:         if ( is_diswai((GCB*)flgcb, ctxtsk, TTW_FLG) ) {
  304:                 ercd = E_DISWAI;
  305:                 goto error_exit;
  306:         }
  307: 
  308:         /* Meet condition for release wait? */
  309:         if ( eventflag_cond(flgcb, waiptn, wfmode) ) {
  310:                 *p_flgptn = flgcb->flgptn;
  311: 
  312:                 /* Clear event flag */
  313:                 if ( (wfmode & TWF_BITCLR) != 0 ) {
  314:                         flgcb->flgptn &= ~waiptn;
  315:                 }
  316:                 if ( (wfmode & TWF_CLR) != 0 ) {
  317:                         flgcb->flgptn = 0;
  318:                 }
  319:         } else {
  320:                 /* Ready for wait */
  321:                 ctxtsk->wspec = ( (flgcb->flgatr & TA_TPRI) != 0 )?
  322:                                         &wspec_flg_tpri: &wspec_flg_tfifo;
  323:                 ctxtsk->wercd = &ercd;
  324:                 ctxtsk->winfo.flg.waiptn = waiptn;
  325:                 ctxtsk->winfo.flg.wfmode = wfmode;
  326:                 ctxtsk->winfo.flg.p_flgptn = p_flgptn;
  327:                 gcb_make_wait_with_diswai((GCB*)flgcb, tmout);
  328:         }
  329: 
  330:     error_exit:
  331:         END_CRITICAL_SECTION;
  332: 
  333:         return ercd;
  334: }
  335: 
  336: /*
  337:  * Check event flag state
  338:  */
  339: SYSCALL ER _tk_ref_flg( ID flgid, T_RFLG *pk_rflg )
  340: {
  341:         FLGCB  *flgcb;
  342:         ER     ercd = E_OK;
  343: 
  344:         CHECK_FLGID(flgid);
  345: 
  346:         flgcb = get_flgcb(flgid);
  347: 
  348:         BEGIN_CRITICAL_SECTION;
  349:         if ( flgcb->flgid == 0 ) {
  350:                 ercd = E_NOEXS;
  351:         } else {
  352:                 pk_rflg->exinf = flgcb->exinf;
  353:                 pk_rflg->wtsk = wait_tskid(&flgcb->wait_queue);
  354:                 pk_rflg->flgptn = flgcb->flgptn;
  355:         }
  356:         END_CRITICAL_SECTION;
  357: 
  358:         return ercd;
  359: }
  360: 
  361: /* ------------------------------------------------------------------------ */
  362: /*
  363:  *      Debugger support function
  364:  */
  365: #if USE_DBGSPT
  366: 
  367: /*
  368:  * Get object name from control block
  369:  */
  370: #if USE_OBJECT_NAME
  371: EXPORT ER eventflag_getname(ID id, UB **name)
  372: {
  373:         FLGCB  *flgcb;
  374:         ER     ercd = E_OK;
  375: 
  376:         CHECK_FLGID(id);
  377: 
  378:         BEGIN_DISABLE_INTERRUPT;
  379:         flgcb = get_flgcb(id);
  380:         if ( flgcb->flgid == 0 ) {
  381:                 ercd = E_NOEXS;
  382:                 goto error_exit;
  383:         }
  384:         if ( (flgcb->flgatr & TA_DSNAME) == 0 ) {
  385:                 ercd = E_OBJ;
  386:                 goto error_exit;
  387:         }
  388:         *name = flgcb->name;
  389: 
  390:     error_exit:
  391:         END_DISABLE_INTERRUPT;
  392: 
  393:         return ercd;
  394: }
  395: #endif /* USE_OBJECT_NAME */
  396: 
  397: /*
  398:  * Refer event flag usage state
  399:  */
  400: SYSCALL INT _td_lst_flg( ID list[], INT nent )
  401: {
  402:         FLGCB  *flgcb, *end;
  403:         INT    n = 0;
  404: 
  405:         BEGIN_DISABLE_INTERRUPT;
  406:         end = flgcb_table + NUM_FLGID;
  407:         for ( flgcb = flgcb_table; flgcb < end; flgcb++ ) {
  408:                 if ( flgcb->flgid == 0 ) {
  409:                         continue;
  410:                 }
  411: 
  412:                 if ( n++ < nent ) {
  413:                         *list++ = flgcb->flgid;
  414:                 }
  415:         }
  416:         END_DISABLE_INTERRUPT;
  417: 
  418:         return n;
  419: }
  420: 
  421: /*
  422:  * Refer event flag state
  423:  */
  424: SYSCALL ER _td_ref_flg( ID flgid, TD_RFLG *pk_rflg )
  425: {
  426:         FLGCB  *flgcb;
  427:         ER     ercd = E_OK;
  428: 
  429:         CHECK_FLGID(flgid);
  430: 
  431:         flgcb = get_flgcb(flgid);
  432: 
  433:         BEGIN_DISABLE_INTERRUPT;
  434:         if ( flgcb->flgid == 0 ) {
  435:                 ercd = E_NOEXS;
  436:         } else {
  437:                 pk_rflg->exinf = flgcb->exinf;
  438:                 pk_rflg->wtsk = wait_tskid(&flgcb->wait_queue);
  439:                 pk_rflg->flgptn = flgcb->flgptn;
  440:         }
  441:         END_DISABLE_INTERRUPT;
  442: 
  443:         return ercd;
  444: }
  445: 
  446: /*
  447:  * Refer event flag wait queue
  448:  */
  449: SYSCALL INT _td_flg_que( ID flgid, ID list[], INT nent )
  450: {
  451:         FLGCB  *flgcb;
  452:         QUEUE  *q;
  453:         ER     ercd = E_OK;
  454: 
  455:         CHECK_FLGID(flgid);
  456: 
  457:         flgcb = get_flgcb(flgid);
  458: 
  459:         BEGIN_DISABLE_INTERRUPT;
  460:         if ( flgcb->flgid == 0 ) {
  461:                 ercd = E_NOEXS;
  462:         } else {
  463:                 INT n = 0;
  464:                 for ( q = flgcb->wait_queue.next; q != &flgcb->wait_queue; q = q->next ) {
  465:                         if ( n++ < nent ) {
  466:                                 *list++ = ((TCB*)q)->tskid;
  467:                         }
  468:                 }
  469:                 ercd = n;
  470:         }
  471:         END_DISABLE_INTERRUPT;
  472: 
  473:         return ercd;
  474: }
  475: 
  476: #endif /* USE_DBGSPT */
  477: #endif /* NUM_FLGID */