NivaarExam PrepOfficial exam papers ↗

25-Comp-A5 Operating Systems · December 2019

Question 2 of 7

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

17-Comp-A5, Operating Systems — National Examinations, December 2019. 3-hour closed-book paper, 7 questions of 20 marks each (candidates asked to answer any 5; all 7 answered here). Total 100 marks.

Reference texts: Silberschatz, Galvin & Gagne, Operating System Concepts (10th ed., Wiley) — CPU scheduling (Ch.5), process synchronization (Ch.6–7), deadlocks (Ch.8), main memory (Ch.9), virtual memory (Ch.10), mass-storage/disk scheduling (Ch.11), file-system implementation/free-space management (Ch.12–14).

Data used below. (1) Q1(a): Proc3's execution time is 21 s (the printed column reads 14, 7, 21, 2, 1 for Proc1–5). (2) Q3(c): the base (relocation) register is 1500. (3) Q5(a) states that the disk has 160 tracks numbered 0 to 159, yet its request queue includes tracks 160, 174 and 176. This inconsistency in the paper is resolved by adopting a 200-track disk (0–199) for the C-SCAN calculation, the only sub-part affected. (4) Q6(b) lists the free holes as 305K/245K/405K/470K/270K/291K/325K/350K, but the next sentence restates the first two as 302K and 243K, a proofing slip in the paper; the full eight-value list is used throughout.

Question 2 (20 marks)

Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.

(a) The algorithm has one genuinely incorrect (mutual-exclusion-violating) defect plus design flaws (busy waiting, no bounded waiting) that do not by themselves corrupt a result; each occurs symmetrically in P0 and P1 and is explained once.

Defect 1 (correctness — mutual exclusion can actually fail). The retreat-and-re-raise pattern (check0=false; while(check1); check0=true;) contains no re-check of check1 immediately before the unconditional re-raise, and no shared "whose turn is it" tie-breaker (unlike Peterson's algorithm, which adds exactly such a turn variable to this same flag skeleton). If both processes retreat in lockstep — each sees the other's flag raised, both lower their own flag and spin, and both then observe the other's flag drop to false during the same interval — both re-raise unconditionally and both fall through into the critical section simultaneously. A concrete interleaving that forces this:

StepActioncheck0check1
1P0 sets check0 = trueTF
2P1 sets check1 = trueTT
3P0 tests check1 (true) → enters retreat branchTT
4P1 tests check0 (true) → enters retreat branchTT
5P0 sets check0 = false (retreating)FT
6P1 sets check1 = false (retreating)FF
7P0's spin re-tests check1 (now false) → exits spinFF
8P1's spin re-tests check0 (now false) → exits spinFF
9P0 sets check0 = true (unconditional re-raise) → enters CSTF
10P1 sets check1 = true (unconditional re-raise) → enters CSTT

At step 10 both processes are inside their critical sections simultaneously — mutual exclusion is violated. This is not a rare corner case invented for the exam; it is exactly the failure Peterson's algorithm's turn variable exists to rule out (whichever process set turn to the other's id last is forced to wait, breaking the lockstep symmetry above).

Defect 2 (design flaw — busy waiting). Each retreating process waits in while(check1){no-op}; (P0) / while(check0){no-op}; (P1), a spin loop that consumes its whole CPU quantum repeatedly testing a flag that cannot change until the other process is scheduled. On a uniprocessor this is pure waste (the flag it is waiting on can only change when it is descheduled), and the results are still correct — exactly the question's “may not give rise to incorrect results but indicates a flaw in design” category. A blocking primitive (semaphore/condition variable) should be used instead. The same flaw occurs symmetrically in P1.

Defect 3 (no bounded waiting — a retreating process can starve). While P0 spins it has lowered check0, so P1 can repeatedly run check1=true → test check0 (false) → enter its CS directly, then set check1=false, run its RS and raise check1 again. P0 escapes the spin only if it happens to be scheduled during the short window in which check1 is false; an unlucky (but legal) schedule can keep missing that window forever, so there is no bound on how many times P1 enters its CS ahead of P0 (and symmetrically for P1). Note what does not happen: the algorithm cannot deadlock or livelock, because the retreat happens only once per attempt and, if both processes are spinning at the same time, both flags are necessarily false so both leave the spin — the price of that “progress” is precisely the unconditional entry that causes Defect 1. A fourth, related point: the if-test and the re-raise are separate non-atomic steps, so every check-then-act on the shared flags is itself a race window; this is the root cause of Defect 1 in both processes.

(b) Monitors and the three critical-section requirements. A monitor is a language-level construct that automatically wraps every one of its procedure bodies in an implicit lock, so only one process can be executing any monitor procedure at a time.

(c) Starvation. Starvation (indefinite postponement) is the situation where a process that is ready to run and would eventually be scheduled under a fair policy instead waits for an unbounded, in principle infinite, amount of time because the scheduler's rule keeps preferring other processes. Under strict (non-aged) priority-based CPU scheduling, a low-priority process starves whenever a steady stream of higher-priority processes keeps arriving: each time the low-priority process is about to reach the head of the ready queue, a new higher-priority arrival preempts it (if preemptive) or is simply dispatched ahead of it (if non-preemptive), so it never actually receives the CPU. Example: on a system running a continuous stream of high-priority interactive/real-time tasks (e.g. keyboard/network interrupts serviced as priority-1 work) alongside one priority-10 batch job, the batch job can wait indefinitely if the priority-1 workload never lets up, even though the CPU is technically being fully utilised the whole time. The standard remedy is aging: gradually increase a waiting process's priority the longer it waits, so it eventually becomes the highest-priority ready process and is guaranteed to run.