Introduce
e: semaphore := 1;
b[j]: semaphore := 0;
d[j]: counter := 0;
The e and the b[j] together constitute a split-binary semaphore. That is, sumOfAll b[k] + e is either a 0 or a 1.
Collect the code segments into the two groups, N[i] and A[j] and
replace them with the code shown below.
N[i] are atomic code segments with no awaits.
P(e); S[i]; PASS-BATON
A[j] are atomic code segments *with* awaits.
P(e); if not B[j] -> d[j] := d[j] + 1; V(e); P(b[j]); fi; S[j]; PASS-BATON
// Invariant I === sumOfAll b[k] == 0 ^ e=0
if
.
.
.
[] B[k] ^ d[k] > 0 ->
// {I ^ B[k] ^ d[k] > 0 }
d[k] := d[k] - 1; // {I ^ B[k] ^ d[k] ≥ 0 }
V(b[k]) // {I ^ B[k] ^ d[k] ≥ 0 }
[]
.
.
.
[] else --> V(e)
fi
Initially: counter nr := 0, nw := 0, dr := 0, dw := 0 semaphore e := 1, r := 0, w := 0 Invariant: RW == ( [nr = 0] or [nw = 0] ) and nw <= 1
do true ->
P(e) ;
if nw = 0 -> skip
[] nw > 0 ->
dr++ ;
V(e) ;
P(r)
fi
nr++ ;
if dr = 0 -> V(e)
[] dr > 0 -> dr--; V(r)
fi
...read...;
P(e) ;
nr-- ;
if nr > 0 or dw = 0 -> V(e)
[] nr = 0 and dw > 0 -> dw--; V(w)
fi
od
do true ->
P(e) ;
if nr = 0 and nw = 0 -> skip
[] nr > 0 or nw > 0 ->
dw++ ;
V(e) ;
P(w)
fi ;
nw++;
V(e) ;
...write...;
P(e) ;
nw-- ;
if dr = 0 and dw = 0 ->V(e)
[] dw > 0 -> dw--; V(w)
[] dr > 0 -> dr--; V(r)
fi
od
do true ->
P(e);
if nw = 0 -> skip
[] nw > 0 or dw > 0 -> //new readers are delayed if a writer is waiting now
dr++ ;
V(e) ;
P(r)
fi ;
nr++;
if dr = 0 -> V(e)
[] dr > 0 -> dr--; V(r)
fi
...read...
P(e) ;
nr-- ;
if nr > 0 or dw = 0 -> V(e)
[] nr = 0 and dw > 0 -> dw--; V(w)
fi
od
do true ->
P(e) ;
if nr = 0 and nw = 0 -> skip
[] nr > 0 or nw > 0 ->
dw++ ;
V(e) ;
P(w)
fi ;
nw++;
V(e)
...write...;
P(e) ;
nw-- ;
if dr = 0 and dw = 0 -> V(e)
[] dw > 0 -> dw--; V(w)
[] dr > 0 and dw = 0 -> dr--; V(r) //a delayed reader is resumed only if no writer is waiting
fi
od