+++ /dev/null
-# To unbundle, sh this file
-echo ex.readme 1>&2
-sed 's/.//' >ex.readme <<'//GO.SYSIN DD ex.readme'
--The 12 files in this bundle are the PROMELA
--files of all exercises and examples discussed
--in the document Doc/Exercises.ps from the
--SPIN distribution.
-//GO.SYSIN DD ex.readme
-echo ex.1a 1>&2
-sed 's/.//' >ex.1a <<'//GO.SYSIN DD ex.1a'
--init {
-- byte i = 0;
-- do
-- :: i = i+1
-- od
--}
-//GO.SYSIN DD ex.1a
-echo ex.1b 1>&2
-sed 's/.//' >ex.1b <<'//GO.SYSIN DD ex.1b'
--init {
-- chan dummy = [20] of { byte };
-- do
-- :: dummy!85
-- :: dummy!170
-- od
--}
-//GO.SYSIN DD ex.1b
-echo ex.1c 1>&2
-sed 's/.//' >ex.1c <<'//GO.SYSIN DD ex.1c'
--#define N 26
--
--int a;
--byte b;
--
--init {
-- do
-- :: atomic { (b < N) ->
-- if
-- :: a = a + (1<<b)
-- :: skip
-- fi;
-- b=b+1 }
-- od
--}
-//GO.SYSIN DD ex.1c
-echo ex.2 1>&2
-sed 's/.//' >ex.2 <<'//GO.SYSIN DD ex.2'
--#define MAX 8
--proctype A(chan in, out)
--{ byte mt; /* message data */
-- bit vr;
--S1: mt = (mt+1)%MAX;
-- out!mt,1;
-- goto S2;
--S2: in?vr;
-- if
-- :: (vr == 1) -> goto S1
-- :: (vr == 0) -> goto S3
-- :: printf("AERROR1\n") -> goto S5
-- fi;
--S3: out!mt,1;
-- goto S4;
--S4: in?vr;
-- if
-- :: goto S1
-- :: printf("AERROR2\n"); goto S5
-- fi;
--S5: out!mt,0;
-- goto S4
--}
--proctype B(chan in, out)
--{ byte mr, lmr;
-- bit ar;
-- goto S2; /* initial state */
--S1: assert(mr == (lmr+1)%MAX);
-- lmr = mr;
-- out!1;
-- goto S2;
--S2: in?mr,ar;
-- if
-- :: (ar == 1) -> goto S1
-- :: (ar == 0) -> goto S3
-- :: printf("ERROR1\n"); goto S5
-- fi;
--S3: out!1;
-- goto S2;
--S4: in?mr,ar;
-- if
-- :: goto S1
-- :: printf("ERROR2\n"); goto S5
-- fi;
--S5: out!0;
-- goto S4
--}
--init {
-- chan a2b = [2] of { bit };
-- chan b2a = [2] of { byte, bit };
-- atomic {
-- run A(a2b, b2a);
-- run B(b2a, a2b)
-- }
--}
-//GO.SYSIN DD ex.2
-echo ex.3 1>&2
-sed 's/.//' >ex.3 <<'//GO.SYSIN DD ex.3'
--mtype = { a, b, c, d, e, i, l, m, n, q, r, u, v };
--
--chan dce = [0] of { mtype };
--chan dte = [0] of { mtype };
--
--active proctype dte_proc()
--{
--state01:
-- do
-- :: dce!b -> /* state21 */ dce!a
-- :: dce!i -> /* state14 */
-- if
-- :: dte?m -> goto state19
-- :: dce!a
-- fi
-- :: dte?m -> goto state18
-- :: dte?u -> goto state08
-- :: dce!d -> break
-- od;
--
-- /* state02: */
-- if
-- :: dte?v
-- :: dte?u -> goto state15
-- :: dte?m -> goto state19
-- fi;
--state03:
-- dce!e;
-- /* state04: */
-- if
-- :: dte?m -> goto state19
-- :: dce!c
-- fi;
-- /* state05: */
-- if
-- :: dte?m -> goto state19
-- :: dte?r
-- fi;
-- /* state6A: */
-- if
-- :: dte?m -> goto state19
-- :: dte?q
-- fi;
--state07:
-- if
-- :: dte?m -> goto state19
-- :: dte?r
-- fi;
-- /* state6B: */
-- if /* non-deterministic select */
-- :: dte?q -> goto state07
-- :: dte?q
-- :: dte?m -> goto state19
-- fi;
-- /* state10: */
-- if
-- :: dte?m -> goto state19
-- :: dte?r
-- fi;
--state6C:
-- if
-- :: dte?m -> goto state19
-- :: dte?l
-- fi;
-- /* state11: */
-- if
-- :: dte?m -> goto state19
-- :: dte?n
-- fi;
-- /* state12: */
-- if
-- :: dte?m -> goto state19
-- :: dce!b -> goto state16
-- fi;
--
--state15:
-- if
-- :: dte?v -> goto state03
-- :: dte?m -> goto state19
-- fi;
--state08:
-- if
-- :: dce!c
-- :: dce!d -> goto state15
-- :: dte?m -> goto state19
-- fi;
-- /* state09: */
-- if
-- :: dte?m -> goto state19
-- :: dte?q
-- fi;
-- /* state10B: */
-- if
-- :: dte?r -> goto state6C
-- :: dte?m -> goto state19
-- fi;
--state18:
-- if
-- :: dte?l -> goto state01
-- :: dte?m -> goto state19
-- fi;
--state16:
-- dte?m;
-- /* state17: */
-- dte?l;
-- /* state21: */
-- dce!a; goto state01;
--state19:
-- dce!b;
-- /* state20: */
-- dte?l;
-- /* state21: */
-- dce!a; goto state01
--}
--
--active proctype dce_proc()
--{
--state01:
-- do
-- :: dce?b -> /* state21 */ dce?a
-- :: dce?i -> /* state14 */
-- if
-- :: dce?b -> goto state16
-- :: dce?a
-- fi
-- :: dte!m -> goto state18
-- :: dte!u -> goto state08
-- :: dce?d -> break
-- od;
--
-- /* state02: */
-- if
-- :: dte!v
-- :: dte!u -> goto state15
-- :: dce?b -> goto state16
-- fi;
--state03:
-- dce?e;
-- /* state04: */
-- if
-- :: dce?b -> goto state16
-- :: dce?c
-- fi;
-- /* state05: */
-- if
-- :: dce?b -> goto state16
-- :: dte!r
-- fi;
-- /* state6A: */
-- if
-- :: dce?b -> goto state16
-- :: dte!q
-- fi;
--state07:
-- if
-- :: dce?b -> goto state16
-- :: dte!r
-- fi;
-- /* state6B: */
-- if /* non-deterministic select */
-- :: dte!q -> goto state07
-- :: dte!q
-- :: dce?b -> goto state16
-- fi;
-- /* state10: */
-- if
-- :: dce?b -> goto state16
-- :: dte!r
-- fi;
--state6C:
-- if
-- :: dce?b -> goto state16
-- :: dte!l
-- fi;
-- /* state11: */
-- if
-- :: dce?b -> goto state16
-- :: dte!n
-- fi;
-- /* state12: */
-- if
-- :: dce?b -> goto state16
-- :: dte!m -> goto state19
-- fi;
--
--state15:
-- if
-- :: dte!v -> goto state03
-- :: dce?b -> goto state16
-- fi;
--state08:
-- if
-- :: dce?c
-- :: dce?d -> goto state15
-- :: dce?b -> goto state16
-- fi;
-- /* state09: */
-- if
-- :: dce?b -> goto state16
-- :: dte!q
-- fi;
-- /* state10B: */
-- if
-- :: dte!r -> goto state6C
-- :: dce?b -> goto state16
-- fi;
--state18:
-- if
-- :: dte!l -> goto state01
-- :: dce?b -> goto state16
-- fi;
--state16:
-- dte!m;
-- /* state17: */
-- dte!l;
-- /* state21: */
-- dce?a; goto state01;
--state19:
-- dce?b;
-- /* state20: */
-- dte!l;
-- /* state21: */
-- dce?a; goto state01
--}
-//GO.SYSIN DD ex.3
-echo ex.4b 1>&2
-sed 's/.//' >ex.4b <<'//GO.SYSIN DD ex.4b'
--#define true 1
--#define false 0
--
--bool flag[2];
--bool turn;
--
--active [2] proctype user()
--{ flag[_pid] = true;
-- turn = _pid;
-- (flag[1-_pid] == false || turn == 1-_pid);
--crit: skip; /* critical section */
-- flag[_pid] = false
--}
-//GO.SYSIN DD ex.4b
-echo ex.4c 1>&2
-sed 's/.//' >ex.4c <<'//GO.SYSIN DD ex.4c'
--byte in;
--byte x, y, z;
--active [2] proctype user() /* file ex.4c */
--{ byte me = _pid+1; /* me is 1 or 2 */
--L1: x = me;
--L2: if
-- :: (y != 0 && y != me) -> goto L1 /* try again */
-- :: (y == 0 || y == me)
-- fi;
--L3: z = me;
--L4: if
-- :: (x != me) -> goto L1 /* try again */
-- :: (x == me)
-- fi;
--L5: y = me;
--L6: if
-- :: (z != me) -> goto L1 /* try again */
-- :: (z == me)
-- fi;
--L7: /* success */
-- in = in+1;
-- assert(in == 1);
-- in = in - 1;
-- goto L1
--}
-//GO.SYSIN DD ex.4c
-echo ex.5a 1>&2
-sed 's/.//' >ex.5a <<'//GO.SYSIN DD ex.5a'
--#define Place byte /* assume < 256 tokens per place */
--
--Place p1, p2, p3;
--Place p4, p5, p6;
--#define inp1(x) (x>0) -> x=x-1
--#define inp2(x,y) (x>0&&y>0) -> x = x-1; y=y-1
--#define out1(x) x=x+1
--#define out2(x,y) x=x+1; y=y+1
--init
--{ p1 = 1; p4 = 1; /* initial marking */
-- do
--/*t1*/ :: atomic { inp1(p1) -> out1(p2) }
--/*t2*/ :: atomic { inp2(p2,p4) -> out1(p3) }
--/*t3*/ :: atomic { inp1(p3) -> out2(p1,p4) }
--/*t4*/ :: atomic { inp1(p4) -> out1(p5) }
--/*t5*/ :: atomic { inp2(p1,p5) -> out1(p6) }
--/*t6*/ :: atomic { inp1(p6) -> out2(p4,p1) }
-- od
--}
-//GO.SYSIN DD ex.5a
-echo ex.5b 1>&2
-sed 's/.//' >ex.5b <<'//GO.SYSIN DD ex.5b'
--#define Place byte /* assume < 256 tokens per place */
--
--Place P1, P2, P4, P5, RC, CC, RD, CD;
--Place p1, p2, p4, p5, rc, cc, rd, cd;
--
--#define inp1(x) (x>0) -> x=x-1
--#define inp2(x,y) (x>0&&y>0) -> x = x-1; y=y-1
--#define out1(x) x=x+1
--#define out2(x,y) x=x+1; y=y+1
--
--init /* file ex.5b */
--{ P1 = 1; p1 = 1; /* initial marking */
-- do
-- :: atomic { inp1(P1) -> out2(rc,P2) } /* DC */
-- :: atomic { inp2(P2,CC) -> out1(P4) } /* CA */
-- :: atomic { inp1(P4) -> out2(P5,rd) } /* DD */
-- :: atomic { inp2(P5,CD) -> out1(P1) } /* FD */
-- :: atomic { inp2(P1,RC) -> out2(P4,cc) } /* AC */
-- :: atomic { inp2(P4,RD) -> out2(P1,cd) } /* AD */
-- :: atomic { inp2(P5,RD) -> out1(P1) } /* DA */
--
-- :: atomic { inp1(p1) -> out2(RC,p2) } /* dc */
-- :: atomic { inp2(p2,cc) -> out1(p4) } /* ca */
-- :: atomic { inp1(p4) -> out2(p5,RD) } /* dd */
-- :: atomic { inp2(p5,cd) -> out1(p1) } /* fd */
-- :: atomic { inp2(p1,rc) -> out2(p4,CC) } /* ac */
-- :: atomic { inp2(p4,rd) -> out2(p1,CD) } /* ad */
-- :: atomic { inp2(p5,rd) -> out1(p1) } /* da */
-- od
--}
-//GO.SYSIN DD ex.5b
-echo ex.6 1>&2
-sed 's/.//' >ex.6 <<'//GO.SYSIN DD ex.6'
--#if 0
-- Cambridge Ring Protocol [Needham'82]
-- basic protocol - no LTL properties
--#endif
--
--#define LOSS 1
--#define RELAXED 1
--
--#if RELAXED==1
--#define stimeout empty(sender)
--#define rtimeout empty(recv)
--#else
--#define stimeout timeout
--#define rtimeout timeout
--#endif
--
--#define QSZ 6 /* length of message queues */
--
-- mtype = {
-- RDY, NOTRDY, DATA, NODATA, RESET
-- };
-- chan sender = [QSZ] of { mtype, byte };
-- chan recv = [QSZ] of { mtype, byte };
--
--active proctype Sender()
--{ short n = -1; byte t,m;
--
-- xr sender;
-- xs recv;
--
--I: /* Idle State */
-- do
--#if LOSS==1
-- :: sender?_,_ -> progress2: skip
--#endif
-- :: sender?RESET,0 ->
--ackreset: recv!RESET,0; /* stay in idle */
-- n = -1;
-- goto I
--
-- /* E-rep: protocol error */
--
-- :: sender?RDY,m -> /* E-exp */
-- assert(m == (n+1)%4);
--advance: n = (n+1)%4;
-- if
--/* buffer */ :: atomic {
-- printf("MSC: NEW\n");
-- recv!DATA,n;
-- goto E
-- }
--/* no buffer */ :: recv!NODATA,n;
-- goto N
-- fi
--
-- :: sender?NOTRDY,m -> /* N-exp */
--expected: assert(m == (n+1)%4);
-- goto I
--
-- /* Timeout */
-- /* ignored (p.154, in [Needham'82]) */
--
-- :: goto reset
--
-- od;
--
--E: /* Essential element sent, ack expected */
-- do
--#if LOSS==1
-- :: sender?_,_ -> progress0: skip
--#endif
-- :: sender?RESET,0 ->
-- goto ackreset
--
-- :: sender?RDY,m ->
-- if
-- :: (m == n) -> /* E-rep */
-- goto retrans
-- :: (m == (n+1)%4) -> /* E-exp */
-- goto advance
-- fi
--
-- :: sender?NOTRDY,m -> /* N-exp */
-- goto expected
--
-- /* Timeout */
-- :: stimeout ->
-- printf("MSC: STO\n");
--retrans: recv!DATA,n /* retransmit */
--
-- :: goto reset
--
-- od;
--
--
--N: /* Non-essential element sent */
-- do
--#if LOSS==1
-- :: sender?_,_ -> progress1: skip
--#endif
-- :: sender?RESET,0 ->
-- goto ackreset
--
-- :: sender?RDY,m -> /* E-rep */
-- assert(m == n) /* E-exp: protocol error */
-- -> recv!NODATA,n /* retransmit and stay in N */
--
-- :: recv!DATA,n; /* buffer ready event */
-- goto E
--
-- :: goto reset
--
-- /* Timeout */
-- /* ignored (p.154, in [Needham'82]) */
-- od;
--
--reset: recv!RESET,0;
-- do
--#if LOSS==1
-- :: sender?_,_ -> progress3: skip
--#endif
-- :: sender?t,m ->
-- if
-- :: t == RESET -> n = -1; goto I
-- :: else /* ignored, p. 152 */
-- fi
-- :: timeout -> /* a real timeout */
-- goto reset
-- od
--}
--
--active proctype Receiver()
--{ byte t, n, m, Nexp;
--
-- xr recv;
-- xs sender;
--
--I: /* Idle State */
-- do
--#if LOSS==1
-- :: recv?_,_ -> progress2: skip
--#endif
-- :: recv?RESET,0 ->
--ackreset: sender!RESET,0; /* stay in idle */
-- n = 0; Nexp = 0;
-- goto I
--
-- :: atomic { recv?DATA(m) -> /* E-exp */
-- assert(m == n);
--advance: printf("MSC: EXP\n");
-- n = (n+1)%4;
-- assert(m == Nexp);
-- Nexp = (m+1)%4;
-- if
-- :: sender!RDY,n; goto E
-- :: sender!NOTRDY,n; goto N
-- fi
-- }
--
-- :: recv?NODATA(m) -> /* N-exp */
-- assert(m == n)
--
-- /* Timeout: ignored */
--
-- /* only receiver can initiate transfer; p. 156 */
-- :: empty(recv) -> sender!RDY,n; goto E
--
-- :: goto reset
-- od;
--
--E:
-- do
--#if LOSS==1
-- :: recv?_,_ -> progress1: skip
--#endif
-- :: recv?RESET,0 ->
-- goto ackreset
--
-- :: atomic { recv?DATA(m) ->
-- if
-- :: ((m+1)%4 == n) -> /* E-rep */
-- printf("MSC: REP\n");
-- goto retrans
-- :: (m == n) -> /* E-exp */
-- goto advance
-- fi
-- }
--
-- :: recv?NODATA(m) -> /* N-exp */
-- assert(m == n);
-- goto I
--
-- :: rtimeout ->
-- printf("MSC: RTO\n");
--retrans: sender!RDY,n;
-- goto E
--
-- :: goto reset
--
-- od;
--
--N:
-- do
--#if LOSS==1
-- :: recv?_,_ -> progress0: skip
--#endif
-- :: recv?RESET,0 ->
-- goto ackreset
--
-- :: recv?DATA(m) -> /* E-rep */
-- assert((m+1)%4 == n); /* E-exp and N-exp: protocol error */
-- printf("MSC: REP\n");
-- sender!NOTRDY,n /* retransmit and stay in N */
--
-- :: sender!RDY,n -> /* buffer ready event */
-- goto E
--
-- /* Timeout: ignored */
--
-- :: goto reset
--
-- od;
--
--progress:
--reset: sender!RESET,0;
-- do
--#if LOSS==1
-- :: recv?_,_ -> progress3: skip
--#endif
-- :: recv?t,m ->
-- if
-- :: t == RESET -> n = 0; Nexp = 0; goto I
-- :: else /* ignored, p. 152 */
-- fi
-- :: timeout -> /* a real timeout */
-- goto reset
-- od
--}
-//GO.SYSIN DD ex.6
-echo ex.7 1>&2
-sed 's/.//' >ex.7 <<'//GO.SYSIN DD ex.7'
--mtype = { Wakeme, Running };
--
--bit lk, sleep_q;
--bit r_lock, r_want;
--mtype State = Running;
--
--active proctype client()
--{
--sleep: /* sleep routine */
-- atomic { (lk == 0) -> lk = 1 }; /* spinlock(&lk) */
-- do /* while r->lock */
-- :: (r_lock == 1) -> /* r->lock == 1 */
-- r_want = 1;
-- State = Wakeme;
-- lk = 0; /* freelock(&lk) */
-- (State == Running); /* wait for wakeup */
-- :: else -> /* r->lock == 0 */
-- break
-- od;
--progress:
-- assert(r_lock == 0); /* should still be true */
-- r_lock = 1; /* consumed resource */
-- lk = 0; /* freelock(&lk) */
-- goto sleep
--}
--
--active proctype server() /* interrupt routine */
--{
--wakeup: /* wakeup routine */
-- r_lock = 0; /* r->lock = 0 */
-- (lk == 0); /* waitlock(&lk) */
-- if
-- :: r_want -> /* someone is sleeping */
-- atomic { /* spinlock on sleep queue */
-- (sleep_q == 0) -> sleep_q = 1
-- };
-- r_want = 0;
--#ifdef PROPOSED_FIX
-- (lk == 0); /* waitlock(&lk) */
--#endif
-- if
-- :: (State == Wakeme) ->
-- State = Running;
-- :: else ->
-- fi;
-- sleep_q = 0
-- :: else ->
-- fi;
-- goto wakeup
--}
-//GO.SYSIN DD ex.7
-echo ex.8 1>&2
-sed 's/.//' >ex.8 <<'//GO.SYSIN DD ex.8'
--/* Dolev, Klawe & Rodeh for leader election in unidirectional ring
-- * `An O(n log n) unidirectional distributed algorithm for extrema
-- * finding in a circle,' J. of Algs, Vol 3. (1982), pp. 245-260
-- */
--
--#define elected (nr_leaders > 0)
--#define noLeader (nr_leaders == 0)
--#define oneLeader (nr_leaders == 1)
--
--/* properties:
-- * ![] noLeader
-- * <> elected
-- * <>[]oneLeader
-- * [] (noLeader U oneLeader)
-- */
--
--#define N 7 /* nr of processes (use 5 for demos) */
--#define I 3 /* node given the smallest number */
--#define L 14 /* size of buffer (>= 2*N) */
--
--mtype = { one, two, winner };
--chan q[N] = [L] of { mtype, byte};
--
--byte nr_leaders = 0;
--
--proctype node (chan in, out; byte mynumber)
--{ bit Active = 1, know_winner = 0;
-- byte nr, maximum = mynumber, neighbourR;
--
-- xr in;
-- xs out;
--
-- printf("MSC: %d\n", mynumber);
-- out!one(mynumber);
--end: do
-- :: in?one(nr) ->
-- if
-- :: Active ->
-- if
-- :: nr != maximum ->
-- out!two(nr);
-- neighbourR = nr
-- :: else ->
-- /* Raynal p.39: max is greatest number */
-- assert(nr == N);
-- know_winner = 1;
-- out!winner,nr;
-- fi
-- :: else ->
-- out!one(nr)
-- fi
--
-- :: in?two(nr) ->
-- if
-- :: Active ->
-- if
-- :: neighbourR > nr && neighbourR > maximum ->
-- maximum = neighbourR;
-- out!one(neighbourR)
-- :: else ->
-- Active = 0
-- fi
-- :: else ->
-- out!two(nr)
-- fi
-- :: in?winner,nr ->
-- if
-- :: nr != mynumber ->
-- printf("MSC: LOST\n");
-- :: else ->
-- printf("MSC: LEADER\n");
-- nr_leaders++;
-- assert(nr_leaders == 1)
-- fi;
-- if
-- :: know_winner
-- :: else -> out!winner,nr
-- fi;
-- break
-- od
--}
--
--init {
-- byte proc;
-- atomic {
-- proc = 1;
-- do
-- :: proc <= N ->
-- run node (q[proc-1], q[proc%N], (N+I-proc)%N+1);
-- proc++
-- :: proc > N ->
-- break
-- od
-- }
--}
--
--#if 0
--/* !(<>[]oneLeader) */
--
--never {
--T0:
-- if
-- :: skip -> goto T0
-- :: !oneLeader -> goto accept
-- fi;
--accept:
-- if
-- :: skip -> goto T0
-- fi
--}
--#endif
-//GO.SYSIN DD ex.8
-echo ex.9 1>&2
-sed 's/.//' >ex.9 <<'//GO.SYSIN DD ex.9'
--#define MaxSeq 3
--#define MaxSeq_plus_1 4
--#define inc(x) x = (x + 1) % (MaxSeq_plus_1)
--
--chan q[2] = [MaxSeq] of { byte, byte };
--
--active [2] proctype p5()
--{ byte NextFrame, AckExp, FrameExp,
-- r, s, nbuf, i;
-- chan in, out;
--
-- in = q[_pid];
-- out = q[1-_pid];
--
-- xr in;
-- xs out;
--
-- do
-- :: nbuf < MaxSeq ->
-- nbuf++;
-- out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq_plus_1);
-- inc(NextFrame)
-- :: in?r,s ->
-- if
-- :: r == FrameExp ->
-- inc(FrameExp)
-- :: else
-- fi;
-- do
-- :: ((AckExp <= s) && (s < NextFrame))
-- || ((AckExp <= s) && (NextFrame < AckExp))
-- || ((s < NextFrame) && (NextFrame < AckExp)) ->
-- nbuf--;
-- inc(AckExp)
-- :: else ->
-- break
-- od
-- :: timeout ->
-- NextFrame = AckExp;
-- i = 1;
-- do
-- :: i <= nbuf ->
-- out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq_plus_1);
-- inc(NextFrame);
-- i++
-- :: else ->
-- break
-- od
-- od
--}
-//GO.SYSIN DD ex.9
-echo ex.9b 1>&2
-sed 's/.//' >ex.9b <<'//GO.SYSIN DD ex.9b'
--#define MaxSeq 3
--#define MaxSeq_plus_1 4
--#define inc(x) x = (x + 1) % (MaxSeq + 1)
--
--chan q[2] = [MaxSeq] of { byte, byte };
--
--active [2] proctype p5()
--{ byte NextFrame, AckExp, FrameExp,
-- r, s, nbuf, i;
-- chan in, out;
--
-- d_step {
-- in = q[_pid];
-- out = q[1-_pid]
-- };
-- xr in;
-- xs out;
--
-- do
-- :: atomic { nbuf < MaxSeq ->
-- nbuf++;
-- out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
-- printf("MSC: nbuf: %d\n", nbuf);
-- inc(NextFrame)
-- }
-- :: atomic { in?r,s ->
-- if
-- :: r == FrameExp ->
-- printf("MSC: accept %d\n", r);
-- inc(FrameExp)
-- :: else
-- -> printf("MSC: reject\n")
-- fi
-- };
-- d_step {
-- do
-- :: ((AckExp <= s) && (s < NextFrame))
-- || ((AckExp <= s) && (NextFrame < AckExp))
-- || ((s < NextFrame) && (NextFrame < AckExp)) ->
-- nbuf--;
-- printf("MSC: nbuf: %d\n", nbuf);
-- inc(AckExp)
-- :: else ->
-- printf("MSC: %d %d %d\n", AckExp, s, NextFrame);
-- break
-- od; skip
-- }
-- :: timeout ->
-- d_step {
-- NextFrame = AckExp;
-- printf("MSC: timeout\n");
-- i = 1;
-- do
-- :: i <= nbuf ->
-- out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
-- inc(NextFrame);
-- i++
-- :: else ->
-- break
-- od; i = 0
-- }
-- od
--}
-//GO.SYSIN DD ex.9b
-echo ex.9c 1>&2
-sed 's/.//' >ex.9c <<'//GO.SYSIN DD ex.9c'
--#define MaxSeq 3
--#define MaxSeq_plus_1 4
--#define inc(x) x = (x + 1) % (MaxSeq + 1)
--
--#define CHECKIT
--
--#ifdef CHECKIT
-- mtype = { red, white, blue }; /* Wolper's test */
-- chan source = [0] of { mtype };
-- chan q[2] = [MaxSeq] of { mtype, byte, byte };
-- mtype rcvd = white;
-- mtype sent = white;
--#else
-- chan q[2] = [MaxSeq] of { byte, byte };
--#endif
--
--active [2] proctype p5()
--{ byte NextFrame, AckExp, FrameExp,
-- r, s, nbuf, i;
-- chan in, out;
--#ifdef CHECKIT
-- mtype ball;
-- byte frames[MaxSeq_plus_1];
--#endif
--
-- d_step {
-- in = q[_pid];
-- out = q[1-_pid]
-- };
--
-- xr in;
-- xs out;
--
-- do
-- :: atomic {
-- nbuf < MaxSeq ->
-- nbuf++;
--#ifdef CHECKIT
-- if
-- :: _pid%2 -> source?ball
-- :: else
-- fi;
-- frames[NextFrame] = ball;
-- out!ball, NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
-- if
-- :: _pid%2 -> sent = ball;
-- :: else
-- fi;
--#else
-- out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
--#endif
--#ifdef VERBOSE
-- printf("MSC: nbuf: %d\n", nbuf);
--#endif
-- inc(NextFrame)
-- }
--#ifdef CHECKIT
-- :: atomic { in?ball,r,s ->
--#else
-- :: atomic { in?r,s ->
--#endif
-- if
-- :: r == FrameExp ->
--#ifdef VERBOSE
-- printf("MSC: accept %d\n", r);
--#endif
--#ifdef CHECKIT
-- if
-- :: _pid%2
-- :: else -> rcvd = ball
-- fi;
--#endif
-- inc(FrameExp)
-- :: else
--#ifdef VERBOSE
-- -> printf("MSC: reject\n")
--#endif
-- fi
-- };
-- d_step {
-- do
-- :: ((AckExp <= s) && (s < NextFrame))
-- || ((AckExp <= s) && (NextFrame < AckExp))
-- || ((s < NextFrame) && (NextFrame < AckExp)) ->
-- nbuf--;
--#ifdef VERBOSE
-- printf("MSC: nbuf: %d\n", nbuf);
--#endif
-- inc(AckExp)
-- :: else ->
--#ifdef VERBOSE
-- printf("MSC: %d %d %d\n", AckExp, s, NextFrame);
--#endif
-- break
-- od;
-- skip
-- }
-- :: timeout ->
-- d_step {
-- NextFrame = AckExp;
--#ifdef VERBOSE
-- printf("MSC: timeout\n");
--#endif
-- i = 1;
-- do
-- :: i <= nbuf ->
--#ifdef CHECKIT
-- if
-- :: _pid%2 -> ball = frames[NextFrame]
-- :: else
-- fi;
-- out!ball, NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
--#else
-- out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
--#endif
-- inc(NextFrame);
-- i++
-- :: else ->
-- break
-- od;
-- i = 0
-- }
-- od
--}
--#ifdef CHECKIT
--active proctype Source()
--{
-- do
-- :: source!white
-- :: source!red -> break
-- od;
-- do
-- :: source!white
-- :: source!blue -> break
-- od;
--end: do
-- :: source!white
-- od
--}
--
--#define sw (sent == white)
--#define sr (sent == red)
--#define sb (sent == blue)
--
--#define rw (rcvd == white)
--#define rr (rcvd == red)
--#define rb (rcvd == blue)
--
--#define LTL 3
--#if LTL==1
--
--never { /* ![](sr -> <> rr) */
-- /* the never claim is generated by
-- spin -f "![](sr -> <> rr)"
-- and then edited a little for readability
-- the same is true for all others below
-- */
-- do
-- :: 1
-- :: !rr && sr -> goto accept
-- od;
--accept:
-- if
-- :: !rr -> goto accept
-- fi
--}
--
--#endif
--#if LTL==2
--
--never { /* !rr U rb */
-- do
-- :: !rr
-- :: rb -> break /* move to implicit 2nd state */
-- od
--}
--
--#endif
--#if LTL==3
--
--never { /* (![](sr -> <> rr)) || (!rr U rb) */
--
-- if
-- :: 1 -> goto T0_S5
-- :: !rr && sr -> goto accept_S8
-- :: !rr -> goto T0_S2
-- :: rb -> goto accept_all
-- fi;
--accept_S8:
-- if
-- :: !rr -> goto T0_S8
-- fi;
--T0_S2:
-- if
-- :: !rr -> goto T0_S2
-- :: rb -> goto accept_all
-- fi;
--T0_S8:
-- if
-- :: !rr -> goto accept_S8
-- fi;
--T0_S5:
-- if
-- :: 1 -> goto T0_S5
-- :: !rr && sr -> goto accept_S8
-- fi;
--accept_all:
-- skip
--}
--#endif
--
--#endif
-//GO.SYSIN DD ex.9c