Project 4: xv6 Threads
Questions about the project? Send them to
Due: Wednesday, 11/09, by whenever.
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
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_join() call, 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.
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.
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
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
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
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
prompt> threadtest numberOfThreads loopCount
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
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).
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.