CS 3750 Handout on an alternative to the Bakery Algorithm, which does not use unique id numbers (at least not in the same way as the Bakery Algorithm) This Algorithm (Eisenberg and McGuire, 1972) Solves the Critical Section Problem for N Processes. Algorithm 5 : The common data structures are: var flag: array [0 .. n-1] of (idle, want-in, in-cs) ; turn: 0 .. n-1 ; All the elements of flag are initially idle, the initial value of "turn" is immaterial (between 0 and n-1). The structure of process Pi is: VAR j: 0..n ; REPEAT REPEAT 1 flag[i] := want-in ; (* I tell everybody I want in *) (* I wait until a sweep from "turn" around "clockwise" to me finds everyone idle -- they have "priority" over me right now.*) 2 j := turn ; 2 WHILE j <> i 2 DO IF flag[j] <> idle THEN j := turn ELSE j := j+1 mod n ; (* I tell everybody I am in the critical section. (but I'm NOT!) *) 3 flag[i] := in-cs ; (* search the whole ring for someone besides me with flag = "in-cs" *) 4 j := 0 ; 4 WHILE (j < n) AND ((j = i) OR (flag[j] <> in-cs)) DO j := j+1 ; (* if (the search fails) and ( (it's my turn) or (P*, the process whos turn it is, is idle)) then I go in to the CS. If not, I start over at 1. *) 4 UNTIL (j >= n) AND ((turn = i) OR (flag[turn] = idle)) ; 5 turn := i ; (* It is my turn, and I go in. *) 6 .. CS .. (* I find the first process clockwise from "turn" who is not idle, and make it be the turn of THAT process. (Note: "turn" is ME when I start this, and it will still be MY turn after lines 7, if everyone else is idle.) *) 7 j := turn+1 mod n ; 7 WHILE (flag[j] = idle) DO j := j+1 mod n ; 7 turn := j ; 8 flag[i] := idle ; (* I tell everybody I am idle *) 9 .. RS .. UNTIL false ; It is helpful to think of the processes as arranged by number in a circle like this: 0 11 1 10 2 me 9 3 8 4 7 5 "turn" 6 Fig 1. Proof of MUTUAL EXCLUSION in Algorithm 5: As in the proof of algorithm 4, we assume that Pk enters its CS at time Tk, REMAINS there for a "while" (0 time or more), and is then joined there for the first time by Pm at time Tm. We let Tm-set be the LAST time before Tm that Pm sets its flag to "in-cs" in 3. Similarly, Tk-set is the LAST time before Tk that Pk sets its flag to "in-cs". ---------------------------------------------------------------------- ^ ^ ^ Tk-set Tk Tm Fig. 2 Suppose that Tm-set < Tk-set (or that Tm-set = Tk-set). Then during all the time between Tk-set and Tk (inclusive), Pm is executing somewhere between 4 and 6, so flag[m]=in-cs during all that time. On the other hand, since Pk is able to enter the CS at time Tk, at SOME time between Tk-set and Tk, Pk verifies in 4 that flag[m] <> in-cs! That is contradictory, so we can conclude that Tk-set < Tm-set. After Tk-set, there is no opportunity for Pk to change the value of flag[k] until after Pk leaves the CS, some time after Tm. Since Tm-set is after Tk-set, that implies that the value of flag[k] is "in-cs" during all the time between Tm-set and Tm. But then THAT contradicts the fact that in order for Pm to enter the CS at time Tm, it must verify in 4 that flag[k] <> in-cs at some time between Tm-set and Tm! So there is NO chronological relationship among Tk, Tk-set, Tm, and Tm-set that is logically consistent with their definitions. We can therefore conclude that the assumption upon which their definitions is based -- the coexistence of Pk and Pm in the CS at time Tm -- is impossible. Proof of PROGRESS in Algorithm 5: Processes set their flag to "idle" in 8 before entering their RS. The RS contains no code that sets any flags. As a result, while executing in their RS, processes always have their flag set to "idle". When the CS is empty and processes are contending for entry, it is only the value of "turn", and flag values <> idle that can prevent a contending process from getting into its CS. Thus processes executing in their remainder sections do not affect the decision. Suppose that S is a subset of the n processes, and that P' is the member of S whose number is closest to the value of "turn" (measured by going clockwise to P' from "turn"). If the members of S are contending to get into the CS, with no other processes entering contention, and if the value of "turn" is constant during this time, and if the decision as to who gets into the CS is postponed long enough, then all the members of S besides P' will eventually get stuck in the loop at 2. After that, under the assumptions above, the only thing that can postpone a decision to let P' into the CS is if a process is still executing in the exit section (7-8) and has not yet set its flag to "idle", with the result that P' is also being forced to stay in the WHILE loop of 2. Of course, that process will leave the exit section eventually (after executing a bounded number of instructions). Thus, if the postponement still persists, it can only then be due to the fact that more processes are entering into contention for the CS. (For example if turn = 4, P8 is stuck in the WHILE loop in 2, P7 is entering the WHILE loop in 4, and P5 begins to contend and succeeds in executing 1 before P7 gets to the part of the WHILE loop in 4 where j = 5, then P5 has effectively stopped P7 from entering the CS, and will enter instead (unless P4 pulls that same trick on P5!). But if the decision continues to be postponed long enough, then sufficient time will pass so that ALL n processes are executing in the entry section (1-4), and all the processes except P* (the process whose turn it is) are caught in the while loop of 2. Once that has occured, P* will be able to get into the CS, thus ending the postponement. Proof of BOUNDED WAITING in Algorithm 5: If there are processes contending to enter the CS, each process Pi that leaves the CS advances "turn" to the NEXT CONTENDING PROCESS after i in the cyclic ordering. This introduces a "ratcheting" influence with a step of at least 1. An argument very similar to one used in the Progress proof above will show that if S is any subset of the n processes that contains P*, and if the processes in S contend for the CS until one of them gets in, it will be P* that gets in -- even if other processes join the contention as it progresses. If a process Pj begins to contend for the CS and then has to yield to another process Pk, then Pk will designate its successor (call it Pm) by setting "turn" after leaving the CS. Since it will then be Pm's turn, Pm will be next to enter the CS. Then, if there are still processes contending for the CS, Pm will designate its successor into the CS by setting "turn". This will go on at least as long as Pj remains in contention for the CS. After "turn" is set to k in 5, and as long as some process remains "non-idle" in the entry section, line 5 will not change the value of "turn" -- "turn" will only change in 7, where the turn is given to the next "non-idle" process in clockwise order. (Note that the first process to enter the CS after a period of no contention MAY actually CHANGE the value of "turn" in line 5, because P* may have its flag set to "idle".) Thus after process Pj has begun to contend to enter the CS and has had to yield to Pk, each process that leaves the CS will move the value of "turn" in a clockwise direction closer to j by a step of at least one, WITHOUT GOING PAST j, and the result will be that "turn" will be set to j after Pj has yielded to another process no more than n-1 times, after which Pj will be the next to enter the CS. "PATHOLOGICAL" EXAMPLE: 0 7 1 6 2 5 3 4 Fig. 3 Initially all idle. Turn = 0. P7, P5, P3, and P1 come into the entry section, in that order, each getting to the end of part 2 and sleeping before the next enters. Now any of P1, P3, P5, or P7 can wake up and execute parts 3-5, set "turn", enter the CS, and then reset turn to the value of the next contending process after it in the cyclic ordering. If, say, P5 is the one to do that, then after P5 resets "turn", its value is 7. So the value of "turn" has been allowed to jump from 0, to 5, to 7, completely bypassing 1 and 3, even though P1 and P3 are contending for the CS. Can this kind of jumping around of "turn" continue in such a way that P1 or P3 will have to yield the CS more than 7 times? The answer is no. What prevents this from happening?