7.4 代码:mycpu和myproc

Xv6通常需要指向当前进程的proc结构体的指针。在单处理器系统上,可以有一个指向当前proc的全局变量。但这不能用于多核系统,因为每个核执行的进程不同。解决这个问题的方法是基于每个核心都有自己的寄存器集,从而使用其中一个寄存器来帮助查找每个核心的信息。

Xv6为每个CPU维护一个struct cpu,它记录当前在该CPU上运行的进程(如果有的话),为CPU的调度线程保存寄存器,以及管理中断禁用所需的嵌套自旋锁的计数。函数mycpu (kernel/proc.c:60)返回一个指向当前CPU的struct cpu的指针。RISC-V给它的CPU编号,给每个CPU一个hartid。Xv6确保每个CPU的hartid在内核中存储在该CPU的tp寄存器中。这允许mycpu使用tp对一个cpu结构体数组(即cpus数组,kernel/proc.c:9)进行索引,以找到正确的那个。

确保CPU的tp始终保存CPU的hartid有点麻烦。mstart在CPU启动次序的早期设置tp寄存器,此时仍处于机器模式(kernel/start.c:46)。因为用户进程可能会修改tpusertrapret在蹦床页面(trampoline page)中保存tp。最后,uservec在从用户空间(kernel/trampoline.S:70)进入内核时恢复保存的tp。编译器保证永远不会使用tp寄存器。如果RISC-V允许xv6直接读取当前hartid会更方便,但这只允许在机器模式下,而不允许在管理模式下。

cpuidmycpu的返回值很脆弱:如果定时器中断并导致线程让步(yield),然后移动到另一个CPU,以前返回的值将不再正确。为了避免这个问题,xv6要求调用者禁用中断,并且只有在使用完返回的struct cpu后才重新启用。

函数myproc (kernel/proc.c:68)返回当前CPU上运行进程struct proc的指针。myproc禁用中断,调用mycpu,从struct cpu中取出当前进程指针(c->proc),然后启用中断。即使启用中断,myproc的返回值也可以安全使用:如果计时器中断将调用进程移动到另一个CPU,其struct proc指针不会改变。

copyright by duguosheng all right reserved,powered by Gitbook该文件修订时间: 2021-08-19 14:02:20

results matching ""

    No results matching ""