gonzui


Format: Advanced Search

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

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    micro T-Kernel 3.00.02
    4:  *
    5:  *    Copyright (C) 2006-2020 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.2.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2020/10.
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: 
   14: /*
   15:  *      task_manage.c
   16:  *      Task Management Function
   17:  */
   18: 
   19: #include "kernel.h"
   20: #include "wait.h"
   21: #include "check.h"
   22: #include <tm/tmonitor.h>
   23: 
   24: #include "../sysdepend/cpu_task.h"
   25: 
   26: /*
   27:  * Create task
   28:  */
   29: SYSCALL ID tk_cre_tsk( CONST T_CTSK *pk_ctsk )
   30: {
   31: #if CHK_RSATR
   32:         const ATR VALID_TSKATR = {     /* Valid value of task attribute */
   33:                  TA_HLNG
   34:                 |TA_RNG3
   35:                 |TA_USERBUF
   36:                 |TA_COPS
   37: #if USE_OBJECT_NAME
   38:                 |TA_DSNAME
   39: #endif
   40:         };
   41: #endif
   42:         TCB    *tcb;
   43:         W      sstksz;
   44:         void   *stack;
   45:         ER     ercd;
   46: 
   47:         CHECK_RSATR(pk_ctsk->tskatr, VALID_TSKATR);
   48: #if !USE_IMALLOC
   49:         /* TA_USERBUF must be specified if configured in no Imalloc */
   50:         CHECK_PAR((pk_ctsk->tskatr & TA_USERBUF) != 0);
   51: #endif
   52:         CHECK_PRI(pk_ctsk->itskpri);
   53: 
   54:         sstksz = pk_ctsk->stksz + DEFAULT_SYS_STKSZ;
   55:         CHECK_PAR(sstksz >= MIN_SYS_STACK_SIZE);
   56: 
   57:         if ( (pk_ctsk->tskatr & TA_USERBUF) != 0 ) {
   58:                 /* Use user buffer */
   59:                 stack = pk_ctsk->bufptr;
   60:         } else {
   61: #if USE_IMALLOC
   62:                 /* Allocate system stack area */
   63:                 sstksz  = (sstksz  + 7) / 8 * 8;      /* Align to a multiple of 8 */
   64:                 stack = knl_Imalloc((UW)sstksz);
   65:                 if ( stack == NULL ) {
   66:                         return E_NOMEM;
   67:                 }
   68: #endif
   69:         }
   70: 
   71:         BEGIN_CRITICAL_SECTION;
   72:         /* Get control block from FreeQue */
   73:         tcb = (TCB*)QueRemoveNext(&knl_free_tcb);
   74:         if ( tcb == NULL ) {
   75:                 ercd = E_LIMIT;
   76:                 goto error_exit;
   77:         }
   78: 
   79:         /* Initialize control block */
   80:         tcb->exinf     = pk_ctsk->exinf;
   81:         tcb->tskatr    = pk_ctsk->tskatr;
   82:         tcb->task      = pk_ctsk->task;
   83:         tcb->ipriority = (UB)int_priority(pk_ctsk->itskpri);
   84:         tcb->sstksz    = sstksz;
   85: #if USE_OBJECT_NAME
   86:         if ( (pk_ctsk->tskatr & TA_DSNAME) != 0 ) {
   87:                 knl_strncpy((char*)tcb->name, (char*)pk_ctsk->dsname, OBJECT_NAME_LENGTH);
   88:         }
   89: #endif
   90: 
   91:         /* Set stack pointer */
   92:         tcb->isstack = (VB*)stack + sstksz;
   93: 
   94:         /* Set initial value of task operation mode */
   95:         tcb->isysmode = 1;
   96:         tcb->sysmode  = 1;
   97: 
   98:         /* make it to DORMANT state */
   99:         knl_make_dormant(tcb);
  100: 
  101:         ercd = tcb->tskid;
  102: 
  103:     error_exit:
  104:         END_CRITICAL_SECTION;
  105: 
  106: #if USE_IMALLOC
  107:         if ( (ercd < E_OK) && ((pk_ctsk->tskatr & TA_USERBUF) == 0) ) {
  108:                 knl_Ifree(stack);
  109:         }
  110: #endif
  111: 
  112:         return ercd;
  113: }
  114: 
  115: /*
  116:  * Task deletion
  117:  *      Call from critical section
  118:  */
  119: LOCAL void knl_del_tsk( TCB *tcb )
  120: {
  121: #if USE_IMALLOC
  122:         if ( (tcb->tskatr & TA_USERBUF) == 0 ) {
  123:                 /* User buffer is not used */
  124:                 /* Free system stack */
  125:                 void *stack = (VB*)tcb->isstack - tcb->sstksz;
  126:                 knl_Ifree(stack);
  127:         }
  128: #endif
  129: 
  130:         /* Return control block to FreeQue */
  131:         QueInsert(&tcb->tskque, &knl_free_tcb);
  132:         tcb->state = TS_NONEXIST;
  133: }
  134: 
  135: #ifdef USE_FUNC_TK_DEL_TSK
  136: /*
  137:  * Delete task 
  138:  */
  139: SYSCALL ER tk_del_tsk( ID tskid )
  140: {
  141:         TCB    *tcb;
  142:         TSTAT  state;
  143:         ER     ercd = E_OK;
  144: 
  145:         CHECK_TSKID(tskid);
  146:         CHECK_NONSELF(tskid);
  147: 
  148:         tcb = get_tcb(tskid);
  149: 
  150:         BEGIN_CRITICAL_SECTION;
  151:         state = (TSTAT)tcb->state;
  152:         if ( state != TS_DORMANT ) {
  153:                 ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;
  154:         } else {
  155:                 knl_del_tsk(tcb);
  156:         }
  157:         END_CRITICAL_SECTION;
  158: 
  159:         return ercd;
  160: }
  161: #endif /* USE_FUNC_TK_DEL_TSK */
  162: 
  163: /* ------------------------------------------------------------------------ */
  164: 
  165: /*
  166:  * Start task
  167:  */
  168: SYSCALL ER tk_sta_tsk( ID tskid, INT stacd )
  169: {
  170:         TCB    *tcb;
  171:         TSTAT  state;
  172:         ER     ercd = E_OK;
  173: 
  174:         CHECK_TSKID(tskid);
  175:         CHECK_NONSELF(tskid);
  176: 
  177:         tcb = get_tcb(tskid);
  178: 
  179:         BEGIN_CRITICAL_SECTION;
  180:         state = (TSTAT)tcb->state;
  181:         if ( state != TS_DORMANT ) {
  182:                 ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;
  183:         } else {
  184:                 knl_setup_stacd(tcb, stacd);
  185:                 knl_make_ready(tcb);
  186:         }
  187:         END_CRITICAL_SECTION;
  188: 
  189:         return ercd;
  190: }
  191: 
  192: /*
  193:  * Task finalization
  194:  *      Call from critical section
  195:  */
  196: LOCAL void knl_ter_tsk( TCB *tcb )
  197: {
  198:         TSTAT  state;
  199: 
  200:         state = (TSTAT)tcb->state;
  201:         if ( state == TS_READY ) {
  202:                 knl_make_non_ready(tcb);
  203: 
  204:         } else if ( (state & TS_WAIT) != 0 ) {
  205:                 knl_wait_cancel(tcb);
  206:                 if ( tcb->wspec->rel_wai_hook != NULL ) {
  207:                         (*tcb->wspec->rel_wai_hook)(tcb);
  208:                 }
  209:         }
  210: 
  211: #if USE_MUTEX == 1
  212:         /* signal mutex */
  213:         knl_signal_all_mutex(tcb);
  214: #endif
  215: 
  216:         knl_cleanup_context(tcb);
  217: }
  218: 
  219: #ifdef USE_FUNC_TK_EXT_TSK
  220: /*
  221:  * End its own task
  222:  */
  223: SYSCALL void tk_ext_tsk( void )
  224: {
  225: #ifdef DORMANT_STACK_SIZE
  226:         /* To avoid destroying stack used in 'knl_make_dormant', 
  227:            allocate the dummy area on the stack. */
  228:         volatile VB _dummy[DORMANT_STACK_SIZE];
  229: #endif
  230: 
  231:         /* Check context error */
  232: #if CHK_CTX2
  233:         if ( in_indp() ) {
  234:                 SYSTEM_MESSAGE("tk_ext_tsk was called in the task independent\n");
  235:                 return;
  236:         }
  237: #endif
  238: #if CHK_CTX1
  239:         if ( in_ddsp() ) {
  240:                 SYSTEM_MESSAGE("tk_ext_tsk was called in the dispatch disabled\n");
  241:         }
  242: #endif
  243: 
  244:         DISABLE_INTERRUPT;
  245:         knl_ter_tsk(knl_ctxtsk);
  246:         knl_make_dormant(knl_ctxtsk);
  247: 
  248:         knl_force_dispatch();
  249:         /* No return */
  250: 
  251: #ifdef DORMANT_STACK_SIZE
  252:         /* Avoid WARNING (This code does not execute) */
  253:         _dummy[0] = _dummy[0];
  254: #endif
  255: }
  256: #endif /* USE_FUNC_TK_EXT_TSK */
  257: 
  258: #ifdef USE_FUNC_TK_EXD_TSK
  259: /*
  260:  * End and delete its own task
  261:  */
  262: SYSCALL void tk_exd_tsk( void )
  263: {
  264:         /* Check context error */
  265: #if CHK_CTX2
  266:         if ( in_indp() ) {
  267:                 SYSTEM_MESSAGE("tk_exd_tsk was called in the task independent\n");
  268:                 return;
  269:         }
  270: #endif
  271: #if CHK_CTX1
  272:         if ( in_ddsp() ) {
  273:                 SYSTEM_MESSAGE("tk_exd_tsk was called in the dispatch disabled\n");
  274:         }
  275: #endif
  276: 
  277:         DISABLE_INTERRUPT;
  278:         knl_ter_tsk(knl_ctxtsk);
  279:         knl_del_tsk(knl_ctxtsk);
  280: 
  281:         knl_force_dispatch();
  282:         /* No return */
  283: }
  284: #endif /* USE_FUNC_TK_EXD_TSK */
  285: 
  286: #ifdef USE_FUNC_TK_TER_TSK
  287: /*
  288:  * Termination of other task
  289:  */
  290: SYSCALL ER tk_ter_tsk( ID tskid )
  291: {
  292:         TCB    *tcb;
  293:         TSTAT  state;
  294:         ER     ercd = E_OK;
  295: 
  296:         CHECK_TSKID(tskid);
  297:         CHECK_NONSELF(tskid);
  298: 
  299:         tcb = get_tcb(tskid);
  300: 
  301:         BEGIN_CRITICAL_SECTION;
  302:         state = (TSTAT)tcb->state;
  303:         if ( !knl_task_alive(state) ) {
  304:                 ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;
  305:         } else if ( tcb->klocked ) {
  306:                 /* Normally, it does not become this state.
  307:                  * When the state is page-in wait in the virtual memory
  308:                  * system and when trying to terminate any task,
  309:                  * it becomes this state.
  310:                  */
  311:                 ercd = E_OBJ;
  312:         } else {
  313:                 knl_ter_tsk(tcb);
  314:                 knl_make_dormant(tcb);
  315:         }
  316:         END_CRITICAL_SECTION;
  317: 
  318:         return ercd;
  319: }
  320: #endif /* USE_FUNC_TK_TER_TSK */
  321: 
  322: /* ------------------------------------------------------------------------ */
  323: 
  324: #ifdef USE_FUNC_TK_CHG_PRI
  325: /*
  326:  * Change task priority
  327:  */
  328: SYSCALL ER tk_chg_pri( ID tskid, PRI tskpri )
  329: {
  330:         TCB    *tcb;
  331:         INT    priority;
  332:         ER     ercd;
  333: 
  334:         CHECK_TSKID_SELF(tskid);
  335:         CHECK_PRI_INI(tskpri);
  336: 
  337:         tcb = get_tcb_self(tskid);
  338: 
  339:         BEGIN_CRITICAL_SECTION;
  340:         if ( tcb->state == TS_NONEXIST ) {
  341:                 ercd = E_NOEXS;
  342:                 goto error_exit;
  343:         }
  344: 
  345:         /* Conversion priority to internal expression */
  346:         if ( tskpri == TPRI_INI ) {
  347:                 priority = tcb->ipriority;
  348:         } else {
  349:                 priority = int_priority(tskpri);
  350:         }
  351: 
  352: #if USE_MUTEX == 1
  353:         /* Mutex priority change limit */
  354:         ercd = knl_chg_pri_mutex(tcb, priority);
  355:         if ( ercd < E_OK ) {
  356:                 goto error_exit;
  357:         }
  358: 
  359:         tcb->bpriority = (UB)priority;
  360:         priority = ercd;
  361: #else
  362:         tcb->bpriority = priority;
  363: #endif
  364: 
  365:         /* Change priority */
  366:         knl_change_task_priority(tcb, priority);
  367: 
  368:         ercd = E_OK;
  369:     error_exit:
  370:         END_CRITICAL_SECTION;
  371: 
  372:         return ercd;
  373: }
  374: #endif /* USE_FUNC_TK_CHG_PRI */
  375: 
  376: #ifdef USE_FUNC_TK_ROT_RDQ
  377: /*
  378:  * Rotate ready queue
  379:  */
  380: SYSCALL ER tk_rot_rdq( PRI tskpri )
  381: {
  382:         CHECK_PRI_RUN(tskpri);
  383: 
  384:         BEGIN_CRITICAL_SECTION;
  385:         if ( tskpri == TPRI_RUN ) {
  386:                 if ( in_indp() ) {
  387:                         knl_rotate_ready_queue_run();
  388:                 } else {
  389:                         knl_rotate_ready_queue(knl_ctxtsk->priority);
  390:                 }
  391:         } else {
  392:                 knl_rotate_ready_queue(int_priority(tskpri));
  393:         }
  394:         END_CRITICAL_SECTION;
  395: 
  396:         return E_OK;
  397: }
  398: #endif /* USE_FUNC_TK_ROT_RDQ */
  399: 
  400: /* ------------------------------------------------------------------------ */
  401: 
  402: #ifdef USE_FUNC_TK_GET_TID
  403: /*
  404:  * Refer task ID at execution
  405:  */
  406: SYSCALL ID tk_get_tid( void )
  407: {
  408:         return ( knl_ctxtsk == NULL )? 0: knl_ctxtsk->tskid;
  409: }
  410: #endif /* USE_FUNC_TK_GET_TID */
  411: 
  412: #ifdef USE_FUNC_TK_REF_TSK
  413: /*
  414:  * Refer task state
  415:  */
  416: SYSCALL ER tk_ref_tsk( ID tskid, T_RTSK *pk_rtsk )
  417: {
  418:         TCB    *tcb;
  419:         TSTAT  state;
  420:         ER     ercd = E_OK;
  421: 
  422:         CHECK_TSKID_SELF(tskid);
  423: 
  424:         tcb = get_tcb_self(tskid);
  425: 
  426:         knl_memset(pk_rtsk, 0, sizeof(*pk_rtsk));
  427: 
  428:         BEGIN_CRITICAL_SECTION;
  429:         state = (TSTAT)tcb->state;
  430:         if ( state == TS_NONEXIST ) {
  431:                 ercd = E_NOEXS;
  432:         } else {
  433:                 if ( ( state == TS_READY ) && ( tcb == knl_ctxtsk ) ) {
  434:                         pk_rtsk->tskstat = TTS_RUN;
  435:                 } else {
  436:                         pk_rtsk->tskstat = (UINT)state << 1;
  437:                 }
  438:                 if ( (state & TS_WAIT) != 0 ) {
  439:                         pk_rtsk->tskwait = tcb->wspec->tskwait;
  440:                         pk_rtsk->wid     = tcb->wid;
  441:                 }
  442:                 pk_rtsk->exinf     = tcb->exinf;
  443:                 pk_rtsk->tskpri    = ext_tskpri(tcb->priority);
  444:                 pk_rtsk->tskbpri   = ext_tskpri(tcb->bpriority);
  445:                 pk_rtsk->wupcnt    = tcb->wupcnt;
  446:                 pk_rtsk->suscnt    = tcb->suscnt;
  447:         }
  448:         END_CRITICAL_SECTION;
  449: 
  450:         return ercd;
  451: }
  452: #endif /* USE_FUNC_TK_REF_TSK */
  453: 
  454: /* ------------------------------------------------------------------------ */
  455: 
  456: 
  457: #ifdef USE_FUNC_TK_REL_WAI
  458: /*
  459:  * Release wait
  460:  */
  461: SYSCALL ER tk_rel_wai( ID tskid )
  462: {
  463:         TCB    *tcb;
  464:         TSTAT  state;
  465:         ER     ercd = E_OK;
  466: 
  467:         CHECK_TSKID(tskid);
  468: 
  469:         tcb = get_tcb(tskid);
  470: 
  471:         BEGIN_CRITICAL_SECTION;
  472:         state = (TSTAT)tcb->state;
  473:         if ( (state & TS_WAIT) == 0 ) {
  474:                 ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;
  475:         } else {
  476:                 knl_wait_release_ng(tcb, E_RLWAI);
  477:         }
  478:         END_CRITICAL_SECTION;
  479: 
  480:         return ercd;
  481: }
  482: #endif /* USE_FUNC_TK_REL_WAI */
  483: 
  484: /* ------------------------------------------------------------------------ */
  485: /*
  486:  *      Debug support function
  487:  */
  488: #if USE_DBGSPT
  489: 
  490: #if USE_OBJECT_NAME
  491: /*
  492:  * Get object name from control block
  493:  */
  494: EXPORT ER knl_task_getname(ID id, UB **name)
  495: {
  496:         TCB    *tcb;
  497:         ER     ercd = E_OK;
  498: 
  499:         CHECK_TSKID_SELF(id);
  500: 
  501:         BEGIN_DISABLE_INTERRUPT;
  502:         tcb = get_tcb_self(id);
  503:         if ( tcb->state == TS_NONEXIST ) {
  504:                 ercd = E_NOEXS;
  505:                 goto error_exit;
  506:         }
  507:         if ( (tcb->tskatr & TA_DSNAME) == 0 ) {
  508:                 ercd = E_OBJ;
  509:                 goto error_exit;
  510:         }
  511:         *name = tcb->name;
  512: 
  513:     error_exit:
  514:         END_DISABLE_INTERRUPT;
  515: 
  516:         return ercd;
  517: }
  518: #endif /* USE_OBJECT_NAME */
  519: 
  520: #ifdef USE_FUNC_TD_LST_TSK
  521: /*
  522:  * Refer task usage state
  523:  */
  524: SYSCALL INT td_lst_tsk( ID list[], INT nent )
  525: {
  526:         TCB    *tcb, *end;
  527:         INT    n = 0;
  528: 
  529:         BEGIN_DISABLE_INTERRUPT;
  530:         end = knl_tcb_table + NUM_TSKID;
  531:         for ( tcb = knl_tcb_table; tcb < end; tcb++ ) {
  532:                 if ( tcb->state == TS_NONEXIST ) {
  533:                         continue;
  534:                 }
  535: 
  536:                 if ( n++ < nent ) {
  537:                         *list++ = tcb->tskid;
  538:                 }
  539:         }
  540:         END_DISABLE_INTERRUPT;
  541: 
  542:         return n;
  543: }
  544: #endif /* USE_FUNC_TD_LST_TSK */
  545: 
  546: #ifdef USE_FUNC_TD_REF_TSK
  547: /*
  548:  * Refer task state
  549:  */
  550: SYSCALL ER td_ref_tsk( ID tskid, TD_RTSK *pk_rtsk )
  551: {
  552:         TCB    *tcb;
  553:         TSTAT  state;
  554:         ER     ercd = E_OK;
  555: 
  556:         CHECK_TSKID_SELF(tskid);
  557: 
  558:         tcb = get_tcb_self(tskid);
  559: 
  560:         knl_memset(pk_rtsk, 0, sizeof(*pk_rtsk));
  561: 
  562:         BEGIN_DISABLE_INTERRUPT;
  563:         state = (TSTAT)tcb->state;
  564:         if ( state == TS_NONEXIST ) {
  565:                 ercd = E_NOEXS;
  566:         } else {
  567:                 if ( ( state == TS_READY ) && ( tcb == knl_ctxtsk ) ) {
  568:                         pk_rtsk->tskstat = TTS_RUN;
  569:                 } else {
  570:                         pk_rtsk->tskstat = (UINT)state << 1;
  571:                 }
  572:                 if ( (state & TS_WAIT) != 0 ) {
  573:                         pk_rtsk->tskwait = tcb->wspec->tskwait;
  574:                         pk_rtsk->wid     = tcb->wid;
  575:                 }
  576:                 pk_rtsk->exinf     = tcb->exinf;
  577:                 pk_rtsk->tskpri    = ext_tskpri(tcb->priority);
  578:                 pk_rtsk->tskbpri   = ext_tskpri(tcb->bpriority);
  579:                 pk_rtsk->wupcnt    = tcb->wupcnt;
  580:                 pk_rtsk->suscnt    = tcb->suscnt;
  581: 
  582:                 pk_rtsk->task      = tcb->task;
  583:                 pk_rtsk->stksz     = tcb->sstksz;
  584:                 pk_rtsk->istack    = tcb->isstack;
  585:         }
  586:         END_DISABLE_INTERRUPT;
  587: 
  588:         return ercd;
  589: }
  590: #endif /* USE_FUNC_TD_REF_TSK */
  591: 
  592: #ifdef USE_FUNC_TD_INF_TSK
  593: /*
  594:  * Get task statistic information
  595:  */
  596: SYSCALL ER td_inf_tsk( ID tskid, TD_ITSK *pk_itsk, BOOL clr )
  597: {
  598:         TCB    *tcb;
  599:         ER     ercd = E_OK;
  600: 
  601:         CHECK_TSKID_SELF(tskid);
  602: 
  603:         tcb = get_tcb_self(tskid);
  604: 
  605:         BEGIN_DISABLE_INTERRUPT;
  606:         if ( tcb->state == TS_NONEXIST ) {
  607:                 ercd = E_NOEXS;
  608:         } else {
  609:                 pk_itsk->stime = tcb->stime;
  610:                 pk_itsk->utime = tcb->utime;
  611:                 if ( clr ) {
  612:                         tcb->stime = 0;
  613:                         tcb->utime = 0;
  614:                 }
  615:         }
  616:         END_DISABLE_INTERRUPT;
  617: 
  618:         return ercd;
  619: }
  620: #endif /* USE_FUNC_TD_INF_TSK */
  621: 
  622: #endif /* USE_DBGSPT */