这回由启动时初始化的顺序分析涉及几个bootstrap函数的文件。

/kern/arch/mips/mips/ram.c

ram_bootstrap()

21       获取当前内存大小
23-32    内存最大为508MB,因为由于mips体系的原因,超出这个大小,内存将不连续了。
34       lastpaddr为内存最后一个字节的地址
36-40    firstpaddr为firstfree-MIPS_KSEG0,firstfree为当前内核堆栈的栈顶
42-44    打印cpu型号和内存可用值

paddr_t ram_stealmem(unsigned long npages)

66-67    size等于请求页数的字节数
69-71    如果大于可分配空间,就返回0(物理上不非法,但逻辑上非法的地址)
73-76    返回当前firstpaddr的地址,并将firstpaddr后移size个字节

ram_getsize(u_int32_t *lo, u_int32_t *hi)

87-89    将可用空间的起止地址传回,*lo为起始地址,*hi为终止地址。并将firstpaddr和lastpaddr置0,相当于交出空白空间。

/kern/thread/scheduler.c

15-20    声明runqueue来存储运行时task,struct queue定义在了/kern/lib/queue.c (10-15)中:

struct queue {
 int size;
 int nextwrite; // next element to write to (was head)
 int nextread; // next element to read from (was tail)
 void **data;
};

scheduler_boostrap()

28-31    调用q_create(32),生成一个长度为32的队列作为runqueue。如果失败就panic

int scheduler_preallocate(int nthreads)

45       调用q_preallocate()来为nthreads个线程预分配空间。

void scheduler_killall(void)

58-61    这个函数用于在panic shutdown的时候,将所有runqueue中的thread清除掉。

void scheduler_shutdown()

74       调用scheduler_killall(),杀掉所有的threads
77-78    清除runqueue

struct thread * scheduler(void)

93-95    这个函数是真正的调度器。如果runqueue是空的,那么调用cpu_idle()休息一会儿,过会儿循环回来判断runqueue。
97-102   去掉print_run_queue()前的注释后,可以打印runqueue
104      将runqueue的第一个task取出,并返回。这实际上是roundrobin的轮转调度算法,最简单的一种。

int make_runnable(struct thread *t)

117      通过调用q_addtail(runqueue, t),将thread t添加到runqueue的尾部。

void print_run_queue(void)

127      关中断
129-130  取得runqueue其实位置
132-137  循环到runqueue结束,打印每一个runqueue线程中的名称和地址。
139      开中断