advance( E ) Signals occurrence of an event Update eventcount value
read( E ) Returns value of eventcount May or may not count events in progress
await( E, v ) Similar to read( E ) Waits for value v to be reached May not return immediately once the vth advance is executed
Producer/Consumer Example N-cell ring buffer buffer[0:N – 1] Eventcounts IN and OUT produce() to generate items
Single producer code Procedure producer() begin integer i; for i:= 1 to infinity do begin await( OUT, i – N); buffer[i mod N] := produce( ); advance( IN ); end
Single consumer code Procedure consumer() begin integer i; for i := 1 to infinity begin await( IN, i ); consume( buffer[i mod N]); advance( OUT ); end Procedure producer() begin integer i; for i:= 1 to infinity do begin await( OUT, i – N); buffer[i mod N] := produce( ); advance( IN ); end
Possible Situations Fast Producer Producer will wait until item it is trying to overwrite is consumed. Fast Consumer Consumer will wait until the producer has added the value.
EventCount observations How is this solution different than semaphores? Relative ordering rather than mutual exclusion. Producer & consumer can be concurrent. Never does a process have to wait due to synchronization.
Sequencers Used when synchronization requires arbitration Used to order the events Useful with Eventcounts but not on its own Non-decreasing integer value
Sequencer operations ticket(S) Value returned is the process s ordering. Two calls to ticket( S ) will always return different values.
Producer/Consumer Example Same as with Eventcounts but multiple producers now Sequencer T Use ticket(T) to synchronize with other producers
Procedure producer() begin integer t; do forever begin t := ticket(T); await( IN, t); await( OUT, t – N + 1 ) buffer[t+1mod N] := produce( ); advance( IN ); end Procedure producer() begin integer i; for i:= 1 to infinity do begin await( OUT, i – N); buffer[i mod N] := produce( ); advance( IN ); end
Relation to semaphores Lower level than Semaphores Semaphores can be built from Eventcounts and Sequencers
Semaphore Example Semaphore S EventCount is S.E Sequencer is S.T Initial value of S is S.I
Semaphore Wait Procedure P(S) begin integer t; t := ticket( S.T ); await( S.E, t – S.I ); end
Semaphore Signal Procedure V( S ) begin advance( S.E ) end
Deadlock Free Simultaneous P 2 Semaphores R and S Global semaphore G to synchronize part of operation
Procedure Pboth( R, S ) begin integer g, r, s; g := ticket( G.T ); await( G.E, g ); r := ticket( R.T ); s := ticket( S.T ); advance( G.E ); await( R.E, r – R.I ); await( S.E, s – S.I ); end
Observations G is used for obtaining tickets await operation could be deferred Useful in solving the Dining Philosophers Problem
Observations Process destroyed while holding 1 ticket Keep the window during which a process has an unredeemed a ticket short Don t allow destroying the process during the window
Flow of information operations are: Observer or Signaler unlike the semaphore wait Easily adapted to permissions Observer permission(advance). signaler permission(read,await). Useful in secure systems
Secure Readers - Writers Shared database Readers have observer permission Writers have observer and signaler permission Writer priority S and C are eventcounts T is a sequencer
Reader code Procedure reader() begin integer w; abort: w := read(S); await(C, w); read DB if read(S) w then goto abort; end
Writer code Procedure writer() begin integer t; advance( S ); t := ticket( T ); await( C, t ); advance( C ); end
Conclusion new mechanism for synchronization. not based on mutual exclusion. Provides an interface between processes. Information flow paths are clear. Effective in secure systems. Unnecessary serialization avoided.