diff --git a/labs/syscall.html b/labs/syscall.html index 662641c..2281f2e 100644 --- a/labs/syscall.html +++ b/labs/syscall.html @@ -117,72 +117,13 @@ time in xv6, determined by how often a hardware timer generates interrupts.

-You should put the following test program in user/alarmtest.c: +You'll find a file user/alarmtest.c in your xv6 +repository. Add it to the Makefile. It won't compile correctly +until you've added sigalarm and sigreturn +system calls (see below). -

-#include "kernel/param.h"
-#include "kernel/types.h"
-#include "kernel/stat.h"
-#include "kernel/riscv.h"
-#include "user/user.h"
-
-void test0();
-void test1();
-void periodic();
-
-int
-main(int argc, char *argv[])
-{
-  test0();
-  test1();
-  exit();
-}
-
-void test0()
-{
-  int i;
-  printf(1, "test0 start\n");
-  sigalarm(2, periodic);
-  for(i = 0; i < 1000*500000; i++){
-    if((i % 250000) == 0)
-      write(2, ".", 1);
-  }
-  sigalarm(0, 0);
-  printf(1, "test0 done\n");
-}
-
-void
-periodic()
-{
-  printf(1, "alarm!\n");
-}
-
-void __attribute__ ((noinline)) foo(int i, int *j) {
-  if((i % 2500000) == 0) {
-    write(2, ".", 1);
-  }
-  *j += 1;
-}
-
-void test1() {
-  int i;
-  int j;
-
-  printf(1, "test1 start\n");
-  j = 0;
-  sigalarm(2, periodic);
-  for(i = 0; i < 1000*500000; i++){
-    foo(i, &j);
-  }
-  if(i != j) {
-    printf(2, "i %d should = j %d\n", i, j);
-    exit();
-  }
-  printf(1, "test1 done\n");
-}
-
- -The program calls sigalarm(2, periodic1) in test0 to +

+alarmtest calls sigalarm(2, periodic) in test0 to ask the kernel to force a call to periodic() every 2 ticks, and then spins for a while. You can see the assembly @@ -194,24 +135,23 @@ When you've finished the lab,

 $ alarmtest
 test0 start
-...................................................alarm!
-.............................................................alarm!
-(repeated many times)
-test0 done
+......................................alarm!
+test0 passed
 test1 start
 ..alarm!
 ..alarm!
 ..alarm!
-(repeated many times)
-test1 done
+.alarm!
+..alarm!
+..alarm!
+..alarm!
+..alarm!
+..alarm!
+..alarm!
+test1 passed
 $
 
-

-At first, however, you'll see that alarmtest only prints periods, -and doesn't print "alarm!". - -

The main challenge will be to arrange that the handler is invoked when the process's alarm interval expires. You'll need to modify usertrap() in kernel/trap.c so that when a @@ -223,6 +163,9 @@ and doesn't print "alarm!".

Your solution will be only a few lines of code, but it may be tricky to get it right. +We'll test your code with the version of alarmtest.c in the original +repository; if you modify alarmtest.c, make sure your kernel changes +cause the original alarmtest to pass the tests.

test0: invoke handler

@@ -236,15 +179,18 @@ program crashes after printing "alarm!". Here are some hints:
  • You'll need to modify the Makefile to cause alarmtest.c to be compiled as an xv6 user program. -
  • The right declaration to put in user/user.h is: +
  • The right declarations to put in user/user.h are:
         int sigalarm(int ticks, void (*handler)());
    +    int sigreturn(void);
     
  • Update user/sys.pl (which generates user/usys.S), kernel/syscall.h, and kernel/syscall.c - to allow alarmtest to invoke the sigalarm system - call. + to allow alarmtest to invoke the sigalarm and + sigreturn system calls. + +
  • For now, your sys_sigreturn should just return zero.
  • Your sys_sigalarm() should store the alarm interval and the pointer to the handler function in new fields in the proc @@ -300,15 +246,15 @@ can continue undisturbed after the alarm.

    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). - Several approaches are possible; one convenient plan is to add another - system call sigreturn that the user-space alarm handler calls when it is - done, and which restores registers and returns to the original + Several approaches are possible; for this lab you should make + the sigreturn system call + restore registers and return to the original interrupted user instruction. + The user-space alarm handler + calls sigreturn when it is done. Some hints: