Petersen Critical Section Correctness
Correctness of Petersen Critical Section Algorithm
This example builds on techniques developed for the Alternating Bit Protocol, but the proof makes especially good
use of the product of case analyses. There are 10 binary cases splits, and
therefore 1024 cases altogether. Although many of these cases are
automatically eliminated by BOBJ because they fail to satisfy the condition of
the equation proved, the output is still very voluminous, since every case is
documented, including the failures. (The purpose of the condition in the
equation of the correctness criterion is to eliminate cases that cannot
occur.) One can also see many instances of circularities in the output,
signaled by the keyword "deduced". This example is still in an
early stage of development, and there is as yet very little explanation; it is
highly likely to become more polished in the future.
The specification and proof score are given in section 1, but only an
extract from the output is given in section 2, since it is very voluminous,
but here is a link to the full output if you want to
see it. Note that execution time is exponential in the number of cases.
Notice also that the fair streams used here differ from those in the
alternating bit protocol, since they need to be fair to each of the two
processes, instead of being fair to channel success, but not failure.
1. BOBJ Source Code
*** file: /tatami/bobj/examples/abp/pete.bob
*** correctness of petersen's critical section algorithm
bth STREAM [ X :: TRIV ] is sort Stream .
op hd_ : Stream -> Elt .
op tl_ : Stream -> Stream .
op _&_ : Elt Stream -> Stream .
var E : Elt . var S : Stream .
eq hd(E & S) = E .
eq tl(E & S) = S .
end
***> fair boolean stream (no infinite consecutive true or false)
bth FAIR-STREAM is pr STREAM[NAT] * (sort Stream to FairStream) + NAT .
op fhd_ : FairStream -> Bool .
op ftl_ : FairStream -> FairStream .
op _#_#_ : Nat Nat FairStream -> FairStream .
vars M N : Nat . var F : FairStream .
eq fhd(0 # M # F) = true .
eq ftl(0 # 0 # F) = F .
eq ftl(0 # s M # F) = 0 # M # F .
eq fhd(s M # N # F) = false .
eq ftl(s M # N # F) = M # N # F .
end
dth MACHINE is sort MState . pr NAT .
op <_,_,_> : Bool Bool Nat -> MState .
ops (idle_) (wait_) (busy_) (run_) : MState -> Bool .
op count _ : MState -> Nat .
op do_ : MState -> MState .
op init__ : Nat MState -> MState .
op begin_ : MState -> MState .
vars B D : Bool . vars M N : Nat .
eq idle = not B .
eq wait = B and not D .
eq busy = B .
eq run = D .
eq count = N .
eq do = if N > 0 .
eq do = .
eq do = if not B or not D .
eq init M = .
eq begin = .
end
dth SYSTEM-STATE is sorts SysState Flag .
pr MACHINE .
ops a b : -> Flag .
op _|_|_ : Flag MState MState -> SysState .
op eq : Flag Flag -> Bool [comm] .
var F : Flag .
eq eq(F, F) = true .
eq eq(a, b) = false .
end
bth PETERSON is pr STREAM[NAT] * (sort Stream to Request) +
STREAM[SYSTEM-STATE] * (sort Stream to Trace) + FAIR-STREAM .
op [_,_,_,_] : SysState Request Request FairStream -> Trace .
var F : Flag . vars Ma Mb : MState .
vars Ra Rb : Request . var Fs : FairStream .
eq hd [ F | Ma | Mb , Ra, Rb, Fs ] = F | Ma | Mb .
*** process A sends a request
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ b | init (hd Ra) Ma | do Mb , tl(Ra), Rb, tl(Fs) ]
if fhd(Fs) and hd(Ra) > 0 and idle Ma .
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ F | Ma | do Mb, tl(Ra), Rb, ftl(Fs) ]
if fhd(Fs) and eq(hd(Ra), 0) and idle Ma .
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ F | begin Ma | do Mb , Ra, Rb, ftl(Fs) ]
if fhd(Fs) and wait Ma and (eq(F, a) or not busy Mb) .
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ F | Ma | do Mb , Ra, Rb, ftl(Fs) ]
if fhd(Fs) and wait Ma and eq(F, b) and busy Mb .
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ F | do Ma | do Mb, Ra, Rb, ftl(Fs) ]
if fhd(Fs) and run Ma .
*** process B sends a request
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ a | do Ma | init (hd Rb) Mb , Ra, tl(Rb), ftl(Fs) ]
if not fhd(Fs) and hd(Rb) > 0 and idle Mb .
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ F | do Ma | Mb, Ra, tl(Rb), ftl(Fs) ]
if not fhd(Fs) and eq(hd(Rb), 0) and idle Mb .
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ F | do Ma | begin Mb, Ra, Rb, ftl(Fs) ]
if not fhd(Fs) and wait Mb and (eq(F, b) or not busy Ma ) .
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ F | do Ma | Mb, Ra, Rb, ftl(Fs) ]
if not fhd(Fs) and wait Mb and eq(F, a) and busy Ma .
eq tl [ F | Ma | Mb , Ra, Rb, Fs ] =
[ F | do Ma | do Mb, Ra, Rb, ftl(Fs) ]
if not fhd(Fs) and run Mb .
end
***> here begins the proof ***
dth PROOF is pr STREAM[BOOL] * (sort Stream to BStream) + PETERSON .
op sys_ : Trace -> BStream .
op good_ : SysState -> Bool .
op all-true : -> BStream .
var Tr : Trace . var F : Flag . vars Ma Mb : MState .
eq hd sys Tr = good (hd Tr) .
eq tl sys Tr = sys tl Tr .
eq good ( F | Ma | Mb ) =
not (run Ma and run Mb ) and
(run Ma implies (busy Ma and (eq(F, a) or not busy Mb))) and
(run Mb implies (busy Mb and (eq(F, b) or not busy Ma))) and
(not busy Ma implies ((not run Ma) and eq(count Ma, 0))) and
(not busy Mb implies ((not run Mb) and eq(count Mb, 0))) .
eq hd all-true = true .
eq tl all-true = all-true .
end
cobasis COB from PROOF is
op hd : BStream -> Bool .
op tl : BStream -> BStream .
end
cases C1 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq F = a .
case eq F = b .
end
cases C2 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq Ba = true .
case eq Ba = false .
end
cases C3 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq Bb = true .
case eq Bb = false .
end
cases C4 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq Da = true .
case eq Da = false .
end
cases C5 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq Db = true .
case eq Db = false .
end
cases C6 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq M = 0 .
case eq M > 0 = true .
end
cases C7 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq N = 0 .
case eq N > 0 = true .
end
cases C8 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq hd(Ra) = 0 .
case eq hd(Ra) > 0 = true .
end
cases C9 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq hd(Rb) = 0 .
case eq hd(Rb) > 0 = true .
end
cases C10 for PROOF is
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
context [ F | | , Ra, Rb, Fs ] .
case eq fhd(Fs) = true .
case eq fhd(Fs) = false .
end
***> mutual exclusion property
set cred trace on .
open PROOF .
use C1 * C2 * C3 * C4 * C5 * C6 * C7 * C8 * C9 * C10 .
var F : Flag . vars M N : Nat . vars Ba Bb Da Db : Bool .
vars Ra Rb : Request . var Fs : FairStream .
set cobasis COB .
cred sys [ F | | , Ra, Rb, Fs ] == all-true
if good (F | | ) .
close
*** *************************************************************
*** Liveness is not yet done
*** *************************************************************
awk% bobj
\|||||||||||||||||/
--- Welcome to BOBJ ---
/|||||||||||||||||\
BOBJ version 0.9.197 built: Tue Nov 5 12:12:21 PST 2002
University of California, San Diego
Wed Nov 06 10:49:14 PST 2002
BOBJ> in pete
==========================================
bth STREAM
==========================================
***> fair boolean stream (no infinite consecutive true or false)
==========================================
bth FAIR-STREAM
==========================================
dth MACHINE
Warning: redefining module MACHINE
==========================================
dth SYSTEM-STATE
Warning: redefining module SYSTEM-STATE
==========================================
bth PETERSON
==========================================
***> here begins the proof ***
==========================================
dth PROOF
==========================================
cases C1
==========================================
cases C2
==========================================
cases C3
==========================================
cases C4
==========================================
cases C5
==========================================
cases C6
==========================================
cases C7
==========================================
cases C8
==========================================
cases C9
==========================================
cases C10
==========================================
***> mutual exclusion property
==========================================
open PROOF
==========================================
use C1 * C2 * C3 * C4 * C5 * C6 * C7 * C8 * C9 * C10
==========================================
var F : Flag
==========================================
vars M N : Nat
==========================================
vars Ba Bb Da Db : Bool
==========================================
vars Ra Rb : Request
==========================================
var Fs : FairStream
==========================================
set cobasis COB
==========================================
c-reduce in PROOF : sys ([(F | (< Ba , Da , M >) | (< Bb , Db , N >))
, Ra , Rb , Fs]) == all-true if good (F | (< Ba , Da , M >) | (<
Bb , Db , N >))
using cobasis COB for PROOF
-------------------------------------------
case analysis by C1 * C2 * C3 * C4 * C5 * C6 * C7 * C8 * C9 * C10
-------------------------------------------
introduce constant(s):
r for the variable Ra
f1 for the variable Fs
r1 for the variable Rb
-------------------------------
case (1,1,1,1,1,1,1,1,1,1) :
assume: f = a
ba = true
bb = true
da = true
db = true
m = 0
n = 0
hd r = 0
hd r1 = 0
fhd f1 = true
the condition is false: good (f | (< ba , da , m >) | (< bb ,
db , n >))
-------------------------------
case (1,1,1,1,1,1,1,1,1,2) :
assume: f = a
ba = true
bb = true
da = true
db = true
m = 0
n = 0
hd r = 0
hd r1 = 0
fhd f1 = false
the condition is false: good (f | (< ba , da , m >) | (< bb ,
db , n >))
-------------------------------
case (1,1,1,1,1,1,1,1,2,1) :
assume: f = a
ba = true
bb = true
da = true
db = true
m = 0
n = 0
hd r = 0
(hd r1) > 0 = true
fhd f1 = true
the condition is false: good (f | (< ba , da , m >) | (< bb ,
db , n >))
-------------------------------
case (1,1,1,1,1,1,1,1,2,2) :
assume: f = a
ba = true
bb = true
da = true
db = true
m = 0
n = 0
hd r = 0
(hd r1) > 0 = true
fhd f1 = false
the condition is false: good (f | (< ba , da , m >) | (< bb ,
db , n >))
-------------------------------
..............................
-------------------------------
case (2,2,2,2,2,2,2,2,2,1) :
assume: f = b
ba = false
bb = false
da = false
db = false
m > 0 = true
n > 0 = true
(hd r) > 0 = true
(hd r1) > 0 = true
fhd f1 = true
eq(m, 0) = true
eq(n, 0) = true
reduce: sys (tl ([(f | (< ba , da , m >) | (< bb , db , n >)) , r ,
r1 , f1])) == all-true
nf: sys ([(b | (< true , false , (hd r) >) | (< false , false
, n >)) , (tl r) , r1 , (tl f1)]) == all-true
-------------------------------
deduce to : all-true == all-true
reduce: sys (tl ([(f | (< ba , da , m >) | (< bb , db , n >)) , r ,
r1 , f1])) == all-true
nf: true
-------------------------------
case (2,2,2,2,2,2,2,2,2,2) :
assume: f = b
ba = false
bb = false
da = false
db = false
m > 0 = true
n > 0 = true
(hd r) > 0 = true
(hd r1) > 0 = true
fhd f1 = false
eq(m, 0) = true
eq(n, 0) = true
reduce: sys (tl ([(f | (< ba , da , m >) | (< bb , db , n >)) , r ,
r1 , f1])) == all-true
nf: sys ([(a | (< false , false , m >) | (< true , false ,
(hd r1) >)) , r , (tl r1) , (ftl f1)]) == all-true
-------------------------------
deduce to : all-true == all-true
reduce: sys (tl ([(f | (< ba , da , m >) | (< bb , db , n >)) , r ,
r1 , f1])) == all-true
nf: true
-----------------------------------------
analyzed 1024 cases, all cases succeeded
condition failed in 576 cases
result: true
c-rewrite time: 264391ms parse time: 96ms
==========================================
close
BOBJ> q
Bye.
awk%
To the BOBJ Examples homepage
To Tatami project homepage
Maintained by Joseph Goguen
Last modified: Thu Dec 5 12:22:49 PST 2002