Producer-Consumer, Readers-Writers and Dining Philosophers for GATE: Semaphore Trace Tables

Counting semaphore values traced line by line through producer-consumer, readers-writers and dining philosophers: the trace tables, the negative-value rule, the swapped-wait deadlock, and how GATE multiple-select questions test each one.

Prashant Jain

KnowledgeGate AI educator

Updated 14 Jul 20266 min read

GATE does not ask you to recite the producer-consumer solution. It gives you the code, runs an interleaving through it, and asks for a semaphore's final value, how many processes are blocked, or which swapped line causes deadlock. That is a trace-table skill, and most aspirants never practise it as one. Here we trace each classic synchronisation problem line by line, with the exact traps multiple-select questions are built on.

Counting semaphores: the two rules every trace table uses

A counting semaphore S is an integer manipulated by two atomic operations. In the standard textbook definition, the one GATE pseudocode almost always follows:

  • wait(S) (also written P(S) or down(S)): decrement S by 1. If S becomes negative, the calling process blocks and joins S's queue.

  • signal(S) (also written V(S) or up(S)): increment S by 1. If S is still zero or negative after the increment, wake one blocked process.

Two consequences do all the work:

  1. The invariant. At any instant, S = initial value + (signals completed) − (waits executed). Nothing else ever changes it.

  2. The reading of a negative value. When S is negative, its magnitude is exactly the number of processes blocked on S. When S is positive, it counts how many waits can still succeed without blocking.

Some books use a convention where wait blocks while S is 0 and the value never goes negative. The pseudocode printed in the question decides; when only "counting semaphore" is stated, the decrement-then-block definition above is standard, and everything below uses it.

Producer-consumer: the bounded-buffer trace table

The bounded-buffer solution uses three semaphores for a buffer of size N: empty = N (free slots), full = 0 (filled slots), mutex = 1 (guards the buffer). The producer runs wait(empty), wait(mutex), insert, signal(mutex), signal(full); the consumer runs wait(full), wait(mutex), remove, signal(mutex), signal(empty). Order matters, which is what the trap below exploits.

Take N = 3, with consumer C1 arriving before anything is produced, then producer P1 producing one item.

Step

Operation

empty

full

mutex

What happened

start

initial values

3

0

1

buffer empty

1

C1: wait(full)

3

-1

1

C1 blocks, no item exists

2

P1: wait(empty)

2

-1

1

a free slot is claimed

3

P1: wait(mutex)

2

-1

0

P1 enters the buffer

4

P1: signal(mutex)

2

-1

1

item placed, buffer released

5

P1: signal(full)

2

0

1

full rises to 0, C1 wakes

6

C1: wait(mutex)

2

0

0

C1 enters the buffer

7

C1: signal(mutex)

2

0

1

item removed

8

C1: signal(empty)

3

0

1

back to the start state

Read step 1 again, because it is the trap. After it, full is −1, not 0: a blocked consumer drives the semaphore negative, and the magnitude counts the waiters. In general, with p producers and c consumers, full ranges over [−c, N] and empty over [−p, N]. Range statements like these are standard multiple-select bait.

The swapped-wait deadlock, traced

Now the classic single-line mutation: the producer runs wait(mutex) before wait(empty), starting from a full buffer (empty = 0, full = 3, mutex = 1).

Step

Operation

empty

full

mutex

What happened

1

P1: wait(mutex)

0

3

0

P1 takes the buffer lock

2

P1: wait(empty)

-1

3

0

P1 blocks holding mutex

3

C1: wait(full)

-1

2

0

an item exists, C1 passes

4

C1: wait(mutex)

-1

2

-1

C1 blocks on the held lock

P1 waits for empty, which only C1 can signal. C1 waits for mutex, which only P1 holds. Circular wait, deadlock, and the final snapshot (empty = −1, full = 2, mutex = −1) is exactly the value set GATE asks you to produce. Note the asymmetry examiners love: swapping the two waits can deadlock; swapping the two signals only reorders wakeups and is harmless.

Two-node cycle. P1 holds mutex and requests empty; C1 holds nothing it can trade, requests mutex; the signal(empty) that would free P1 sits after C1's blocked wait, closing the cycle.

