thread_init()
进入 C语言 之后,进程的每一个进程的上下文就是它的调用堆栈,此时 main 函数应该就是 main thread 的上下文,并且已经在上下文之中了,此时需要做的就是将 main 函数封装在 thread 之中,thread_init() 就是用来完成以上任务
function: thread_init()
1 | void thread_init(void) |
thread_init() 初始化了两个队列,一个是全部线程队列 all_list 和另一个就绪队列 ready_list ,然后调用了另一个 pintOS 的重要函数 init_thread() ,之后每一个进程初始化都会调用 init_thread() 在看 init_thread() 之前,不妨先看看 pintOS thread 的结构
struct: thread
1 | struct thread |
在 thread 结构体中,存放的是 thread 的属性,其中最重要的是 tid , stack 和 priority 分别是 thread ID , 堆栈指针和优先级,剩下的 allelem 和 elem 分别为 thead 的迭代器,为队列所使用。
在 thread init 中,initial_thread 是一个 thread 的结构体指针initial_thread = running_thread() 语句初始化了 initial_thread 指针的位置,在running_thread()中会先获取我们当前的堆栈指针,由于页面都是 4KB 大小,将堆栈指针除以 4KB 即可拿到页面首地址,running_thread() 使用 bit mask 将堆栈指针的后12位页偏移置0(使用bit mask),得到的就是页首地址,也就是说 initial thread 指向了当前页面的首地址,main thread 的其他属性在 init_thread() 中初始化
function: init_thread()
1 | static void |
语句t->stack = t + PGSIZE 将 stack 指向了 页首地址 + 页长 也就是页底,和 pintOS 源码中给出的图一致(如下)
页首的位置为 main thread 结构体,main thread 堆栈从页底向上扩展,magic number 用于检测堆栈移除,同时也可以检测当前线程指针的正确性
4 kB +---------------------------------+
| kernel stack | -------> thread 堆栈
| | |
| | |
| V |
| grows downward |
| |
| |
| |
| |
| |
| |
| |
| |
+---------------------------------+
| magic |
| : |
| : |
| name |
| status | ------> thread 结构体
0 kB +---------------------------------+
实际上,pintOS 的每一个 thread 都占用一个 4KB 的页面,而页首永远是当前 thread 的结构体指针,而 running_thread() 永远指向了页首,也就是当前 thread 结构体,给确定上下文创造了方便