(5.7) Consider a system running ten I/O-bound tasks and one CPU-bound task. Assume that the I/O-bound tasks issue an I/O operation once for every millisecond of CPU computing and that each I/O operation takes 10 milliseconds to complete. Also assume that the context-switching overhead is 0.1 millisecond and that all processes are long-runing tasks. What is the CPU utilization for a round-robin scheduler when:
a. The time quantum is 1 millisecond
b. The time quantum is 10 milliseconds
(5.10) Explain the differences in the degree to which the following scheduling algorithms discriminate in favor of short processes:
a. FCFS
b. RR
c. Multilevel feedback queues
(7.1) Consider the traffic deadlock depicted in Figure 7.9 in the book.
a. Show that the four necessary conditions for deadlock
indeed hold in this example.
b. State a simple rule that will avoid deadlocks in this
system.
a. Write a monitor that implements Barrier using Mesa semantics.
monitor Barrier {
...
}
b. Implement Barrier using an explicit mutex and condition variable. The mutex and condition variable have the semantics described at the end of the "Semaphore and Monitor" lecture in the ping_pong example, and as implemented by you in Project 1.
class Barrier {
...private variables...
void Done (int n) {
...
}
...
}
c. A more socially conscious implementation of the Mating Whale problem in the first Nachos project would allow any three whales that call their respective Whale methods to mate. Solving this form of the problem is very straightforward using a Barrier. Implement the Whale class with these semantics using a Barrier, where the Male, Female, and Matchmaker methods in Whale simply make a call to a Barrier. (Hint: The implementation should be trivial.)
Hint: This problem is very similar to the producer/consumer problem — it just so happens that objects are produced in pairs, and each part of a pair is consumed individually.
Write a Mesa-style monitor for this problem. It should have three entry methods: void Put(int a, b) that p would use to produce values, int GetA(void) that c1 would use to consume a values, and int GetB(void) that c2 would use to consume b values. For synchronization, you should only use condition variables.
An example sequence of calls could be:
Put(10,20) GetA() -> returns 10 Put(300,400) GetA() -> returns 300 GetB() -> returns 20 GetA() blocks the caller
Consider the following state: