version 1.1, 2007/11/19 15:54:33 |
version 1.2, 2007/11/20 16:07:24 |
|
|
*/ |
*/ |
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/kern_sched.h> |
#include <sys/kern_sched.h> |
|
#include <sys/kern_time.h> /* for HZ */ |
|
#include <sys/mem.h> |
|
|
#include <libkern/printf.h> |
#include <libkern/printf.h> |
|
|
|
|
|
/* config.c gives us tasks that we'll schedule */ |
|
extern struct u_task config_tasklist[]; |
|
|
|
/* list of k_tasks */ |
|
struct k_task *ktasklist; |
|
|
|
/* pcb of running task; we will save context there when enter irq_mode */ |
|
uint32_t *curpcb; |
|
|
|
/* total tasks; used to TID generation */ |
|
uint8_t ntasks; |
|
|
|
/* "idle" task exists forever and occupy cpu when there is no other task pretending. */ |
|
const struct u_task idle_utask = {"idle", 0, NULL}; |
|
|
|
|
|
void |
|
sched_init(void) |
|
{ |
|
/* |
|
* Create struct k_task for each u_task that user described in config_tasklist. |
|
*/ |
|
struct u_task *utaskp; |
|
struct k_task *ktaskp, *oldktaskp; |
|
|
|
ntasks = 0; |
|
|
|
/* |
|
* Create an "idle" task which always has TID 0. |
|
*/ |
|
ktaskp = kmalloc(sizeof(struct k_task)); |
|
|
|
if (ktaskp == NULL) |
|
panic("can't allocate memory for idle task\n"); |
|
|
|
/* link u_task for idle task */ |
|
ktaskp->kt_utask = (struct u_task *)&idle_utask; |
|
|
|
/* TID (always 0) */ |
|
ktaskp->kt_tid = 0; |
|
|
|
/* idle task is always in state READY (or RUNNING, if on processor now) */ |
|
ktaskp->kt_state = TASK_READY; |
|
|
|
/* next task in list isn't up yet (and prev too) */ |
|
ktaskp->kt_next = NULL; |
|
|
|
/* make "idle" task first task in ktasklist, system k_task list */ |
|
ktasklist = ktaskp; |
|
|
|
/* bump ntasks to 1 */ |
|
ntasks = 1; |
|
|
|
/* preserve pointer to this k_task so we can link-in next task */ |
|
oldktaskp = ktaskp; |
|
|
|
/* |
|
* Idle task set up completed. |
|
* Configure all other system tasks, |
|
*/ |
|
|
|
/* look through tasklist */ |
|
utaskp = config_tasklist; |
|
while(utaskp->ut_name != NULL) { |
|
|
|
/* try to allocate memory for ktask */ |
|
ktaskp = kmalloc(sizeof(struct k_task)); |
|
|
|
if (ktaskp == NULL) |
|
panic("can't allocate memory for task '%s'\n", utaskp->ut_name); |
|
|
|
/* |
|
* Successfully allocated new ktask. |
|
*/ |
|
|
|
/* link u_task */ |
|
ktaskp->kt_utask = utaskp; |
|
|
|
/* set TID (Task Identificator) */ |
|
ktaskp->kt_tid = oldktaskp->kt_tid + 1; |
|
|
|
/* state */ |
|
ktaskp->kt_state = TASK_READY; |
|
|
|
/* link current task in previous task's structure */ |
|
oldktaskp->kt_next = ktaskp; |
|
|
|
/* NULLify kt_next of current task */ |
|
ktaskp->kt_next = NULL; |
|
|
|
/* save current ktask for use with next ktask */ |
|
oldktaskp = ktaskp; |
|
|
|
/* bump ntasks */ |
|
ntasks++; |
|
|
|
/* shift to next element in config_tasklist[] */ |
|
utaskp++; |
|
} |
|
|
|
/* 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); |
|
|
|
/* 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); |
|
|
|
if (ktaskp->kt_tid == NULL) /* that was an "idle" task */ |
|
break; |
|
|
|
ktaskp = ktaskp->kt_next; |
|
} while(1); |
|
|
|
printf("; HZ=%d\n", HZ); |
|
|
|
} |
|
|