gonzui


Format: Advanced Search

tkernel_2/kernel/tkernel/src/task.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 TRON Forum(http://www.tron.org/) at 2015/06/01.
   11:  *
   12:  *----------------------------------------------------------------------
   13:  */
   14: 
   15: /*
   16:  *      task.c (T-Kernel/OS)
   17:  *      Task Control
   18:  */
   19: 
   20: #include "kernel.h"
   21: #include "task.h"
   22: #include "wait.h"
   23: #include "ready_queue.h"
   24: #include "cpu_task.h"
   25: #include "tkdev_timer.h"
   26: #include "check.h"
   27: #include <sys/rominfo.h>
   28: 
   29: /*
   30:  * Task dispatch disable state
   31:  */
   32: EXPORT INT      dispatch_disabled;   /* DDS_XXX see task.h */
   33: 
   34: /*
   35:  * Task execution control
   36:  */
   37: EXPORT TCB      *ctxtsk;     /* Task in execution */
   38: EXPORT TCB      *schedtsk;   /* Task which should be executed */
   39: EXPORT RDYQUE   ready_queue;      /* Ready queue */
   40: 
   41: /*
   42:  * Task control information
   43:  */
   44: EXPORT TCB      *tcb_table;  /* Task control block */
   45: EXPORT QUEUE    free_tcb;  /* FreeQue */
   46: EXPORT ID       max_tskid;    /* Maximum task ID */
   47: 
   48: EXPORT INT      default_sstksz;      /* Default system stack size */
   49: EXPORT INT      svc_call_limit;      /* Protect level of system call */
   50: 
   51: /*
   52:  * TCB Initialization
   53:  */
   54: EXPORT ER task_initialize( void )
   55: {
   56:         INT    i;
   57:         TCB    *tcb;
   58:         ID     tskid;
   59: 
   60:         /* Get system information */
   61:         i = _tk_get_cfn(SCTAG_TMAXTSKID, &max_tskid, 1);
   62:         if ( i < 1 || NUM_TSKID < 1 ) {
   63:                 return E_SYS;
   64:         }
   65:         i = _tk_get_cfn(SCTAG_TSYSSTKSZ, &default_sstksz, 1);
   66:         if ( i < 1 || default_sstksz < MIN_SYS_STACK_SIZE ) {
   67:                 return E_SYS;
   68:         }
   69:         i = _tk_get_cfn(SCTAG_TSVCLIMIT, &svc_call_limit, 1);
   70:         if ( i < 1 || svc_call_limit < 0 || svc_call_limit > 3 ) {
   71:                 return E_SYS;
   72:         }
   73: 
   74:         /* Allocate TCB area */
   75:         tcb_table = Imalloc((UINT)NUM_TSKID * sizeof(TCB));
   76:         if ( tcb_table == NULL ) {
   77:                 return E_NOMEM;
   78:         }
   79: 
   80:         /* Initialize task execution control information */
   81:         ctxtsk = schedtsk = NULL;
   82:         ready_queue_initialize(&ready_queue);
   83:         dispatch_disabled = DDS_ENABLE;
   84: 
   85:         /* Register all TCBs onto FreeQue */
   86:         QueInit(&free_tcb);
   87:         for ( tcb = tcb_table, i = 0; i < NUM_TSKID; tcb++, i++ ) {
   88:                 tskid = ID_TSK(i);
   89:                 tcb->tskid = tskid;
   90:                 tcb->state = TS_NONEXIST;
   91: #ifdef NUM_PORID
   92:                 tcb->wrdvno = tskid;
   93: #endif
   94:                 InitSVCLOCK(&tcb->svclock);
   95:                 tcb->svclocked = NULL;
   96: 
   97:                 QueInsert(&tcb->tskque, &free_tcb);
   98:         }
   99: 
  100:         return E_OK;
  101: }
  102: 
  103: /*
  104:  * Prepare task execution.
  105:  */
  106: EXPORT void make_dormant( TCB *tcb )
  107: {
  108:         /* Initialize variables which should be reset at DORMANT state */
  109:         tcb->state     = TS_DORMANT;
  110:         tcb->priority  = tcb->bpriority = tcb->ipriority;
  111:         tcb->sysmode   = tcb->isysmode;
  112:         tcb->wupcnt    = 0;
  113:         tcb->suscnt    = 0;
  114:         tcb->waitmask  = 0;
  115: 
  116:         tcb->nodiswai  = FALSE;
  117:         tcb->klockwait = FALSE;
  118:         tcb->klocked   = FALSE;
  119: 
  120:         tcb->slicetime = 0;
  121:         tcb->stime     = 0;
  122:         tcb->utime     = 0;
  123: 
  124: #ifdef NUM_MTXID
  125:         tcb->mtxlist   = NULL;
  126: #endif
  127:         tcb->tskevt    = 0;
  128: 
  129:         tcb->reqdct    = 0;       /* clear DCT request */
  130: 
  131:         tcb->texhdr    = NULL; /* Undefined task exception handler */
  132:         tcb->texmask   = 0;
  133:         tcb->pendtex   = 0;
  134:         tcb->exectex   = 0;
  135:         tcb->texflg    = 0;
  136:         tcb->execssid  = 0;
  137: 
  138:         /* Set context to start task */
  139:         setup_context(tcb);
  140: }
  141: 
  142: /* ------------------------------------------------------------------------ */
  143: 
  144: /*
  145:  * Scheduling by time slice
  146:  *      Add TIMER_PERIOD to the 'tcb' task's continuous execution
  147:  *      time counter, and then if the counter exceeds the maximum
  148:  *      continuation time, put the task at the end of the ready queue.
  149:  */
  150: EXPORT TCB* time_slice_schedule( TCB *tcb )
  151: {
  152:         if ( tcb != NULL && tcb->slicetime > 0 ) {
  153: 
  154:                 tcb->slicecnt += TIMER_PERIOD;
  155:                 if ( tcb->slicecnt > tcb->slicetime ) {
  156:                         tcb = ready_queue_move_last(&ready_queue, tcb);
  157:                 }
  158:         }
  159: 
  160:         return tcb; /* New head task */
  161: }
  162: 
  163: /*
  164:  * Reselect task to execute
  165:  *      Set 'schedtsk' to the head task at the ready queue.
  166:  */
  167: Inline void reschedule( void )
  168: {
  169:         TCB    *toptsk;
  170: 
  171:         toptsk = ready_queue_top(&ready_queue);
  172:         if ( schedtsk != toptsk ) {
  173:                 /*
  174:                  * When the state becomes RUN to READY,
  175:                  * execute the time slice scheduling.
  176:                  */
  177:                 if ( schedtsk == ctxtsk ) {
  178:                         time_slice_schedule(schedtsk);
  179:                 }
  180: 
  181:                 schedtsk = toptsk;
  182:                 dispatch_request();
  183:         }
  184: }
  185: 
  186: /*
  187:  * Set task to READY state.
  188:  *      Update the task state and insert in the ready queue. If necessary,
  189:  *      update 'schedtsk' and request to start task dispatcher.
  190:  */
  191: EXPORT void make_ready( TCB *tcb )
  192: {
  193:         tcb->state = TS_READY;
  194:         if ( ready_queue_insert(&ready_queue, tcb) ) {
  195:                 /*
  196:                  * When the state becomes RUN to READY,
  197:                  * execute the time slice scheduling.
  198:                  */
  199:                 if ( schedtsk == ctxtsk ) {
  200:                         time_slice_schedule(schedtsk);
  201:                 }
  202: 
  203:                 schedtsk = tcb;
  204:                 dispatch_request();
  205:         }
  206: }
  207: 
  208: /*
  209:  * Set task to non-executable state.
  210:  *      Delete the task from the ready queue.
  211:  *      If the deleted task is 'schedtsk', set 'schedtsk' to the
  212:  *      highest priority task in the ready queue.
  213:  *      'tcb' task must be READY.
  214:  */
  215: EXPORT void make_non_ready( TCB *tcb )
  216: {
  217:         ready_queue_delete(&ready_queue, tcb);
  218:         if ( schedtsk == tcb ) {
  219:                 schedtsk = ready_queue_top(&ready_queue);
  220:                 dispatch_request();
  221:         }
  222: }
  223: 
  224: /*
  225:  * Change task priority.
  226:  */
  227: EXPORT void change_task_priority( TCB *tcb, INT priority )
  228: {
  229:         INT    oldpri;
  230: 
  231:         if ( tcb->state == TS_READY ) {
  232:                 /*
  233:                  * When deleting a task from the ready queue,
  234:                  * a value in the 'priority' field in TCB is needed.
  235:                  * Therefore you need to delete the task from the
  236:                  * ready queue before changing 'tcb->priority.'
  237:                  */
  238:                 ready_queue_delete(&ready_queue, tcb);
  239:                 tcb->priority = (UB)priority;
  240:                 ready_queue_insert(&ready_queue, tcb);
  241:                 reschedule();
  242:         } else {
  243:                 oldpri = tcb->priority;
  244:                 tcb->priority = (UB)priority;
  245: 
  246:                 /* If the hook routine at the task priority change is defined,
  247:                    execute it */
  248:                 if ( (tcb->state & TS_WAIT) != 0 && tcb->wspec->chg_pri_hook) {
  249:                         (*tcb->wspec->chg_pri_hook)(tcb, oldpri);
  250:                 }
  251:         }
  252: }
  253: 
  254: /*
  255:  * Rotate ready queue.
  256:  */
  257: EXPORT void rotate_ready_queue( INT priority )
  258: {
  259:         ready_queue_rotate(&ready_queue, priority);
  260:         reschedule();
  261: }
  262: 
  263: /*
  264:  * Rotate the ready queue including the highest priority task.
  265:  */
  266: EXPORT void rotate_ready_queue_run( void )
  267: {
  268:         if ( schedtsk != NULL ) {
  269:                 ready_queue_rotate(&ready_queue,
  270:                                 ready_queue_top_priority(&ready_queue));
  271:                 reschedule();
  272:         }
  273: }
  274: 
  275: /* ------------------------------------------------------------------------ */
  276: /*
  277:  *      Debug support function
  278:  */
  279: #if USE_DBGSPT
  280: 
  281: /*
  282:  * Refer ready queue
  283:  */
  284: SYSCALL INT _td_rdy_que( PRI pri, ID list[], INT nent )
  285: {
  286:         QUEUE  *q, *tskque;
  287:         INT    n = 0;
  288: 
  289:         CHECK_PRI(pri);
  290: 
  291:         BEGIN_DISABLE_INTERRUPT;
  292:         tskque = &ready_queue.tskque[int_priority(pri)];
  293:         for ( q = tskque->next; q != tskque; q = q->next ) {
  294:                 if ( n++ < nent ) {
  295:                         *(list++) = ((TCB*)q)->tskid;
  296:                 }
  297:         }
  298:         END_DISABLE_INTERRUPT;
  299: 
  300:         return n;
  301: }
  302: 
  303: #endif /* USE_DBGSPT */