diff --git a/labs/syscall.html b/labs/syscall.html index dad86fe..1e6e504 100644 --- a/labs/syscall.html +++ b/labs/syscall.html @@ -8,10 +8,10 @@
Since you will be reading and writing RISC-V assembly code for xv6, - you should read through call.asm and understand it. The instruction - manual for RISC-V is in the doc directory (doc/riscv-spec-v2.2.pdf). - Here are some questions that you should answer for yourself: +
Read through call.asm and understand it. The instruction manual + for RISC-V is in the doc directory (doc/riscv-spec-v2.2.pdf). Here + are some questions that you should answer for yourself:
-You should add a new alarm(interval, handler) system call. -If an application calls alarm(n, fn), then after every +You should add a new sigalarm(interval, handler) system call. +If an application calls sigalarm(n, fn), then after every n "ticks" of CPU time that the program consumes, the kernel will cause application function fn to be called. When fn returns, the application @@ -186,12 +185,13 @@ void test1() { } -The program calls alarm(2, periodic1) in test0 to ask the kernel to -force a call to periodic() every 10 ticks, and then spins for -a while. -After you have implemented the alarm() system call in the kernel, -alarmtest should produce output like this for test0: +The program calls sigalarm(2, periodic1) in test0 to +ask the kernel to force a call to periodic() every 2 ticks, +and then spins for a while. After you have implemented +the sigalarm() system call in the kernel, +alarmtest should produce output like this for test0: +Update output for final usertests.c
$ alarmtest alarmtest starting @@ -227,7 +227,7 @@ alarmtest starting code for the alarmtest program in alarmtest.asm, which will be handy for debugging. -Test0
+Test0: invoke handler
To get started, the best strategy is to first pass test0, which will force you to handle the main challenge above. Here are some @@ -240,52 +240,48 @@ to be compiled as an xv6 user program.
- int alarm(int ticks, void (*handler)()); + int sigalarm(int ticks, void (*handler)());-
if(which_dev == 2) ...-
make CPUS=1 qemu
Test0 doesn't stress whether the handler returns correctly to +
Test0 doesn't tests whether the handler returns correctly to interrupted instruction in test0. If you didn't get this right, it is likely that test1 will fail (the program crashes or the program goes into an infinite loop). @@ -296,16 +292,30 @@ only one CPU, which you can do by running receives an interrupt, which register contains the address of the interrupted instruction? -
Your solution is likely to require you to save and restore a - register. There are several ways to do this. It is ok to change the - API of alarm() and have an alarm stub in user space that cooperates - with the kernel. +
Your solution is likely to require you to save and restore + registers---what registers do you need to save and restore to resume + the interrupted code correctly? (Hint: it will be many). There are + several ways to do this, but one convenient way is to add another + system call sigreturn that the handler calls when it is + done. Your job is to arrange that sigreturn returns to the + interrupted code. + + Some hints: +
Once you pass test0 and test1, run usertests to + make sure you didn't break any other parts of the kernel. -
-Optional challenges: Prevent re-entrant calls to the handler----if a - handler hasn't returned yet, don't call it again. - -