comp 300e operating systems fall semester 2011 midterm ...€¦ · fall semester 2011 midterm...
TRANSCRIPT
COMP 300E Operating Systems
Fall Semester 2011
Midterm Examination Solution
Time/Date: 5:30 – 6:30 pm Oct 19, 2011 (Wed)
Name: ____________________ Student ID: __________________
Instructions:
1. Please write your name, student ID, and section number on this page.
2. This is a CLOSED book exam!
3. This examination paper consists of 5 questions and 10 pages (including this page).
4. You have 60 minutes to complete this exam.
5. Please answer all questions within the space provided on the paper. Be concise!
6. Please read each question very carefully and answer the question clearly to the point. Make
sure that your answers are neatly written, legible, and readable.
Question Points Score
1 20
2 20
3 20
4 20
5 20
Total 100
1. (20 pts) Short Q&A
1.1 (3 pts) What are the optimal scheduling algorithms for minimizing average response
time, for the case of non-preemptive scheduling and the case of preemptive
scheduling, respectively?
Shortest Job First (SJF) among non-preemptive algorithms, Shortest Remaining
Time First (SRTF) among preemptive algorithms
1.2 (3 pts) If the time quantum for Round-Robin scheduling is set to be very large
(approaching infinity), then it becomes equivalent to what scheduling algorithm?
FCFS or FIFO
1.3 (3 pts) Name one common hardware instruction that is useful for implementing critical
sections.
TestAndSet,or CompareAndSwap
1.4 (3 pts) The signal() operation is used with both semaphores (also called V() operation)
and monitors. Explain the key difference in its runtime behavior in the two cases. (Hint:
consider what happens when a thread signals, but no other thread is waiting.)
When the signal() operation is used in monitors, if a signal is performed and if there are
no waiting processes, the signal is simply ignored and the system does not remember the
fact that the signal took place. If a subsequent wait operation is performed, then the
corresponding thread simply blocks.
In semaphores, on the other hand, every signal results in a corresponding increment of
the semaphore value even if there are no process waiting. A future wait() operation would
immediately succeed because of the earlier increment.
1.5 (3 pts) Explain the key drawback of spinlocks with busy-waiting compared to binary
semaphores with sleeping.
Spin locks waste CPU time.
1.6 (2 pts) List the four necessary conditions for deadlocks.
Mutual exclusion, Hold and wait, No preemption, Circular wait
1.7 (3 pts) What is the main limitation of Resource Allocation Graph used for deadlock
detection, as compared to Banker’s algorithm?
It can only detect deadlocks for the case of single-instance resources.
2. (20 pts) Processor Scheduling.
Here is a table of processes and their associated arrival and running times.
Process ID Arrival Time Running Time
1 0 2
2 1 6
3 4 1
4 7 4
5 8 3
a. (12 points)
Show the scheduling order for these processes under 3 policies: First Come First
Serve (FCFS), Shortest-Remaining-Time-First (SRTF), Round-Robin (RR) with
timeslice quantum = 1, by filling in the Gantt chart with ID of the process currently
running in each time quantum. Assume that context switch overhead is 0 and that new
RR processes are added to the head of the queue and new FCFS processes are added
to the tail of the queue.
Answer:
b. (8 points) Compute the response time for each process in each schedule above.
Scheduler Process 1 Process 2 Process 3 Process 4 Process 5
FIFO 2 7 5 6 8
SRTF 2 8 1 9 4
RR 3 12 1 9 7
3. (20 pts) Synchronization
Consider the following semaphore-based solution to the readers-writers problem:
Common initialization section for both writer and reader:
semaphore wrt=1, mutex=1;
int readcount=0;
The code bodies for writer and reader::
Writer Reader
Writer() {
wrt.P() ;
//writing is performed
wrt.V() ;
}
Reader(){
mutex.P() ;
readcount ++ ;
if (readcount == 1)
wrt.P() ;
mutex.V();
// reading is performed
mutex.P() ;
readcount - - ;
if (readcount == 0)
wrt.V() ;
mutex.V() ;
}
1) (10 pts) Fill in the underlined areas in Reader() to make it a complete solution to
the readers-writers problem. Your solution should allow multiple concurrent
readers, but only one writer, to access the shared database simultaneously.
First if statement: if (readcount == 1) wrt.P() ;
Second if statement: if (readcount == 0) wrt.V() ;
(“wrt” guarantees mutual exclusion to the critical section in the presence of writers.
“mutex” guarantees mutual exclusion when updating the shared variable readcount.)
2) (4 pts) Suppose a writer thread is inside its critical section performing writing,
while another writer and n>1 readers are waiting outside their critical sections.
Which semaphores are they waiting on, respectively?
writer is waiting on wrt; the 1st reader is waiting on wrt and the other n-1 readers are
waiting on mutex.
3) (4 pts) Does this solution give preference to waiting readers or waiting writers?
Why?
This solution gives readers preference over writers; once one reader is accessing the
database, all readers are allowed to read the database without performing the P operations
on wrt.
Note that we are not explicitly checking the number of waiting readers or waiting
writers like the solution in class. For example, if there are both waiting readers and waiting
writers when a writer calls wrt.V(), then either reader(s) or one writer can get ahead of each
other nondeterministic ally. However, once one reader has already started reading, then
other waiting and newly arrived readers have preference over any waiting writers.
Discussions (not part of the problem): Work out a monitor-based solution to this
problem.
MonitorVar wrt=1;
Lock lock=FREE;
int readcount=0;
bool writing=FALSE;
The code bodies for writer and reader:
Writer Reader
Writer() {
lock.aquire();
wrt.wait(&lock) ;
writing=TRUE;
lock.release();
//writing is performed
lock.aquire();
writing=FALSE;
wrt.signalAll();
lock.release();
}
Reader(){
lock.aquire();
readcount ++ ;
while (writing)
wrt.wait(&lock);
lock.release();
// reading is performed
lock.aquire();;
readcount - - ;
if (readcount==0)
wrt.signalAll() ;
lock.release();
}
Note: Compared to the solution in the class notes, this is a simplified solution that removes
several checks to give writers preference, and uses a single condition variable instead of 2.
Suppose a writer thread is inside its critical section performing writing, while another writer
and n>1 readers are waiting outside their critical sections. Then both the one writer and all n
readers are waiting on wrt. Recall that condition.wait(&lock) implicitly releases the lock upon
going to sleep. Assuming Mesa style monitors, “while” needs to be used instead of “if” to check the
boolean “writing”.
We should use signalAll() in both reader and writer code to wake up potentially multiple
readers. If multiple writers are woken up, all but one will go to sleep again, so the program is still
correct. Since only the last reader invokes wrt.signalAll(), using wrt.signal() here would not be
correct, since multiple readers may be waiting on condition wrt, and they all need to be woken up.
4. (20 points total) Synchronization
In parallel programs (one multi-threaded process), a common design
methodology is to perform processing in sequential stages. All of the threads work
independently during each stage, but they must synchronize at the end of each stage at
a synchronization point called a barrier. If a thread reaches the barrier before all other
threads have arrived, it waits. When all threads reach the barrier, they are notified and
can begin execution on the next phase of the computation.
There are three complications to barriers. First, there is no master thread that controls
the threads, waits for each of them to reach the barrier, and then tells them to re-start.
Instead, the threads must monitor themselves and determine when they should wait or
proceed. Second, for many dynamic programs, the number of threads that will be
created during the lifetime of the parallel program is unknown in advance, since a
thread can spawn another thread, which will start in the same program stage as the
thread that created it. Third, a thread may end before reaching the barrier. In all cases,
all active threads (those that have not ended) must synchronize at the barrier before
the processing is allowed to proceed to the next phase.
Provide the pseudo-code for a class called Barrier that enables this style of
barrier synchronization. Your solution must support creation of a new thread (an
additional thread that needs to synchronize), termination of a thread (one less thread
that needs to synchronize), waiting when a thread reaches the barrier early, and
releasing waiting threads when the last thread reaches the barrier. Implement your
solution using monitors (e.g., wait(), signal(), and
signalAll()). Your class must implement the following three methods:
threadCreated(), threadEnd(), barrierReached(). We have provided code
skeletons below. Please fill in the blank areas.
Class Barrier () {
condition barrier; Lock lock = FREE;
int numThreads = 0; int numThreadsAtBarrier = 0;
threadCreated() {
lock.acquire();
numThreads++;
lock.release();
}
threadEnd() {
lock.acquire();
numThreads--;
if (numThreadsAtBarrier == numThreads) {
numThreadsAtBarrier = 0;
barrier.signalAll();
}
lock.release();
}
barrierReached() {
lock.acquire();
numThreadsAtBarrier++;
if (numThreadsAtBarrier < numThreads) {
barrier.wait(&lock);
} else {
numThreadsAtBarrier = 0;
barrier.signalAll();
}
lock.release();
}
}
We subtracted points as follow:
Answers with semaphores received no credit
Answers without locks lost 10 points, incorrect lock use lost 2 points for
each error (max –10 points)
If your threadEnd procedure didn’t check the ending thread was the last
one not at the barrier, you lost 4 points
If threads could slip through your barrierReached, you lost 6 to 10 points
If not all threads were released after the barrier, you lost 8 points
Excessive thread wakeups (e.g., in threadEnd) cost you 2 points
Answers with indefinite waiting (never finishing the barrier) lost 10 points
Answers with busy waiting lost 10 points
5. (20 pts) Deadlocks
Consider the following snapshot of a system:
C (Current
allocation
matrix)
R (Total
Request matrix)
A (Available
resource vector)
A B C D A B C D A B C D
P0 0 0 1 2 0 0 3 2 2 1 2 0
P1 2 0 0 0 2 7 5 0
P2 0 0 3 4 6 6 5 6
P3 2 3 5 4 4 3 5 6
P4 0 3 3 2 0 6 5 2
Answer the following questions using Banker’s algorithm:
a. (12 pts) Determine if the system is currently in a safe state using Banker’s algorithm.
(Hint: first determine the matrix of additional resources needed by each process, then
find a sequence of process executions that can complete successfully. We have
provided the tables below, so you only need to fill in the blanks.)
Answer: R – C = Need (maxtrix)
Still Needed
A B C D
P0 0 0 2 0
P1 0 7 5 0
P2 6 6 2 2
P3 2 0 0 2
P4 0 3 2 0
The allocation should be safe right now, with a sequence of process executions.
Answer: Yes, with <P0, P3, P4, P1, P2>.
Resources available after
each process has finished
A B C D
P0 2 1 3 2
P3 4 4 8 6
P4 4 7 11 8
P1 6 7 11 8
P2 6 7 14 12
b. (8 pts) If a request from process P2 arrives for resources (0, 1, 2, 0), can the requested
be granted immediately? If yes, then show the sequence of successful process
executions in tabular form; if no, then you do not need to show any further details.
Answer: No, this cannot be allocated. If this is allocated, the resulting Available() is (2, 0, 0,
0), there is no sequence of the process execution order that lead to the completion of all
processes. This is an unsafe state.