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 }