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. + +