diff options
| author | Robert Morris <rtm@csail.mit.edu> | 2019-08-05 02:04:44 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@csail.mit.edu> | 2019-08-05 02:04:44 -0400 | 
| commit | d96a8c5661ac27c82e577edc6714832b970586dc (patch) | |
| tree | a78e0d1bb187e5f40816d89509ee1380170e71d8 | |
| parent | deec67f05db8377dc912c33ff910002364f9199a (diff) | |
| download | xv6-labs-d96a8c5661ac27c82e577edc6714832b970586dc.tar.gz xv6-labs-d96a8c5661ac27c82e577edc6714832b970586dc.tar.bz2 xv6-labs-d96a8c5661ac27c82e577edc6714832b970586dc.zip | |
add alarmtest.c to the repository
they don't have to modify alarmtest.c, so we can use the
original version to test, to make it harder to cheat.
| -rw-r--r-- | labs/syscall.html | 114 | ||||
| -rw-r--r-- | user/alarmtest.c | 88 | 
2 files changed, 118 insertions, 84 deletions
| 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.  <p> -You should put the following test program in <tt>user/alarmtest.c</tt>: +You'll find a file <tt>user/alarmtest.c</tt> in your xv6 +repository. Add it to the Makefile. It won't compile correctly +until you've added <tt>sigalarm</tt> and <tt>sigreturn</tt> +system calls (see below). -<pre> -#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"); -} -</pre> - -The program calls <tt>sigalarm(2, periodic1)</tt> in <tt>test0</tt> to +<p> +<tt>alarmtest</tt> calls <tt>sigalarm(2, periodic)</tt> in <tt>test0</tt> to  ask the kernel to force a call to <tt>periodic()</tt> every 2 ticks,  and then spins for a while.  You can see the assembly @@ -194,24 +135,23 @@ When you've finished the lab,  <pre>  $ 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  $  </pre> -<p> -At first, however, you'll see that alarmtest only prints periods, -and doesn't print "alarm!". - -  <p>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!".  <p>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.  <h3>test0: invoke handler</h3> @@ -236,15 +179,18 @@ program crashes after printing "alarm!". Here are some hints:  <li>You'll need to modify the Makefile to cause <tt>alarmtest.c</tt>  to be compiled as an xv6 user program. -<li>The right declaration to put in <tt>user/user.h</tt> is: +<li>The right declarations to put in <tt>user/user.h</tt> are:  <pre>      int sigalarm(int ticks, void (*handler)()); +    int sigreturn(void);  </pre>  <li>Update user/sys.pl (which generates user/usys.S),      kernel/syscall.h, and kernel/syscall.c  -   to allow <tt>alarmtest</tt> to invoke the sigalarm system -  call. +   to allow <tt>alarmtest</tt> to invoke the sigalarm and +   sigreturn system calls. + +<li>For now, your <tt>sys_sigreturn</tt> should just return zero.  <li>Your <tt>sys_sigalarm()</tt> should store the alarm interval and  the pointer to the handler function in new fields in the <tt>proc</tt> @@ -300,15 +246,15 @@ can continue undisturbed after the alarm.  <p>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 <tt>sigreturn</tt> 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 <tt>sigreturn</tt> 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:    <ul> -    <li>Add a new <tt>sigreturn</tt> system call. -            <li>Have <tt>usertrap</tt> save enough state in        <tt>struct proc</tt> when the timer goes off        that <tt>sigreturn</tt> can correctly return to the diff --git a/user/alarmtest.c b/user/alarmtest.c new file mode 100644 index 0000000..c6da547 --- /dev/null +++ b/user/alarmtest.c @@ -0,0 +1,88 @@ +// +// test program for the alarm lab. +// you can modify this file for testing, +// but please make sure your kernel +// modifications pass the original +// versions of these tests. +// + +#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(); +} + +volatile static int count; + +void +periodic() +{ +  count = count + 1; +  printf(1, "alarm!\n"); +  sigreturn(); +} + +// tests whether the kernel calls +// the alarm handler even a single time. +void +test0() +{ +  int i; +  printf(1, "test0 start\n"); +  count = 0; +  sigalarm(2, periodic); +  for(i = 0; i < 1000*500000; i++){ +    if((i % 250000) == 0) +      write(2, ".", 1); +    if(count > 0) +      break; +  } +  sigalarm(0, 0); +  if(count > 0){ +    printf(1, "test0 passed\n"); +  } else { +    printf(1, "test0 failed\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"); +  count = 0; +  j = 0; +  sigalarm(2, periodic); +  for(i = 0; i < 500000000; i++){ +    if(count >= 10) +      break; +    foo(i, &j); +  } +  if(i != j || count < 10){ +    // i should equal j +    printf(1, "test1 failed\n"); +  } else { +    printf(1, "test1 passed\n"); +  } +} | 
