Merge branch 'riscv' of g.csail.mit.edu:xv6-dev into riscv

This commit is contained in:
Robert Morris 2019-07-28 07:10:23 -04:00
commit 2d89a101c4
2 changed files with 91 additions and 1 deletions

86
labs/lock.html Normal file
View file

@ -0,0 +1,86 @@
<html>
<head>
<title>Lab: locks</title>
<link rel="stylesheet" href="homework.css" type="text/css" />
</head>
<body>
<h1>Lab: locks</h1>
<p>In this lab you will try to avoid lock contention for certain
workloads.
<h2>lock contention</h2>
<p>The program user/kalloctest stresses xv6's memory allocator: three
processes grow and shrink there address space, which will results in
many calls to <tt>kalloc</tt> and <tt>kfree</tt>,
respectively. <tt>kalloc</tt> and <tt>kfree</tt>
obtain <tt>kmem.lock</tt>. To see if there is lock contention for
<tt>kmem.lock</tt> replace the call to <tt>acquire</tt>
in <tt>kalloc</tt> with the following code:
<pre>
while(!tryacquire(&kmem.lock)) {
printf("!");
}
</pre>
<p><tt>tryacquire</tt> tries to acquire <tt>kmem.lock</tt>: if the
lock is taking it returns false (0); otherwise, it returns true (1)
and with the lock acquired. Your first job is to
implement <tt>tryacquire</tt> in kernel/spinlock.c.
<p>A few hints:
<ul>
<li>look at <tt>acquire</tt>.
<li>don't forget to restore interrupts when acquision fails
<li>Add tryacquire's signature to defs.h.
</ul>
<p>Run usertests to see if you didn't break anything. Note that
usertests never prints "!"; there is never contention
for <tt>kmem.lock</tt>. The caller is always able to immediately
acquire the lock and never has to wait because some other process
has the lock.
<p>Now run kalloctest. You should see quite a number of "!" on the
console. kalloctest causes many processes to contend on
the <tt>kmem.lock</tt>. This lock contention is a bit artificial,
because qemu is simulating 3 processors, but it is likely on real
hardware, there would be contention too.
<h2>Removing lock contention</h2>
<p>The root cause of lock contention in kalloctest is that there is a
single free list, protected by a single lock. To remove lock
contention, you will have to redesign the memory allocator to avoid
a single lock and list. The basic idea is to maintain a free list
per CPU, each list with its own lock. Allocations and frees on each
CPU can run in parallel, because each CPU will operate on a
different list.
<p> The main challenge will be to deal with the case that one CPU runs
out of memory, but another CPU has still free memory; in that case,
the one CPU must "steal" part of the other CPU's free list.
Stealing may introduce lock contention, but that may be acceptable
because it may happen infrequently.
<p>Your job is to implement per-CPU freelists and stealing when one
CPU is out of memory. Run kalloctest() to see if your
implementation has removed lock contention.
<p>Some hints:
<ul>
<li>You can use the constant <tt>NCPU</tt> in kernel/param.h
<li>Let <tt>freerange</tt> give all free memory to the CPU
running <tt>freerange</tt>.
<li>The function <tt>cpuid</tt> returns the current core, but note
that you can use it when interrupts are turned off and so you will
need to turn on/off interrupts in your solution.
</ul>
<p>Run usertests to see if you don't break anything.
</body>
</html>

View file

@ -121,7 +121,7 @@ interrupts.
<p> <p>
You should put the following example program in <tt>user/alarmtest.c</tt>: You should put the following example program in <tt>user/alarmtest.c</tt>:
<b>XXX Insert the final program here</b> <b>XXX Insert the final program here; maybe just give the code in the repo</b>
<pre> <pre>
#include "kernel/param.h" #include "kernel/param.h"
#include "kernel/types.h" #include "kernel/types.h"
@ -317,6 +317,10 @@ use only one CPU, which you can do by running
make sure you didn't break any other parts of the kernel. make sure you didn't break any other parts of the kernel.
</body>
</html>