Annotation of funnyos/kern/kern_sched.c, Revision 1.3
1.1 nbrk 1: /*
1.3 ! nbrk 2: * $Id: kern_sched.c,v 1.2 2007/11/20 16:07:24 nbrk Exp $
1.1 nbrk 3: */
4: #include <sys/types.h>
5: #include <sys/kern_sched.h>
1.2 nbrk 6: #include <sys/kern_time.h> /* for HZ */
7: #include <sys/mem.h>
1.1 nbrk 8:
9: #include <libkern/printf.h>
10:
1.3 ! nbrk 11: /* #define SCHED_DEBUG */
! 12: /* #define SCHED_REGDEBUG */
! 13:
! 14: #ifdef SCHED_DEBUG
! 15: #define DPRINTF(x...) do { printf(x); } while (0)
! 16: #else
! 17: #define DPRINTF(x...) { }
! 18: #endif
! 19:
! 20: #ifdef SCHED_REGDEBUG
! 21: #define DRPRINTF(x...) do { printf(x); } while (0)
! 22: #else
! 23: #define DRPRINTF(x...) { }
! 24: #endif
! 25:
1.2 nbrk 26:
27: /* config.c gives us tasks that we'll schedule */
28: extern struct u_task config_tasklist[];
29:
30: /* list of k_tasks */
31: struct k_task *ktasklist;
32:
1.3 ! nbrk 33: /* current running task */
! 34: struct k_task *curktask;
! 35:
1.2 nbrk 36: /* pcb of running task; we will save context there when enter irq_mode */
1.3 ! nbrk 37: struct pcb *curpcb;
! 38:
! 39: /* interrupt frame */
! 40: extern struct pcb *iframep;
1.2 nbrk 41:
42: /* total tasks; used to TID generation */
43: uint8_t ntasks;
44:
45: /* "idle" task exists forever and occupy cpu when there is no other task pretending. */
46: const struct u_task idle_utask = {"idle", 0, NULL};
47:
48:
49: void
50: sched_init(void)
51: {
52: /*
53: * Create struct k_task for each u_task that user described in config_tasklist.
54: */
55: struct u_task *utaskp;
56: struct k_task *ktaskp, *oldktaskp;
57:
58: ntasks = 0;
59:
60: /*
61: * Create an "idle" task which always has TID 0.
62: */
63: ktaskp = kmalloc(sizeof(struct k_task));
64:
65: if (ktaskp == NULL)
66: panic("can't allocate memory for idle task\n");
67:
68: /* link u_task for idle task */
69: ktaskp->kt_utask = (struct u_task *)&idle_utask;
70:
71: /* TID (always 0) */
72: ktaskp->kt_tid = 0;
73:
74: /* idle task is always in state READY (or RUNNING, if on processor now) */
75: ktaskp->kt_state = TASK_READY;
76:
77: /* next task in list isn't up yet (and prev too) */
78: ktaskp->kt_next = NULL;
79:
80: /* make "idle" task first task in ktasklist, system k_task list */
81: ktasklist = ktaskp;
82:
83: /* bump ntasks to 1 */
84: ntasks = 1;
85:
86: /* preserve pointer to this k_task so we can link-in next task */
87: oldktaskp = ktaskp;
88:
89: /*
90: * Idle task set up completed.
91: * Configure all other system tasks,
92: */
93:
94: /* look through tasklist */
95: utaskp = config_tasklist;
96: while(utaskp->ut_name != NULL) {
97:
98: /* try to allocate memory for ktask */
99: ktaskp = kmalloc(sizeof(struct k_task));
100:
101: if (ktaskp == NULL)
102: panic("can't allocate memory for task '%s'\n", utaskp->ut_name);
103:
104: /*
105: * Successfully allocated new ktask.
106: */
107:
108: /* link u_task */
109: ktaskp->kt_utask = utaskp;
110:
111: /* set TID (Task Identificator) */
112: ktaskp->kt_tid = oldktaskp->kt_tid + 1;
113:
114: /* state */
115: ktaskp->kt_state = TASK_READY;
116:
1.3 ! nbrk 117: /* set intitial entry point (initial pc) to task_enter */
! 118: ktaskp->kt_pcb.p_pc = (uint32_t)ktaskp->kt_utask->ut_enter;
! 119:
1.2 nbrk 120: /* link current task in previous task's structure */
121: oldktaskp->kt_next = ktaskp;
122:
123: /* NULLify kt_next of current task */
124: ktaskp->kt_next = NULL;
125:
126: /* save current ktask for use with next ktask */
127: oldktaskp = ktaskp;
128:
129: /* bump ntasks */
130: ntasks++;
131:
132: /* shift to next element in config_tasklist[] */
133: utaskp++;
134: }
135:
136: /* make this list circularly linked (e.g point list's last->next node into first) */
137: ktaskp->kt_next = ktasklist;
138:
1.3 ! nbrk 139: DPRINTF("kern_sched: created %d tasks:", ntasks);
1.2 nbrk 140:
141: /* print tasks' names */
142: ktaskp = ktasklist + 1; /* skip (first) "idle" task (display it as the end of circularly list) */
143: do {
1.3 ! nbrk 144: DPRINTF(" %s", ktaskp->kt_utask->ut_name);
1.2 nbrk 145:
146: if (ktaskp->kt_tid == NULL) /* that was an "idle" task */
147: break;
148:
149: ktaskp = ktaskp->kt_next;
150: } while(1);
151:
1.3 ! nbrk 152: DPRINTF("; HZ=%d\n", HZ);
! 153:
! 154: /*
! 155: * Run "idle" task in NOSCHED, so it will not schedule after first context siwtch;
! 156: */
! 157: ktasklist->kt_state = TASK_NOSCHED;
! 158: curktask = ktasklist; /* ktasklist always points to "idle" task */
! 159:
! 160: /* point curpcb */
! 161: curpcb = &ktasklist->kt_pcb;
! 162: }
! 163:
! 164:
! 165: void
! 166: sched_tick(void)
! 167: {
! 168: /*
! 169: * Schedule next task that will occupy cpu (if any).
! 170: * Remember that we are in IRQ_mode here.
! 171: */
! 172:
! 173: /*
! 174: * All we need to do now is:
! 175: * - see if context switch is required
! 176: * - if so, save iframe into curpcb (save hardware context)
! 177: * - select next task to run
! 178: * - point curpcb to pcb of new task
! 179: * - point curktask to k_task of new task
! 180: * - copy curpcb into iframep (so we'll continue in another task when we exit irq_mode)
! 181: * - if context switch is not required
! 182: * - XXX we will not copy curpcb into iframep? (cause we end up in same task at next irq)
! 183: * - anyway, account time, etc..
! 184: */
! 185:
! 186: /* XXX use pre-emtive multitasking to simplify things for now! */
! 187:
! 188: /* save hardware state of interrupted task */
! 189: *curpcb = *iframep;
! 190:
! 191: /* "suspend" interrupted task */
! 192: if(curktask->kt_state == TASK_RUNNING) /* XXX ugly hack to skip "idle" which is NOSCHED */
! 193: curktask->kt_state = TASK_READY;
! 194:
! 195: DPRINTF("sched_tick: task tid=%d (\"%s\") suspended\n", curktask->kt_tid, curktask->kt_utask->ut_name);
! 196: DRPRINTF("r0=0x%x\n", iframep->p_r0);
! 197: DRPRINTF("r1=0x%x\n", iframep->p_r1);
! 198: DRPRINTF("r2=0x%x\n", iframep->p_r2);
! 199: DRPRINTF("r3=0x%x\n", iframep->p_r3);
! 200: DRPRINTF("r4=0x%x\n", iframep->p_r4);
! 201: DRPRINTF("r5=0x%x\n", iframep->p_r5);
! 202: DRPRINTF("r6=0x%x\n", iframep->p_r6);
! 203: DRPRINTF("r7=0x%x\n", iframep->p_r7);
! 204: DRPRINTF("r8=0x%x\n", iframep->p_r8);
! 205: DRPRINTF("r9=0x%x\n", iframep->p_r9);
! 206: DRPRINTF("r10=0x%x\n", iframep->p_r10);
! 207: DRPRINTF("r11=0x%x\n", iframep->p_r11);
! 208: DRPRINTF("r12=0x%x\n", iframep->p_r12);
! 209: DRPRINTF("pc=0x%x\n", iframep->p_pc);
! 210:
! 211: /* round-robin select next task in circlelist */
! 212: curktask = curktask->kt_next;
! 213:
! 214: /* look for next ready task */
! 215: while(curktask->kt_state != TASK_READY)
! 216: curktask = curktask->kt_next;
! 217:
! 218: /* run selected task */
! 219: curktask->kt_state = TASK_RUNNING;
! 220:
! 221: /* point curpcb into selected task's pcb */
! 222: curpcb = &curktask->kt_pcb;
! 223:
! 224: /* restore selected task's hardware context into an IRQ stack */
! 225: *iframep = *curpcb;
! 226:
! 227: DPRINTF("sched_tick: task tid=%d (\"%s\") resumed\n", curktask->kt_tid, curktask->kt_utask->ut_name);
! 228: DRPRINTF("r0=0x%x\n", iframep->p_r0);
! 229: DRPRINTF("r1=0x%x\n", iframep->p_r1);
! 230: DRPRINTF("r2=0x%x\n", iframep->p_r2);
! 231: DRPRINTF("r3=0x%x\n", iframep->p_r3);
! 232: DRPRINTF("r4=0x%x\n", iframep->p_r4);
! 233: DRPRINTF("r5=0x%x\n", iframep->p_r5);
! 234: DRPRINTF("r6=0x%x\n", iframep->p_r6);
! 235: DRPRINTF("r7=0x%x\n", iframep->p_r7);
! 236: DRPRINTF("r8=0x%x\n", iframep->p_r8);
! 237: DRPRINTF("r9=0x%x\n", iframep->p_r9);
! 238: DRPRINTF("r10=0x%x\n", iframep->p_r10);
! 239: DRPRINTF("r11=0x%x\n", iframep->p_r11);
! 240: DRPRINTF("r12=0x%x\n", iframep->p_r12);
! 241: DRPRINTF("pc=0x%x\n", iframep->p_pc);
1.2 nbrk 242:
243: }
1.1 nbrk 244:
CVSweb