

Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Material Type: Assignment; Professor: Son; Class: Operating Systems; Subject: Computer Science; University: University of Virginia; Term: Spring 2008;
Typology: Assignments
1 / 3
This page cannot be seen from the preview
Don't miss anything!


In the first Nachos assignment, we gave you part of a working thread system. Your job now is to complete the thread system and then use it to solve several synchronization problems. The first step is to read and understand the partial thread system; you should know how the thread system implements thread fork, thread completion, and semaphores for synchronization. You can run the program “nachos” and trace the execution path (by hand). You have already done this for Nachos Assignment 1. For this assignment, you have to write properly synchronized code for the given synchronization problems. By properly synchronized code, we mean that your code should work no matter what order the scheduler chooses to run the threads on the ready list. In other words, we should be able to put a call to Thread::Yield (causing the scheduler to choose another thread to run) anywhere in your code where interrupts are enabled without changing the correctness of your code. Writing properly synchronized code is crucial to being able to do this assignment. To aid you in this, code linked in with Nachos will cause Thread::Yield to be called on your behalf in a repeatable but unpredictable way. Nachos code is repeatable in that if you call it repeatedly with the same arguments, it will do exactly the same thing each time. However, if you invoke “nachos -rs #'”, (rs is for random seed) with a different number each time, calls to Thread::Yield will be inserted at different places in the code. Make sure to run various test cases against your solutions to these problems. For instance, in part two, create multiple producers and consumers and demonstrate that the output can vary, within certain boundaries. Warning: In our implementation of threads, each thread is assigned a small, fixed-size execution stack. This may cause bizarre problems (such as segmentation faults at strange lines of code) if you declare large data structures to be automatic variables (e.g., “int buf[1000];'”). You will probably not have this problem, but if you do, you may change the size of the stack by modifying the StackSize defined in switch.h. Although the solutions can be written as normal C routines, you will find organizing your code to be easier if you structure your code as separate classes. It would make your code easier to read and debug.
you may use more primitive thread routines (such as Thread::Sleep). We have provided the public interface to lock and condition variables in synch.h. You need to define the private data and implement the interface. Note that you do not need to do too much of coding to implement either lock or condition variables. When you write the description of your implementation, explain and justify your design.