Proof of Correctness of Algorithm 3, Chapter 6, Silberschatz & Galvin This algorithm is due to Peterson (1981) It solves the critical section problem for two concurrent processes that share access to an array of two flags and a variable called "turn". Code for P0 Code for P1 repeat repeat flag[0] := true ; 1 flag[1] := true ; turn := 1 ; 2 turn := 0 ; while (flag[1] 3 while (flag[0] and turn=1) 4 and turn=0) do skip ; 5 do skip ; .. CS(P0) .. 6 .. CS(P1) .. flag[0] := false ; 7 flag[1] := false ; .. RS(P0) .. 8 .. RS(P1) .. until false until false Mutual Exclusion Proof: Assume that coexistence happens. Let T0 be the instant of time that the coexistence FIRST occurs (in the life of the two processes). We may also assume, without loss of generality (WOLOG), that P0 arrives in CS(P0) at time T0. (ONE of the processes must arrive at that time, if it is P1, then switch the names of the processes!) It follows that P1 must either enter CS(P1) BEFORE T0, or at least at exactly time T0. (Remember, this solution applies to a multi-PROCESSING environment, as well as to a multi-PROGRAMMING environment, so two processes really can do some things SIMULTANEOUSLY.) Let T1 be the very LAST time <= to T0 that P1 enters CS(P1). It follows from these definitions that, P1 REMAINS in CS(P1) during the time between T1 and T0. (If P1 left CS(P1) after T1 and before T0, then it would have to re-enter again no later than T0 to be there for the "magic moment" of first coexistence. But T1 is the LAST time <= to T0 that P1 enters CS(P1)!) ---------------------------------------------------------------------- ^ ^ ^ ^ ^ ^ T1 T0 Fig 1. P1 may enter CS(P1) MANY times before time T0, but T1 is the LAST time no later than T0 that P1 enters CS(P1). Let T0-set be the LAST time before T0 that P0 completes the execution of instruction 2. Similarly, let T1-set be the LAST time before T1 that P1 completes instruction 2. Note that between T1-set and T0, P1 REMAINS in the part of its code that is after 2 and before 7. ---------------------------------------------------------------------- ^ ^ ^ T1-set T1 T0 (P1 past 2) (P1 still before 7) Fig 2. What happens if both processes try to execute 2 at about the same time? Our assumptions about the hardware on which the processes are running tell us that in the event of such a "race conditon", the outcome of the race is guaranteed to be the same as if the two instructions were executed SEQUENTIALLY (one after the other) in some order, but not in an order we can necessarily predict in advance. Suppose that T1-set < T0-set (or that T1-set = T0-set and that P1 is the "winner of the race", so that "turn" = 1 after time T0-set). Then T1-set <= T0-set < T0, so at time T0-set 1. P1 will be executing somewhere after 2 and before 7, so the value of flag[1] will be true, and will remain so until after T0, 2. "turn" will have just been set to 1 by P0, and there will be no possibility of "turn" being set back to 0 until some time after T0. Thus both of P0's loop conditions will remain TRUE from time T0-set, right through to, and including, time T0: (flag[1] = true) and (turn = 1). But P0 enters the loop at 3 some time after T0-set, and gets out of it no later than T0 in order to arrive in CS(P0) at time T0. Since P0 CAN'T get out of the loop until one of the loop conditions becomes false, we see that we have come up against an obvious contradiction. So IF P0 and P1 really do come to co-exist in their CS's, it must be that T0-set < T1-set. ---------------------------------------------------------------------- ^ ^ ^ ^ T0-set T1-set T1 T0 (P1 past 2) (P1 still before 7) Fig 3. But if THAT is true, then after T1-set but before T0, BOTH flags are true and "turn" = 0 (it can't be 1 because P1 sets it to 0 at time T1-set, and P0 remains in the code after 2 and before 7 all through the time between T0-set and T0). THAT is a contradiction, because it implies that P1 can't get out of ITS while-loop until after T0 -- which was defined to be a time when BOTH processes are in their CS's. So now we have run out of possibilities. There is no ordering of the times T0, T1, T0-set, and T1-set that is logically consistent! So the assumption upon which we based our definition of these times must be incorrect -- in short, it must be impossible for P0 and P1 to be in their CS's concurrently. Progress Proof: It's quite obvious that progress is assured, so the proof is short: If a process is executing in its remainder section, then clearly its flag is FALSE. Thus the other process has no difficulty getting out of its while loop and entering the CS. There is NO postponement of the other process (all that has to be done is one evaluation of the loop conditions), and the process executing in its RS has no say about whether the other process gets in, DESPITE the fact that "turn" might be "in its favor". Bounded Waiting Proof: If P0, say. has arrived in its while loop, then it can enter the CS when flag[1] is false OR when "turn" = 0. If P1 is executing in its RS, its flag will be false, and P0 will enter with no wait. If P1 is in contention with P0 to enter its own CS, and if P1 has won the race to set "turn", then it will enter its CS, if not P0 will enter with no wait. If P1 is in its CS when P0 begins its wait, or if P1 wins a race and enters ahead of P0, it will eventually set "turn" to 0 and enter the loop again (unless it halts! -- just kidding, in this context, it's not "allowed" to halt). That will assure that P0 gets in to its CS before P1 can get in again (even if P1 is fast enough to set its flag to false and back to true again before P0 has had time to notice). In any case P0 gets in after P1 gets in AT MOST ONCE.