answers-syscall.txt: OK uthread: $ make qemu-gdb OK (2.3s) running alarmtest: $ make qemu-gdb (3.7s) alarmtest: test0: OK alarmtest: test1: OK usertests: $ make qemu-gdb OK (91.4s) time: OK Score: 100/100
Where is the function call to f from main? Where is the call to g? (Hint: the compiler may inline functions.)
注意括号里的话。根据笔算我们知道 f(8)+1 = 12,又发现 main 中并为调用 f 函数,说明 f 在编译期被直接优化成一个常量 12 塞到 a1 寄存器里了。
At what address is the function printf located?
观察 main 函数,在调用时使用了代码 auipc ra,0x0 和 jalr 1440(ra),前者取当前指令的 pc 加上 0x0 存入 ra,后者跳转到 ra + 1440。计算知 0x0000000000000030 + 1440 = 0x00000000000005d0。经验证是 printf 的入口地址。
What value is in the register ra just after the jalr to printf in main?
此题需要看 rv spec 。jalr 指令完成后,ra 寄存器会存储返回点位置(也即 pc + 4 )
2. Uthread: switching between threads
这题并不难,我给想复杂了。
首先我们把 Hint 里面的问题解决:thread_switch needs to save/restore only the callee-save registers. Why? 这个是因为协程切换的过程本质是一个函数调用,因此 caller-save registers 是被调用者(如 thread_a() )保存好的。
// Per-process state struct proc { //... omitted int alarm_interval; // Alarm's interval (0 for disabled) uint64 alarm_handler; // Virtual address of the alarm handler (can be 0 due to xv6-rv's userspace memory layout) uint64 alarm_last_tick; // Ticks of the last call struct trapframe alarm_tf; // trapframe for storing original tf uint alarm_state; // 1 if the handler hasn't return };