gonzui


Format: Advanced Search

tkernel_2/kernel/tkernel/src/task_sync.cbare sourcepermlink (0.01 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 TRON Forum(http://www.tron.org/) at 2015/06/01.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: 
   16: /*
   17:  *      task_sync.c (T-Kernel/OS)
   18:  *      Task with Synchronize Function
   19:  */
   20: 
   21: #include <limits.h>
   22: #include "kernel.h"
   23: #include "task.h"
   24: #include "wait.h"
   25: #include "check.h"
   26: 
   27: /*
   28:  * Suspend task
   29:  */
   30: SYSCALL ER _tk_sus_tsk( ID tskid )
   31: {
   32:         TCB    *tcb;
   33:         TSTAT  state;
   34:         ER     ercd = E_OK;
   35: 
   36:         CHECK_TSKID(tskid);
   37:         CHECK_NONSELF(tskid);
   38: 
   39:         tcb = get_tcb(tskid);
   40: 
   41:         BEGIN_CRITICAL_SECTION;
   42:         state = (TSTAT)tcb->state;
   43:         if ( !task_alive(state) ) {
   44:                 ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;
   45:                 goto error_exit;
   46:         }
   47:         if ( tcb == ctxtsk && dispatch_disabled >= DDS_DISABLE ) {
   48:                 ercd = E_CTX;
   49:                 goto error_exit;
   50:         }
   51:         if ( tcb->suscnt == INT_MAX ) {
   52:                 ercd = E_QOVR;
   53:                 goto error_exit;
   54:         }
   55: 
   56:         /* Update suspend request count */
   57:         ++tcb->suscnt;
   58: 
   59:         /* Move to forced wait state */
   60:         if ( state == TS_READY ) {
   61:                 make_non_ready(tcb);
   62:                 tcb->state = TS_SUSPEND;
   63: 
   64:         } else if ( state == TS_WAIT ) {
   65:                 tcb->state = TS_WAITSUS;
   66:         }
   67: 
   68:     error_exit:
   69:         END_CRITICAL_SECTION;
   70: 
   71:         return ercd;
   72: }
   73: 
   74: /*
   75:  * Resume task
   76:  */
   77: SYSCALL ER _tk_rsm_tsk( ID tskid )
   78: {
   79:         TCB    *tcb;
   80:         ER     ercd = E_OK;
   81: 
   82:         CHECK_TSKID(tskid);
   83:         CHECK_NONSELF(tskid);
   84: 
   85:         tcb = get_tcb(tskid);
   86: 
   87:         BEGIN_CRITICAL_SECTION;
   88:         switch ( tcb->state ) {
   89:           case TS_NONEXIST:
   90:                 ercd = E_NOEXS;
   91:                 break;
   92: 
   93:           case TS_DORMANT:
   94:           case TS_READY:
   95:           case TS_WAIT:
   96:                 ercd = E_OBJ;
   97:                 break;
   98: 
   99:           case TS_SUSPEND:
  100:                 if ( --tcb->suscnt == 0 ) {
  101:                         make_ready(tcb);
  102:                 }
  103:                 break;
  104:           case TS_WAITSUS:
  105:                 if ( --tcb->suscnt == 0 ) {
  106:                         tcb->state = TS_WAIT;
  107:                 }
  108:                 break;
  109: 
  110:           default:
  111:                 ercd = E_SYS;
  112:                 break;
  113:         }
  114:         END_CRITICAL_SECTION;
  115: 
  116:         return ercd;
  117: }
  118: 
  119: /*
  120:  * Force resume task
  121:  */
  122: SYSCALL ER _tk_frsm_tsk( ID tskid )
  123: {
  124:         TCB    *tcb;
  125:         ER     ercd = E_OK;
  126: 
  127:         CHECK_TSKID(tskid);
  128:         CHECK_NONSELF(tskid);
  129: 
  130:         tcb = get_tcb(tskid);
  131: 
  132:         BEGIN_CRITICAL_SECTION;
  133:         switch ( tcb->state ) {
  134:           case TS_NONEXIST:
  135:                 ercd = E_NOEXS;
  136:                 break;
  137: 
  138:           case TS_DORMANT:
  139:           case TS_READY:
  140:           case TS_WAIT:
  141:                 ercd = E_OBJ;
  142:                 break;
  143: 
  144:           case TS_SUSPEND:
  145:                 tcb->suscnt = 0;
  146:                 make_ready(tcb);
  147:                 break;
  148:           case TS_WAITSUS:
  149:                 tcb->suscnt = 0;
  150:                 tcb->state = TS_WAIT;
  151:                 break;
  152: 
  153:           default:
  154:                 ercd = E_SYS;
  155:                 break;
  156:         }
  157:         END_CRITICAL_SECTION;
  158: 
  159:         return ercd;
  160: }
  161: 
  162: /* ------------------------------------------------------------------------ */
  163: 
  164: /*
  165:  * Definition of task wait specification
  166:  */
  167: LOCAL CONST WSPEC wspec_slp = { TTW_SLP, NULL, NULL };
  168: 
  169: /*
  170:  * Move its own task state to wait state
  171:  */
  172: SYSCALL ER _tk_slp_tsk( TMO tmout )
  173: {
  174:         return _tk_slp_tsk_u(to_usec_tmo(tmout));
  175: }
  176: 
  177: SYSCALL ER _tk_slp_tsk_u( TMO_U tmout )
  178: {
  179:         ER     ercd = E_OK;
  180: 
  181:         CHECK_TMOUT(tmout);
  182:         CHECK_DISPATCH();
  183: 
  184:         BEGIN_CRITICAL_SECTION;
  185:         /* Check wait disable */
  186:         if ( (ctxtsk->waitmask & TTW_SLP) != 0 ) {
  187:                 ercd = E_DISWAI;
  188:                 goto error_exit;
  189:         }
  190: 
  191:         if ( ctxtsk->wupcnt > 0 ) {
  192:                 ctxtsk->wupcnt--;
  193:         } else {
  194:                 ercd = E_TMOUT;
  195:                 if ( tmout != TMO_POL ) {
  196:                         ctxtsk->wspec = &wspec_slp;
  197:                         ctxtsk->wid = 0;
  198:                         ctxtsk->wercd = &ercd;
  199:                         make_wait(tmout, TA_NULL);
  200:                         QueInit(&ctxtsk->tskque);
  201:                 }
  202:         }
  203: 
  204:     error_exit:
  205:         END_CRITICAL_SECTION;
  206: 
  207:         return ercd;
  208: }
  209: 
  210: /*
  211:  * Wakeup task
  212:  */
  213: SYSCALL ER _tk_wup_tsk( ID tskid )
  214: {
  215:         TCB    *tcb;
  216:         TSTAT  state;
  217:         ER     ercd = E_OK;
  218: 
  219:         CHECK_TSKID(tskid);
  220:         CHECK_NONSELF(tskid);
  221: 
  222:         tcb = get_tcb(tskid);
  223: 
  224:         BEGIN_CRITICAL_SECTION;
  225:         state = (TSTAT)tcb->state;
  226:         if ( !task_alive(state) ) {
  227:                 ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;
  228: 
  229:         } else if ( (state & TS_WAIT) != 0 && tcb->wspec == &wspec_slp ) {
  230:                 wait_release_ok(tcb);
  231: 
  232:         } else if ( tcb->wupcnt == INT_MAX ) {
  233:                 ercd = E_QOVR;
  234:         } else {
  235:                 ++tcb->wupcnt;
  236:         }
  237:         END_CRITICAL_SECTION;
  238: 
  239:         return ercd;
  240: }
  241: 
  242: /*
  243:  * Cancel wakeup request
  244:  */
  245: SYSCALL INT _tk_can_wup( ID tskid )
  246: {
  247:         TCB    *tcb;
  248:         ER     ercd = E_OK;
  249: 
  250:         CHECK_TSKID_SELF(tskid);
  251: 
  252:         tcb = get_tcb_self(tskid);
  253: 
  254:         BEGIN_CRITICAL_SECTION;
  255:         switch ( tcb->state ) {
  256:           case TS_NONEXIST:
  257:                 ercd = E_NOEXS;
  258:                 break;
  259:           case TS_DORMANT:
  260:                 ercd = E_OBJ;
  261:                 break;
  262: 
  263:           default:
  264:                 ercd = tcb->wupcnt;
  265:                 tcb->wupcnt = 0;
  266:         }
  267:         END_CRITICAL_SECTION;
  268: 
  269:         return ercd;
  270: }
  271: 
  272: /* ------------------------------------------------------------------------ */
  273: 
  274: #define toTTW(evtmask)          ( (UINT)(evtmask) << 16 )
  275: #define toEVT(tskwait)          ( (UB)((tskwait) >> 16) )
  276: 
  277: /*
  278:  * Wait for task event
  279:  */
  280: SYSCALL INT _tk_wai_tev( INT waiptn, TMO tmout )
  281: {
  282:         return _tk_wai_tev_u(waiptn, to_usec_tmo(tmout));
  283: }
  284: 
  285: SYSCALL INT _tk_wai_tev_u( INT waiptn, TMO_U tmout )
  286: {
  287:         WSPEC  wspec;
  288:         ER     ercd;
  289: 
  290:         CHECK_TMOUT(tmout);
  291:         CHECK_PAR((((UINT)waiptn & ~0x000000ffU) == 0)&&(((UINT)waiptn & 0x000000FFU) != 0));
  292:         CHECK_DISPATCH();
  293: 
  294:         BEGIN_CRITICAL_SECTION;
  295:         /* Check wait disable */
  296:         if ( (ctxtsk->waitmask & toTTW(waiptn)) != 0 ) {
  297:                 ercd = E_DISWAI;
  298:                 goto error_exit;
  299:         }
  300: 
  301:         if ( (ctxtsk->tskevt & waiptn) != 0 ) {
  302:                 ercd = ctxtsk->tskevt;
  303:                 ctxtsk->tskevt &= ~waiptn;
  304:         } else {
  305:                 ercd = E_TMOUT;
  306:                 if ( tmout != TMO_POL ) {
  307:                         wspec.tskwait = toTTW(waiptn);
  308:                         wspec.chg_pri_hook = NULL;
  309:                         wspec.rel_wai_hook = NULL;
  310:                         ctxtsk->wspec = &wspec;
  311:                         ctxtsk->wid = 0;
  312:                         ctxtsk->wercd = &ercd;
  313:                         make_wait(tmout, TA_NULL);
  314:                         QueInit(&ctxtsk->tskque);
  315:                 }
  316:         }
  317: 
  318:     error_exit:
  319:         END_CRITICAL_SECTION;
  320: 
  321:         return ercd;
  322: }
  323: 
  324: /*
  325:  * Send task event
  326:  */
  327: SYSCALL ER _tk_sig_tev( ID tskid, INT tskevt )
  328: {
  329:         UINT   evtmsk;
  330:         TCB    *tcb;
  331:         TSTAT  state;
  332:         ER     ercd = E_OK;
  333: 
  334:         CHECK_TSKID_SELF(tskid);
  335:         CHECK_PAR(tskevt >= 1 && tskevt <= 8);
  336: 
  337:         evtmsk = (UINT)(1 << (tskevt - 1));
  338:         tcb = get_tcb_self(tskid);
  339: 
  340:         BEGIN_CRITICAL_SECTION;
  341:         state = (TSTAT)tcb->state;
  342:         if ( !task_alive(state) ) {
  343:                 ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;
  344:                 goto error_exit;
  345:         }
  346: 
  347:         if ( (state & TS_WAIT) != 0 && (tcb->wspec->tskwait & toTTW(evtmsk)) != 0 ) {
  348:                 wait_release_ok_ercd(tcb, (ER)(tcb->tskevt | evtmsk));
  349:         } else {
  350:                 tcb->tskevt |= evtmsk;
  351:         }
  352: 
  353:     error_exit:
  354:         END_CRITICAL_SECTION;
  355: 
  356:         return ercd;
  357: }