Readers-writers: tracing readcount and wrt together

The first-readers-preference solution uses an integer readcount = 0 and two semaphores: mutex = 1 guarding readcount, wrt = 1 guarding the data. A writer does wait(wrt), writes, signal(wrt). A reader increments readcount under mutex, and only the first reader in does wait(wrt); on exit, only the last reader out does signal(wrt). Trace two readers overlapping one writer:

Step

Operation

readcount

mutex

wrt

What happened

start

initial values

0

1

1

idle

1

R1: wait(mutex); readcount=1

1

0

1

first reader in

2

R1: wait(wrt); signal(mutex)

1

1

0

R1 locks writers out, reads

3

R2: wait(mutex); readcount=2; signal(mutex)

2

1

0

not first, skips wrt, reads

4

W1: wait(wrt)

2

1

-1

writer blocks behind readers

5

R1 exits: readcount=1

1

1

-1

not last, wrt untouched

6

R2 exits: readcount=0; signal(wrt)

0

1

0

last reader out, W1 wakes

7

W1 writes; signal(wrt)

0

1

1

back to idle

Three facts fall straight out of the table, and all three appear as answer options. First, wrt is touched only by the first reader in and the last reader out; a middle reader never changes it. Second, while readers hold the data and w writers wait, wrt sits at −w. Third, readcount is a plain integer, not a semaphore; it stays consistent only because mutex serialises every touch. The structural weakness is visible too: as long as new readers keep arriving, readcount never returns to 0 and the writer at step 4 starves. This variant is the writers-can-starve solution.

Dining philosophers: tracing five chopsticks into deadlock

Five philosophers, five chopsticks, each chopstick a semaphore initialised to 1. The naive protocol for philosopher i: wait(chopstick[i]), wait(chopstick[(i+1) mod 5]), eat, signal both. Run the worst case: all five get hungry at once, and each completes its first wait before any starts the second.

  • After round one, every chopstick reads 0: five waits succeeded, each philosopher holds a left chopstick.

  • In round two, each waits on the right chopstick, which a neighbour holds. Every chopstick drops to −1 and every philosopher blocks.

All four deadlock conditions hold, and the trace shows the numbers: five processes blocked, each semaphore at −1. GATE variants then ask which fix breaks the cycle:

  • At most four at the table. Add a semaphore room = 4, waited on before the first chopstick. If all five arrive, room runs 4, 3, 2, 1, 0, then −1: one philosopher blocks at the door and the remaining four can never close a five-way cycle.

  • Break the symmetry. Make one philosopher (or every even-numbered one) pick the right chopstick first, so the circular wait cannot close.

  • Pick both atomically. Take both chopsticks inside one critical section, so round one's hold-and-wait never forms.

Five philosophers around a circle, five chopstick nodes between them, every philosopher holding the left chopstick with an arrow requesting the right one, forming a closed five-edge cycle.

How GATE tests semaphore traces

The multiple-select format is the natural home for this topic: each classic problem generates several independently checkable statements, a final semaphore value, a blocked-process count, a range claim, a deadlock or starvation claim. You clear such a question only by running the table. For scoring rules and the current paper pattern, rely on the official GATE information brochure published by the organising institute for your cycle, not a coaching summary. Use the current official GATE portal to locate the organising institute's cycle-specific brochure.

Two habits make the traces fast. First, use the invariant instead of simulating mentally: value = initial + signals − waits, then check the sign. Second, always ask which process a signal wakes, because the woken process completes its wait without decrementing again. If the topic still feels loose, the concept sequence in Operating Systems for GATE places synchronisation next to scheduling and deadlock, and the Operating System, Process Synchronization learn module carries the solved-question drill for exactly these problems.

The short version and your next step

Learn the two semaphore rules, then hand-trace each classic once: producer-consumer to a negative full, the swapped-wait deadlock to its final snapshot, readers-writers through first-in and last-out, and dining philosophers into the five-way cycle. After that, every trace question is arithmetic.

For a structured route through the whole OS paper, GATE Guidance by Sanchit Sir builds a personalised plan around your target score, and the GATE CS Exam category collects the subject resources if you only need to patch specific topics. Ten traced tables beat a hundred read pages; start with the three above.