CEG 7370: Distributed Computing Principles

Notes on Passing The Baton Technique

Converting an await-based solution to one that uses semaphores.

Semaphores/Counters

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] === < S[i] >

N[i] are atomic code segments with no awaits.

P(e); 
S[i]; 
PASS-BATON

A[j] === < await B[j] → S[j] >

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 	

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

Readers/Writers by Andrew, 1990 - Original

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

Reader[i:1..M] ::

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

Writer[j:1..N] ::

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

Readers/Writers by Andrew - With writers having priority

Reader[i:1..M] ::

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

Writer[j:1..N] ::

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