ICS412 - Fall 2009 - Nachos Project #1 -

Team Project
This is a project to do in a team of three students. The motivation is that working with somebody is always a good experience, and that the project is sufficiently complicated to justify a 3-student team. You can divide the work among team members as you wish. A team can (and is encouraged to) engage in general discussions with other teams regarding the project, but specific details of a solution, including the solution itself, must always be the team's own work. (See the statement of Academic Dishonesty on the course's syllabus.)

What to turn in?
Turn in an archive (.zip, .tar, .tar.gz, .tgz, etc.) that contains: The archive must be turned in via e-mail to henric@hawaii.edu and to altunkay@hawaii.edu with a subject line like "ICS412: PROJ#1" before 11:59PM on the day the project is due.


Getting Started with the Nachos Project #1
The slides presented and discussed in class are available: [PPT], [PDF].


Downloading and Installing Nachos

In this project you're only adding/modifying source code in the thread directory. If you add a new source file in that directory, then you must (trivially) modify the top-level Makefile and turn it in as well. Do not modify code anywhere else (since you don't turn it in).

Reading the Nachos for Java Walkthrough, and in particular its Threads and Scheduling Section is probably a very good idea.


Question #1: Adding Simple Testing [10pts]
Implement the KThreadSimpleTest.java class (right now it's an empty placeholder). That class should create 2 KThread objects and start them. Threads should be named HelloWorldThread-1 and HelloWorkdThread-2, and should each print "Hello World!" to the screen. Do not remove the KThread.yield() call in KThreadSimpleTest.java. It is there so that the machine does not halt before the two test threads have a chance to print out their message to the console. You can look at other Test classes for inspiration.

(My solution takes ~45 lines of code, including comments and debug messages, not counting testing)


Question #2: Reading the Code [8pts]
Answer the following questions and the code in KThread.java. The goals here is for you to read the code and the comments therein.


Question #3: Implementing join() [20pts]
Implement the KThread.join() method. Calling this method allows for a thread to block until another thread is done (just like pthread_join()). Multiple threads can call join() on the same thread, and they are all unblocked when that thread terminates. Of course, a thread must finish executing normally whether or not it is joined.

Hint: To implement join() you need to write code elsewhere in the code. When a thread calls join(), it may block. The code to unblock it obviously is not in join() but elsewhere in the Kernel. Shouldn't be too hard to figure out.

For this question you're given a tester in KThreadTest.java. You can run it by uncommenting the call to KThread.selfTest() in ThreadedKernel.java.

(My solution takes ~25 lines of code, including comments and debug messages, not counting testing)


Question #4: Implementing Condition Variables [40pts]
Implement condition variables directly, by using interrupt enable and disable to provide atomicity. We have provided a sample implementation that uses semaphores; your job is to provide an equivalent implementation without directly using semaphores (you may of course still use locks, even though they indirectly use semaphores). Once you are done, you will have two alternative implementations that provide the exact same functionality. Your second implementation of condition variables must reside in class nachos.threads.Condition2.

For this question you're given a tester in Condition2Test.java. You can run it by uncommenting the call to Condition2.selfTest() in ThreadedKernel.java.

(My solution takes ~130 lines of code, including comments and debug messages, not counting testing)


Question #5: Implementing waitUntil() [30pts]
Complete the implementation of the Alarm class, by implementing the waitUntil(long x) method. A thread calls waitUntil() to suspend its own execution until time has advanced to at least now + x. This is useful for threads that operate in real-time, for example, for blinking the cursor once per second. There is no requirement that threads start running immediately after waking up; just put them on the ready queue in the timer interrupt handler after they have waited for at least the right amount of time. Do not fork any additional threads to implement waitUntil(); you need only modify waitUntil() and the timer interrupt handler. waitUntil() is not limited to one thread; any number of threads may call it and be suspended at any one time.

For this question you're have to develop a tester, following the model of the other testers, and explain how your tester does indeed provide confidence that implementation of waitUntil() works. (Worth 10pts).

(My solution, not counting the tester, takes ~50 lines of code, including comments and debug messages, not counting testing)


Question #6: Implementing Rendez-Vous [40pts]
Implement synchronous send and receive of one word messages (also known as rendez-vous), using condition variables (do NOT use semaphores!). Implement the Communicator class with the following two operations:

speak() atomically waits until listen() is called on the same Communicator object, and then transfers the word over to listen(). Once the transfer is made, both can return. Similarly, listen() waits until speak() is called, at which point the transfer is made, and both can return (listen() returns the word). Your solution should work even if there are multiple speakers and listeners for the same Communicator (note: this is equivalent to a zero-length bounded buffer; since the buffer has no room, the producer and consumer must interact directly, requiring that they wait for one another). Each communicator should only use exactly one lock. If you're using more than one lock, you're making things too complicated.

For this question you're given a tester in CommunicatorTest.java. You can run it by uncommenting the call to Communicator.selfTest() in ThreadedKernel.java.

(My solution takes ~125 lines of code, including comments and debug messages, not counting testing)


henric@hawaii.edu