summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-08-03 07:12:00 -0400
committerRobert Morris <[email protected]>2019-08-03 07:12:00 -0400
commitdeec67f05db8377dc912c33ff910002364f9199a (patch)
tree2e5ab35f75b1ef7ed73393f58b538fc40b7daf98
parentfdea26548977d9a9b188c90ebe6e89c1cc1a8dfa (diff)
downloadxv6-labs-deec67f05db8377dc912c33ff910002364f9199a.tar.gz
xv6-labs-deec67f05db8377dc912c33ff910002364f9199a.tar.bz2
xv6-labs-deec67f05db8377dc912c33ff910002364f9199a.zip
alarm stuff
-rw-r--r--labs/syscall.html126
1 files changed, 57 insertions, 69 deletions
diff --git a/labs/syscall.html b/labs/syscall.html
index 835e510..662641c 100644
--- a/labs/syscall.html
+++ b/labs/syscall.html
@@ -7,10 +7,10 @@
<h1>Lab: Alarm and uthread</h1>
-This lab makes you familiar with the implementation of system calls
+This lab will familiarize you with the implementation of system calls
and switching between threads of execution. In particular, you will
implement new system calls (<tt>sigalarm</tt> and <tt>sigreturn</tt>)
-and switching between threads of a user-level thread package.
+and switching between threads in a user-level thread package.
<h2>Warmup: RISC-V assembly</h2>
@@ -119,7 +119,6 @@ interrupts.
<p>
You should put the following test program in <tt>user/alarmtest.c</tt>:
-<b>XXX Insert the final program here; maybe just give the code in the repo</b>
<pre>
#include "kernel/param.h"
#include "kernel/types.h"
@@ -143,12 +142,12 @@ void test0()
{
int i;
printf(1, "test0 start\n");
- alarm(2, periodic);
+ sigalarm(2, periodic);
for(i = 0; i < 1000*500000; i++){
if((i % 250000) == 0)
write(2, ".", 1);
}
- alarm(0, 0);
+ sigalarm(0, 0);
printf(1, "test0 done\n");
}
@@ -171,7 +170,7 @@ void test1() {
printf(1, "test1 start\n");
j = 0;
- alarm(2, periodic);
+ sigalarm(2, periodic);
for(i = 0; i < 1000*500000; i++){
foo(i, &j);
}
@@ -185,55 +184,53 @@ void test1() {
The program calls <tt>sigalarm(2, periodic1)</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. After you have implemented
-the <tt>sigalarm()</tt> system call in the kernel,
-<tt>alarmtest</tt> should produce output like this for <tt>test0</tt>:
+and then spins for a while.
+You can see the assembly
+code for alarmtest in user/alarmtest.asm, which may be handy
+for debugging.
+When you've finished the lab,
+<tt>alarmtest</tt> should produce output like this:
-<b>Update output for final usertests.c</b>
<pre>
$ alarmtest
-alarmtest starting
-.....alarm!
-....alarm!
-.....alarm!
-......alarm!
-.....alarm!
-....alarm!
-....alarm!
-......alarm!
-.....alarm!
-...alarm!
-...$
+test0 start
+...................................................alarm!
+.............................................................alarm!
+(repeated many times)
+test0 done
+test1 start
+..alarm!
+..alarm!
+..alarm!
+(repeated many times)
+test1 done
+$
</pre>
-<p>
<p>
-(If you only see one "alarm!", try increasing the number of iterations in
-<tt>alarmtest.c</tt> by 10x.)
+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
process's alarm interval expires, the process executes
- the handler. How can you do that? You will need to understand in
- detail how system calls work (i.e., the code in kernel/trampoline.S
- and kernel/trap.c). Which register contains the address where
- system calls return to?
+ the handler. How can you do that? You will need to understand
+ how system calls work (i.e., the code in kernel/trampoline.S
+ and kernel/trap.c). Which register contains the address to which
+ system calls return?
-<p>Your solution will be few lines of code, but it will be tricky to
- write the right lines of code. The most common failure scenario is that the
- user program crashes or doesn't terminate. You can see the assembly
- code for the alarmtest program in alarmtest.asm, which will be handy
- for debugging.
+<p>Your solution will be only a few lines of code, but it may be tricky to
+ get it right.
-<h3>Test0: invoke handler</h3>
+<h3>test0: invoke handler</h3>
-<p>To get started, the best strategy is to first pass test0, which
- will force you to handle the main challenge above. Here are some
- hints how to pass test0:
+<p>Get started by modifying the kernel to jump to the alarm handler in
+user space, which will cause test0 to print "alarm!". Don't worry yet
+what happens after the "alarm!" output; it's OK for now if your
+program crashes after printing "alarm!". Here are some hints:
-<p><b>XXX alarm() needs to be defined somewhere.</b><br>
-
<ul>
<li>You'll need to modify the Makefile to cause <tt>alarmtest.c</tt>
@@ -268,7 +265,7 @@ in <tt>usertrap()</tt>; you should add some code here.
if(which_dev == 2) ...
</pre>
-<li>Only invoke the process's alarm function, if the process has a
+<li>Only invoke the alarm function if the process has a
timer outstanding. Note that the address of the user's alarm
function might be 0 (e.g., in alarmtest.asm, <tt>periodic</tt> is at
address 0).
@@ -279,41 +276,32 @@ use only one CPU, which you can do by running
make CPUS=1 qemu
</pre>
-<li><b>XXX we need to somehow convey what it is they don't
- need to do here, i.e. what part is to be left to
- the next section.</b>
-
-<li><b>XXX it's not clear how they can tell whether they
-are passing test0(), and should proceed to the next section.
-do they need to make sure at this point that they see multiple
-alarm! printouts? or is it OK if they see one alarm! and
-then a crash? may need to fix the sample ...alarm! output shown above</b>
+<li>You've succeeded if alarmtest prints "alarm!".
</ul>
<h3>test1(): resume interrupted code</h3>
-<p><b>XXX it is surprising that test0() appears to work
-perfectly, even though something is seriously wrong
-with the way periodic() returns. we should recognize
-that something odd is happening, maybe ask them to think
-about it, and hint or say why they are not done even though
-test0() works.</b>
-
-<p>Test0 doesn't test whether the handler returns correctly to
- the user instruction that was interrupted by the timer.
- The previous section didn't require you to get this right.
- If you didn't, test0 will probably succeed anyway, but
- test1 will likely fail (the program crashes or the program
- goes into an infinite loop).
- Another challenge is that the register contents need to be
- correct when control returns to the interrupted user instruction.
+Chances are that alarmtest crashes at some point after it prints
+"alarm!". Depending on how your solution works, that point may be in
+test0, or it may be in test1. Crashes are likely caused
+by the alarm handler (<tt>periodic</tt> in alarmtest.c) returning
+to the wrong point in the user program.
+
+<p>
+Your job now is to ensure that, when the alarm handler is done,
+control returns to
+the instruction at which the user program was originally
+interrupted by the timer interrupt. You must also ensure that
+the register contents are restored to values they held
+at the time of the interrupt, so that the user program
+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). There are
- several ways to restore the registers; one convenient plan is to add another
- system call <tt>sigreturn</tt> that the handler calls when it is
+ 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
interrupted user instruction.
@@ -324,7 +312,7 @@ test0() works.</b>
<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
- interrupted code.
+ interrupted user code.
<li>Prevent re-entrant calls to the handler----if a handler hasn't
returned yet, the kernel shouldn't call it again.