这回由启动时初始化的顺序分析涉及几个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)中:
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 开中断