=================================================================== RCS file: /cvs/funnyos/kern/kern_sched.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- funnyos/kern/kern_sched.c 2007/11/20 16:07:24 1.2 +++ funnyos/kern/kern_sched.c 2007/11/23 13:37:43 1.3 @@ -1,5 +1,5 @@ /* - * $Id: kern_sched.c,v 1.2 2007/11/20 16:07:24 nbrk Exp $ + * $Id: kern_sched.c,v 1.3 2007/11/23 13:37:43 nbrk Exp $ */ #include #include @@ -8,16 +8,37 @@ #include +/* #define SCHED_DEBUG */ +/* #define SCHED_REGDEBUG */ +#ifdef SCHED_DEBUG +#define DPRINTF(x...) do { printf(x); } while (0) +#else +#define DPRINTF(x...) { } +#endif + +#ifdef SCHED_REGDEBUG +#define DRPRINTF(x...) do { printf(x); } while (0) +#else +#define DRPRINTF(x...) { } +#endif + + /* config.c gives us tasks that we'll schedule */ extern struct u_task config_tasklist[]; /* list of k_tasks */ struct k_task *ktasklist; +/* current running task */ +struct k_task *curktask; + /* pcb of running task; we will save context there when enter irq_mode */ -uint32_t *curpcb; +struct pcb *curpcb; +/* interrupt frame */ +extern struct pcb *iframep; + /* total tasks; used to TID generation */ uint8_t ntasks; @@ -93,6 +114,9 @@ /* state */ ktaskp->kt_state = TASK_READY; + /* set intitial entry point (initial pc) to task_enter */ + ktaskp->kt_pcb.p_pc = (uint32_t)ktaskp->kt_utask->ut_enter; + /* link current task in previous task's structure */ oldktaskp->kt_next = ktaskp; @@ -112,12 +136,12 @@ /* make this list circularly linked (e.g point list's last->next node into first) */ ktaskp->kt_next = ktasklist; - printf("kern_sched: created %d tasks:", ntasks); + DPRINTF("kern_sched: created %d tasks:", ntasks); /* print tasks' names */ ktaskp = ktasklist + 1; /* skip (first) "idle" task (display it as the end of circularly list) */ do { - printf(" %s", ktaskp->kt_utask->ut_name); + DPRINTF(" %s", ktaskp->kt_utask->ut_name); if (ktaskp->kt_tid == NULL) /* that was an "idle" task */ break; @@ -125,7 +149,96 @@ ktaskp = ktaskp->kt_next; } while(1); - printf("; HZ=%d\n", HZ); + DPRINTF("; HZ=%d\n", HZ); + + /* + * Run "idle" task in NOSCHED, so it will not schedule after first context siwtch; + */ + ktasklist->kt_state = TASK_NOSCHED; + curktask = ktasklist; /* ktasklist always points to "idle" task */ + + /* point curpcb */ + curpcb = &ktasklist->kt_pcb; +} + + +void +sched_tick(void) +{ + /* + * Schedule next task that will occupy cpu (if any). + * Remember that we are in IRQ_mode here. + */ + + /* + * All we need to do now is: + * - see if context switch is required + * - if so, save iframe into curpcb (save hardware context) + * - select next task to run + * - point curpcb to pcb of new task + * - point curktask to k_task of new task + * - copy curpcb into iframep (so we'll continue in another task when we exit irq_mode) + * - if context switch is not required + * - XXX we will not copy curpcb into iframep? (cause we end up in same task at next irq) + * - anyway, account time, etc.. + */ + + /* XXX use pre-emtive multitasking to simplify things for now! */ + + /* save hardware state of interrupted task */ + *curpcb = *iframep; + + /* "suspend" interrupted task */ + if(curktask->kt_state == TASK_RUNNING) /* XXX ugly hack to skip "idle" which is NOSCHED */ + curktask->kt_state = TASK_READY; + + DPRINTF("sched_tick: task tid=%d (\"%s\") suspended\n", curktask->kt_tid, curktask->kt_utask->ut_name); + DRPRINTF("r0=0x%x\n", iframep->p_r0); + DRPRINTF("r1=0x%x\n", iframep->p_r1); + DRPRINTF("r2=0x%x\n", iframep->p_r2); + DRPRINTF("r3=0x%x\n", iframep->p_r3); + DRPRINTF("r4=0x%x\n", iframep->p_r4); + DRPRINTF("r5=0x%x\n", iframep->p_r5); + DRPRINTF("r6=0x%x\n", iframep->p_r6); + DRPRINTF("r7=0x%x\n", iframep->p_r7); + DRPRINTF("r8=0x%x\n", iframep->p_r8); + DRPRINTF("r9=0x%x\n", iframep->p_r9); + DRPRINTF("r10=0x%x\n", iframep->p_r10); + DRPRINTF("r11=0x%x\n", iframep->p_r11); + DRPRINTF("r12=0x%x\n", iframep->p_r12); + DRPRINTF("pc=0x%x\n", iframep->p_pc); + + /* round-robin select next task in circlelist */ + curktask = curktask->kt_next; + + /* look for next ready task */ + while(curktask->kt_state != TASK_READY) + curktask = curktask->kt_next; + + /* run selected task */ + curktask->kt_state = TASK_RUNNING; + + /* point curpcb into selected task's pcb */ + curpcb = &curktask->kt_pcb; + + /* restore selected task's hardware context into an IRQ stack */ + *iframep = *curpcb; + + DPRINTF("sched_tick: task tid=%d (\"%s\") resumed\n", curktask->kt_tid, curktask->kt_utask->ut_name); + DRPRINTF("r0=0x%x\n", iframep->p_r0); + DRPRINTF("r1=0x%x\n", iframep->p_r1); + DRPRINTF("r2=0x%x\n", iframep->p_r2); + DRPRINTF("r3=0x%x\n", iframep->p_r3); + DRPRINTF("r4=0x%x\n", iframep->p_r4); + DRPRINTF("r5=0x%x\n", iframep->p_r5); + DRPRINTF("r6=0x%x\n", iframep->p_r6); + DRPRINTF("r7=0x%x\n", iframep->p_r7); + DRPRINTF("r8=0x%x\n", iframep->p_r8); + DRPRINTF("r9=0x%x\n", iframep->p_r9); + DRPRINTF("r10=0x%x\n", iframep->p_r10); + DRPRINTF("r11=0x%x\n", iframep->p_r11); + DRPRINTF("r12=0x%x\n", iframep->p_r12); + DRPRINTF("pc=0x%x\n", iframep->p_pc); }