1:     2:     3:     4:     5:     6:     7:     8:     9:    10:    11:    12:    13: 
   14: 
   15:    16:    17:    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:    31: 
   32: EXPORT INT      dispatch_disabled;   
   33: 
   34:    35:    36: 
   37: EXPORT TCB      *ctxtsk;     
   38: EXPORT TCB      *schedtsk;   
   39: EXPORT RDYQUE   ready_queue;      
   40: 
   41:    42:    43: 
   44: EXPORT TCB      *tcb_table;  
   45: EXPORT QUEUE    free_tcb;  
   46: EXPORT ID       max_tskid;    
   47: 
   48: EXPORT INT      default_sstksz;      
   49: EXPORT INT      svc_call_limit;      
   50: 
   51:    52:    53: 
   54: EXPORT ER task_initialize( void )
   55: {
   56:         INT    i;
   57:         TCB    *tcb;
   58:         ID     tskid;
   59: 
   60:         
   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:         
   75:         tcb_table = Imalloc((UINT)NUM_TSKID * sizeof(TCB));
   76:         if ( tcb_table == NULL ) {
   77:                 return E_NOMEM;
   78:         }
   79: 
   80:         
   81:         ctxtsk = schedtsk = NULL;
   82:         ready_queue_initialize(&ready_queue);
   83:         dispatch_disabled = DDS_ENABLE;
   84: 
   85:         
   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:   105: 
  106: EXPORT void make_dormant( TCB *tcb )
  107: {
  108:         
  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;       
  130: 
  131:         tcb->texhdr    = NULL; 
  132:         tcb->texmask   = 0;
  133:         tcb->pendtex   = 0;
  134:         tcb->exectex   = 0;
  135:         tcb->texflg    = 0;
  136:         tcb->execssid  = 0;
  137: 
  138:         
  139:         setup_context(tcb);
  140: }
  141: 
  142: 
  143: 
  144:   145:   146:   147:   148:   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; 
  161: }
  162: 
  163:   164:   165:   166: 
  167: Inline void reschedule( void )
  168: {
  169:         TCB    *toptsk;
  170: 
  171:         toptsk = ready_queue_top(&ready_queue);
  172:         if ( schedtsk != toptsk ) {
  173:                   174:   175:   176: 
  177:                 if ( schedtsk == ctxtsk ) {
  178:                         time_slice_schedule(schedtsk);
  179:                 }
  180: 
  181:                 schedtsk = toptsk;
  182:                 dispatch_request();
  183:         }
  184: }
  185: 
  186:   187:   188:   189:   190: 
  191: EXPORT void make_ready( TCB *tcb )
  192: {
  193:         tcb->state = TS_READY;
  194:         if ( ready_queue_insert(&ready_queue, tcb) ) {
  195:                   196:   197:   198: 
  199:                 if ( schedtsk == ctxtsk ) {
  200:                         time_slice_schedule(schedtsk);
  201:                 }
  202: 
  203:                 schedtsk = tcb;
  204:                 dispatch_request();
  205:         }
  206: }
  207: 
  208:   209:   210:   211:   212:   213:   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:   226: 
  227: EXPORT void change_task_priority( TCB *tcb, INT priority )
  228: {
  229:         INT    oldpri;
  230: 
  231:         if ( tcb->state == TS_READY ) {
  232:                   233:   234:   235:   236:   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:                   247: 
  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:   256: 
  257: EXPORT void rotate_ready_queue( INT priority )
  258: {
  259:         ready_queue_rotate(&ready_queue, priority);
  260:         reschedule();
  261: }
  262: 
  263:   264:   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:   278: 
  279: #if USE_DBGSPT
  280: 
  281:   282:   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