diff --git a/labs/syscall.html b/labs/syscall.html new file mode 100644 index 0000000..a167885 --- /dev/null +++ b/labs/syscall.html @@ -0,0 +1,196 @@ + +
+In this exercise you will modify the xv6 kernel to print out a line +for each system call invocation. It is enough to print the name of the +system call and the return value; you don't need to print the system +call arguments. + +
+When you're done, you should see output like this when booting +xv6: + +
+... +fork -> 2 +exec -> 0 +open -> 3 +close -> 0 +$write -> 1 + write -> 1 ++ +
+That's init forking and execing sh, sh making sure only two file descriptors are +open, and sh writing the $ prompt. (Note: the output of the shell and the +system call trace are intermixed, because the shell uses the write syscall to +print its output.) + +
Hint: modify the syscall() function in kernel/syscall.c. + +
Run the programs you wrote in the lab and inspect the system call + trace. Are there many system calls? Which systems calls correspond + to code in the applications you wrote above? + +
Optional: print the system call arguments. + +
+In this exercise you'll add a feature to xv6 that periodically alerts +a process as it uses CPU time. This might be useful for compute-bound +processes that want to limit how much CPU time they chew up, or for +processes that want to compute but also want to take some periodic +action. More generally, you'll be implementing a primitive form of +user-level interrupt/fault handlers; you could use something similar +to handle page faults in the application, for example. + +
+You should add a new alarm(interval, handler) system call. +If an application calls alarm(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 +will resume where it left off. A tick is a fairly arbitrary unit of +time in xv6, determined by how often a hardware timer generates +interrupts. + +
+You should put the following example program in user/alarmtest.c: + +
+#include "kernel/param.h" +#include "kernel/types.h" +#include "kernel/stat.h" +#include "user/user.h" + +void periodic(); + +int +main(int argc, char *argv[]) +{ + int i; + printf(1, "alarmtest starting\n"); + alarm(10, periodic); + for(i = 0; i < 25*500000; i++){ + if((i % 250000) == 0) + write(2, ".", 1); + } + exit(); +} + +void +periodic() +{ + printf(1, "alarm!\n"); +} ++ +The program calls alarm(10, periodic) 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: + +
+$ alarmtest +alarmtest starting +.....alarm! +....alarm! +.....alarm! +......alarm! +.....alarm! +....alarm! +....alarm! +......alarm! +.....alarm! +...alarm! +...$ ++
+ +
+(If you only see one "alarm!", try increasing the number of iterations in +alarmtest.c by 10x.) + +Here are some hints: +
+ int alarm(int ticks, void (*handler)()); ++ +
+ if(which_dev == 2) .. ++ +
+In your usertrap, when a process's alarm interval expires, +you'll want to cause it to execute its handler. How can you do that? + +
+ make CPUS=1 qemu ++ +
+Optional challenges: 1) Save and restore the caller-saved user registers around the +call to handler. 2) Prevent re-entrant calls to the handler -- if a handler +hasn't returned yet, don't call it again. 3) Assuming your code doesn't +check that tf->esp is valid, implement a security attack on the +kernel that exploits your alarm handler calling code. + +