------------------------------ MODULE threads ------------------------------ EXTENDS TLC, Integers CONSTANT Threads (*--algorithm dekker variables flag = [t \in Threads |-> FALSE]; fair process thread \in Threads begin P1: flag[self] := TRUE; P2: while \E t \in Threads \ {self}: flag[t] do P2_1: flag[self] := FALSE; P2_2: flag[self] := TRUE; end while; CS: skip; P3: flag[self] := FALSE; end process; end algorithm; *) \* BEGIN TRANSLATION VARIABLES flag, pc vars == << flag, pc >> ProcSet == (Threads) Init == (* Global variables *) /\ flag = [t \in Threads |-> FALSE] /\ pc = [self \in ProcSet |-> "P1"] P1(self) == /\ pc[self] = "P1" /\ flag' = [flag EXCEPT ![self] = TRUE] /\ pc' = [pc EXCEPT ![self] = "P2"] P2(self) == /\ pc[self] = "P2" /\ IF \E t \in Threads \ {self}: flag[t] THEN /\ pc' = [pc EXCEPT ![self] = "P2_1"] ELSE /\ pc' = [pc EXCEPT ![self] = "CS"] /\ flag' = flag P2_1(self) == /\ pc[self] = "P2_1" /\ flag' = [flag EXCEPT ![self] = FALSE] /\ pc' = [pc EXCEPT ![self] = "P2_2"] P2_2(self) == /\ pc[self] = "P2_2" /\ flag' = [flag EXCEPT ![self] = TRUE] /\ pc' = [pc EXCEPT ![self] = "P2"] CS(self) == /\ pc[self] = "CS" /\ TRUE /\ pc' = [pc EXCEPT ![self] = "P3"] /\ flag' = flag P3(self) == /\ pc[self] = "P3" /\ flag' = [flag EXCEPT ![self] = FALSE] /\ pc' = [pc EXCEPT ![self] = "Done"] thread(self) == P1(self) \/ P2(self) \/ P2_1(self) \/ P2_2(self) \/ CS(self) \/ P3(self) Next == (\E self \in Threads: thread(self)) \/ (* Disjunct to prevent deadlock on termination *) ((\A self \in ProcSet: pc[self] = "Done") /\ UNCHANGED vars) Spec == /\ Init /\ [][Next]_vars /\ \A self \in Threads : WF_vars(thread(self)) Termination == <>(\A self \in ProcSet: pc[self] = "Done") \* END TRANSLATION OnlyOneCritical == \A t1, t2 \in Threads: /\ pc[t1] = "CS" /\ pc[t2] = "CS" => t1 = t2 NoLiveLocks == \A t \in Threads: <>(pc[t] = "CS") =============================================================================