00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00021 #undef SCHED_DEBUG
00022 
00023 #include <stddef.h>
00024 #include <stdio.h>
00025 #include <signal.h>
00026 #include <cubeos.h>
00027 #include <sys_var.h>
00028 #include <context.h>
00029 #include <schedule.h>
00030 #include <kerror.h>
00031 #include <malloc.h>
00032 #include <cubereent.h>
00033 #include <list.h>
00034 
00035 
00036 #define MAGIC 0xbabababa;
00037 
00038 int _LIBC_init_reent();
00039 
00040 struct process _KERN_ptable[MAX_PROCESSNUM];    
00041 
00042 
00043 list _KERN_delta;
00044 list _KERN_prio[MAX_PRIONUM+1];
00045 
00050 void _KERN_taskend ()
00051 {
00052         _KERN_ptable[__MYPID].signal |= SIGKILL;
00053         KERN_schedule ();
00054 }
00055 
00060 regptr
00061 _KERN_initcontext (regptr context, short sr, void *sp, void *function)
00062 {
00063         
00064 
00065         int i;
00066 
00067         void *stack;
00068 
00069         stack = sp;
00070 
00071         for (i = 0; i < PNREGS; i++)
00072                 (*context).regs[i] = 0;         
00073 
00074         (*context).regs[POS_SR] = sr;   
00075 
00076 
00077         (*context).regs[POS_PC] = (unsigned long) function;     
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087         
00088         writeint (stack, (unsigned int) MAGIC);
00089         stack -= 4;
00090         writeint (stack, (unsigned int) _KERN_taskend);
00091 
00092 
00093         (*context).regs[POS_SSP] = (unsigned long) stack;       
00094 
00095 
00096         return context;
00097 }
00098 
00099 
00106 int KERN_create_prio (void *function,int prio)
00107 {                               
00108         int i, j;
00109         short sr;
00110         void *stack;
00111         if ((prio<0)||(prio>MAX_PRIONUM))
00112                 return(-1);
00113 
00114 
00115         disable ();
00116 
00117         
00118         i = 1;
00119         while ((i < MAX_PROCESSNUM) && (_KERN_ptable[i].state != STATE_EMPTY))
00120                 i++;
00121         if (i == MAX_PROCESSNUM) {      
00122                 enable ();
00123                 KERN_complain (ERR_EMERG, "process table full");
00124                 
00125                 return (-1);
00126         }
00127         for (j = 0; j < PNREGS; j++)
00128                 _KERN_ptable[i].regs.regs[j] = 0;       
00129         
00130 
00131         stack = (void *) malloc (TASK_INIT_STACKSIZE);  
00132         if (stack == NULL) {
00133                 enable ();
00134                 KERN_complain (ERR_EMERG, "no room for stack");
00135                 return (-1);
00136         }
00137         sr = TASK_INIT_SR;      
00138         _KERN_ptable[i].irq = TASK_INIT_IRQLVL;         
00139 
00140         _KERN_ptable[i].stack = stack;  
00141 
00142         _KERN_initcontext (&(_KERN_ptable[i].regs), sr, (stack + TASK_INIT_STACKSIZE), function);
00143         _LIBC_init_reent (&_KERN_ptable[i].reent);
00144         _KERN_ptable[i].ppid = getpid ();       
00145 
00146         _KERN_ptable[i].state = STATE_READY;
00147         _KERN_ptable[i].signal = 0;
00148         _KERN_ptable[i].next = NO_TASK;         
00149 
00150         _KERN_ptable[i].time_delta = 0;
00151         _KERN_ptable[i].prio = prio;
00152 
00153 
00154 
00155         LIST_insert_tail (&_KERN_prio[prio], &(_KERN_ptable[i].me));
00156 
00157         enable ();
00158         return i;
00159 }
00160 
00166 int KERN_create (void *function)
00167 {                       
00168 KERN_create_prio (function,0);
00169 }
00170 
00175 void KERN_schedule (void)
00176 {
00177         int old, new;
00178 
00179 
00180 
00181       asm ("move.w %%sr,%0":"=m" (_KERN_context_srsave));
00182         asm ("ori.w #0x0700,%sr");      
00183 
00184 
00185         old = getpid ();
00186         if ((_KERN_ptable[old].state != STATE_RUNNING) && (_KERN_ptable[old].state != STATE_SUSPEND)) {
00187                 
00188               asm ("move.w %0,%%sr": :"m" (_KERN_context_srsave));
00189                 KERN_complain (ERR_PANIC, "scheduler not called from running task");
00190                 return;         
00191 
00192         }
00193         if ((_KERN_ptable[old].signal & (1 << SIGKILL))) {
00194                 free (_KERN_ptable[old].stack);
00195                 LIST_delete (&_KERN_ptable[old].me);
00196                 
00197                 _KERN_ptable[old].state = STATE_EMPTY;
00198         }
00199 
00200 #ifdef PLRR_SCHEDULER
00201 
00202         new = old;
00203         while ((new < MAX_PROCESSNUM) && (_KERN_ptable[new].state != STATE_READY))
00204                 new++;
00205         if (new == MAX_PROCESSNUM) {    
00206                 new = 0;
00207                 while ((new < old) && (_KERN_ptable[new].state != STATE_READY))
00208                         new++;
00209         }
00210 #else
00211 #ifdef RR_SCHEDULER
00212 
00213         {
00214                 int prio = MAX_PRIONUM;
00215                 int quit = 0;
00216                 entry *this;
00217 
00218 #ifdef SCHED_DEBUG
00219                 printf("s%d\n",old);
00220                 printf("task = 0x%x\n",(unsigned int)&(_KERN_ptable[old].me));
00221 #endif
00222                 new = old;
00223 
00224 
00225                 while ((!quit) && (prio >= 0)) {
00226                         
00227                         if (LIST_entries (&_KERN_prio[prio]) > 0) {
00228                                 
00229                                 this = LIST_head (&_KERN_prio[prio]);
00230                                 
00231                                 
00232                                 while (
00233                                               (this) &&
00234                                               (this->data) &&
00235                                               (((struct process *) (this->data))->state != STATE_READY))
00236                                         this = this->next;
00237                                 if (this)
00238                                         quit = 1;       
00239                         }
00240                         prio--;
00241                 }
00242                 if (quit == 1) {        
00243 #ifdef SCHED_DEBUG
00244                         printf("this = %x\n",(unsigned int) this);
00245 #endif
00246                         new = ((struct process *) (this->data))->pid;
00247 #ifdef SCHED_DEBUG
00248                         printf("n%d\n",new);
00249 #endif
00250                 }
00251 
00252         }
00253 #else
00254       asm ("move.w %0,%%sr": :"m" (_KERN_context_srsave));
00255         KERN_complain (ERR_PANIC, "NO Scheduler defined !");
00256 
00257 #endif
00258 #endif
00259         if ((new <0)
00260             ||(new>MAX_PROCESSNUM)
00261             ||(
00262                (_KERN_ptable[new].state!=STATE_READY)
00263                &&(new!=old))) {
00264                         printf("new=%d\n",new);
00265                         if ((new >0)&&(new<MAX_PROCESSNUM))
00266                                 printf("new.state = %d",_KERN_ptable[new].state);
00267                         KERN_complain (ERR_PANIC, "Scheduler did something stupid !");
00268         }
00269         if (old == new) {       
00270                 if (_KERN_ptable[old].state == STATE_EMPTY) {
00271                         
00272                       asm ("move.w %0,%%sr": :"m" (_KERN_context_srsave));
00273                         KERN_complain (ERR_PANIC, "AIEEE, just killed my last task !");
00274                         while (1);
00275                         return; 
00276 
00277                 }
00278               asm ("move.w %0,%%sr": :"m" (_KERN_context_srsave));
00279                 return;
00280         }
00281         if (_KERN_ptable[old].state == STATE_RUNNING) {
00282                 _KERN_ptable[old].state = STATE_READY;
00283                 LIST_insert_tail (&_KERN_prio[_KERN_ptable[old].prio], &_KERN_ptable[old].me);
00284                 
00285         }
00286         __MYPID = new;
00287 
00288         _KERN_ptable[new].state = STATE_RUNNING;
00289         LIST_delete (&_KERN_ptable[new].me);
00290         
00291 
00292 
00293 
00294 
00295         _impure_ptr = &(_KERN_ptable[__MYPID].reent);
00296 
00297         KERN_contextsw (&(_KERN_ptable[old].regs), &(_KERN_ptable[new].regs));
00298 
00299         
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309         return;
00310 
00311 }
00312 
00317 int KERN_schedinit ()
00318 {
00319         int i, j;
00320 
00321 
00322         __MYPID = 0;
00323 
00324 
00325 
00326         LIST_init (&_KERN_delta);
00327         _KERN_delta.type = LIST_TYPE_SYS;
00328 
00329         for (i = 0; i < MAX_PRIONUM; i++) {
00330                 LIST_init (&_KERN_prio[i]);
00331                 _KERN_prio[i].type = LIST_TYPE_PRIO;
00332         }
00333 
00334         
00335         for (i = 0; i < MAX_PROCESSNUM; i++) {
00336                 _KERN_ptable[i].state = STATE_EMPTY;
00337                 for (j = 0; j < PNREGS; j++)
00338                         _KERN_ptable[i].regs.regs[j] = 0;
00339                 _KERN_ptable[i].stack = (void *) 0;
00340                 _KERN_ptable[i].signal = 0;
00341                 _KERN_ptable[i].ppid = 0;
00342                 _KERN_ptable[i].pid = i;
00343                 LIST_makeentry (&_KERN_ptable[i].me);
00344                 _KERN_ptable[i].me.data = &(_KERN_ptable[i]);
00345                 _KERN_ptable[i].me.len = sizeof (_KERN_ptable[i]);
00346         }
00347 
00348         _KERN_ptable[0].state = STATE_RUNNING;
00349         _KERN_ptable[0].prio = 0;
00350         _LIBC_init_reent (&_KERN_ptable[0].reent);
00351         _impure_ptr = &(_KERN_ptable[0].reent);         
00352         return 0;
00353 
00354 }
00355 
00361 int KERN_suspend (int i)
00362 {
00363 
00364         
00365         
00366 
00367 
00368         if ((i < -1) || (i > MAX_PROCESSNUM)){
00369                 printf("cannot suspend %d\n",i);
00370                 return -1;
00371         }
00372         if ((i != -1) && (_KERN_ptable[i].state == STATE_EMPTY)){
00373                 printf("cannot suspend %d: empty\n",i);
00374                 return -1;
00375         }
00376 
00377         if ((i == -1) || (i == __MYPID)) {
00378                 
00379 
00380                 i = __MYPID;
00381                 
00382                 _KERN_ptable[i].state = STATE_SUSPEND;
00383                 KERN_schedule ();
00384                 
00385         } else {
00386                 
00387                 
00388                 disable ();     
00389                 _KERN_ptable[i].state = STATE_SUSPEND;
00390                 if (_KERN_ptable[i].me.list->type == LIST_TYPE_PRIO)
00391                         LIST_delete (&_KERN_ptable[i].me);
00392                 
00393                 
00394                 enable ();
00395         }
00396 
00397         return 0;
00398 }
00399 
00405 int KERN_wakeup (int i)
00406 {
00407 
00408 
00409         if (i > MAX_PROCESSNUM)
00410                 return -1;
00411         if (_KERN_ptable[i].state != STATE_SUSPEND)
00412                 return -1;
00413 
00414         _KERN_ptable[i].state = STATE_READY;
00415         LIST_delete (&_KERN_ptable[i].me);      
00416         LIST_insert_head (&_KERN_prio[_KERN_ptable[i].prio], &_KERN_ptable[i].me);
00417 
00418 
00419         return 0;
00420 }
00421 
00426 int KERN_delta_handler ()
00427 {
00428         int schedflag = 0;
00429 
00430 
00431 
00432         if (LIST_entries (&_KERN_delta) == 0)
00433                 return (0);
00434 
00435         ((struct process *) (LIST_head (&_KERN_delta)->data))->time_delta--;
00436 
00437         while ((LIST_entries (&_KERN_delta) > 0) &&
00438                (((struct process *) (LIST_head (&_KERN_delta)->data))->time_delta == 0)) {
00439                 KERN_wakeup (((struct process *) (LIST_head (&_KERN_delta))->data)->pid);
00440                 schedflag = 1;  
00441 
00442         }
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460 
00461 
00462         if (schedflag)
00463                 return 1;
00464 
00465         return 0;               
00466 }