Project 4: xv6 Threads
Important Dates
Questions about the project? Send them to 537-help@cs.wisc.edu .
Due: Wednesday, 11/09, by whenever.
Overview
In this project, you'll be adding real kernel threads to xv6. Sound like
fun? Well, it should. Because you know fun is our major goal with these
projects.
Specifically, you'll do three things. First, you'll define a new system
call to create a kernel thread, called clone() . Then, you'll use
clone() to build a little thread library, with a thread_create() call,
a thread_join() call, and lock_acquire() and
lock_release() functions. Finally, you'll show these things work by writing a
test program in which multiple threads are created by the parent, and each
adds values to a shared counter. And now, for some details.
Details
Your new syscall should look like this: int clone(void *stack, int
size) . It does more or less what fork() does, except for one major
difference: instead of making a new address space, it should use the parent's
address space (which is thus shared between parent and child). You might also
notice a single pointer is passed to the call, and size; this is the location
of the child's user stack, which must be allocated before the call to
clone is made. Thus, inside clone() , you should make sure that when you
return, you are running on this stack, instead of the stack of the parent.
As with fork() , the clone() call returns the pid of the child
to the parent, and 0 to the newly-created child thread.
Your thread library will be built on top of this, and just have a simple
thread_create(void *(*start_routine)(void*), void *arg) routine. This
routine should use clone() to create the child, and then call
start_routine() with the argument arg .
Your library will also have a thread_join() routine. This call, made
by the parent of the thread, simply waits for a thread that the parent created
to exit. In this way, it is quite similar to the wait() system call.
Your thread library should also have a simple spin lock. There should be a
type lock_t that one uses to declare a lock, and two routines
lock_acquire(lock_t *) and lock_release(lock_t *) , which acquire and
release the lock. The spin lock should use x86 atomic exchange to built the
spin lock (see the xv6 kernel for an example of something close to what you
need to do). One last routine, lock_init(lock_t *) , is used to
initialize the lock as need be.
To test your code, you should build a simple program that uses
thread_create() to create some number of threads; each thread should, in a
loop for a fixed number of times, add one to a shared counter. The counter
should be made thread safe using locks of course. At the end, the main thread
should call thread_join() (repeatedly, once per child) to wait
for all the children to complete; at this point, the main thread should print
out the value of the counter.
The command line arguments for this program, called threadtest , are
thus:
prompt> threadtest numberOfThreads loopCount
Have fun!
The Code
The code (and associated README) can be found in
~cs537-1/ta/xv6/ . Everything you need to build and run and even debug the
kernel is in there, as before.
Might be good to read the xv6 book a bit:
Here . Particularly useful to read about how fork() works.
You may also find this book useful:
Programming from the Ground Up . Particular attention should be paid to the
first few chapters, including the calling convention (i.e., what's on the
stack when you make a function call, and how it all is manipulated).
Testing
Unlike before, we will be grading this project by examining your code and
reading a write-up describing the changes you made, as well running the counter
test as described above. The write-up should be short (a few pages at most) and
concise. You should also describe how you tested your code, to convince us
(and yourselves) that it works!
Handing It In
Use the p4 directory for your handin. If working as a team of two, please
handin the material in ONE directory, with a README that clearly
indicates the names and CS logins of the team members.
Turn in a writeup, called p4.pdf , which describes the changes and all
the stuff you have done to build and test your kernel.
Turn in all files that you have changed or added (.c and .h files, and
possibly a modified Makefile). Thus, we should be able to take your handed in
files, add the rest of the source code, and build and run your kernel and any
tests you have turned in.
|