This web page is organized in way that is useful during my lecture, instead of ppt slides.
The number nP of completed P operations is at most the number nV of completed V operations plus iV the semaphore's initial value:
nP ≤ nV + iV.
Distributed: The state of the semaphore s must be distributed. These counters must not be maintained by just one process. Replicated?
We need a way to count P and V operations and a way to delay P operations. Moreover, the processes that share a semaphore need to cooperate so they maintain the semaphore invariant even though the program state is distributed.
The following algorithm implements one semaphore; let us call it, s.
User[i: 1..n]:: var lc : int := O # users logical clock var ts : int # received in go messages
User processes broadcast on semop[] with k = PEE or VEE only.
This is a collection of n private channels -- in the sense that only User[i] receives on go[i] what is sent by Helper[i].
When the i-th User process wishes to do a V(s), it does the following.
broadcast semop(i, VEE, lc); lc := lc + 1
When the i-th User process wishes to do a P(s), it does the following.
broadcast semop(i, PEE, lc); lc := lc+1; receive go[i](ts); lc := max(lc, ts+1); lc := lc+1
The following is a slightly modified version of 387p, Figure 7.20 of Andrews book.
Helper[i: 1..n]:: var mq : queue of (int, kind, int) # ordered by timestamps var lc : int := O # logical clock var sem : int:= initial value # int value of semaphore var sender : int, k : kind, ts : int do true --> { loop invariant DSEM } receive semop[i](sender, k, ts); lc := max(k, t.s+1); lc := lc+1; if k = PEE or k = VEE --> insert (sender, k, ts) at appropriate place in mq; broadcast semop(i, ACK, lc); lc := lc+1; [] k = ACK --> record that another ACK has been seen; do for all msg in fully acknowledged V messages --> remove msg from mq; sem := sem + 1 od; do for all msg in fully acknowledged P messages such that sem > 0 --> remove msg from mq; sem := sem - 1; if sender = i --> send go[i](lc); lc:= lc+1 fi od fi od
Helper processes send ACKs. They are used to determine when a message in mq has become fully acknowledged.
Consider a message m = (s, k, t) in the queue. Then once the process has received a message with a larger time stamp from every other process, it is assured that it will never see a message with a smaller timestamp. At this point, message m is said to be fully acknowledged.
Moreover, once m is fully acknowledged, then every other message in front of it in mq will also be fully acknowledged since they all have smaller timestamps. Thus, the part of mq containing fully acknowledged messages is a stable prefix: No new messages will ever be inserted into it.
2012 Prabhaker Mateti