這回由啟動時初始化的順序分析涉及幾個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 開中斷