Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whats causing timeout in Promela/SPIN?

I have the following promela code:

chan level = [0] of {int};

proctype Sensor (chan levelChan) {
    int x;
    do
    :: true ->
            levelChan ? x;
            if 
            :: (x < 2) -> printf("low %d", x);
            :: (x > 8) -> printf("high %d", x);
            :: else -> printf("normal %d", x);
            fi
    od
}

init {
    run Sensor(level);  
    int lvl = 5;
    level ! lvl;
    lvl = 0;
    do 
    :: true ->
        level ! lvl; 
        lvl++;
        (lvl > 9) -> break;
    od
}

I am expecting to send level (0-9) information into a channel and have the sensor output low|normal|high depending on this level. Its quite simple. But why SPIN saying its timeout all the time?

  0:    proc  - (:root:) creates proc  0 (:init:)
Starting Sensor with pid 1
  1:    proc  0 (:init:) creates proc  1 (Sensor)
  1:    proc  0 (:init:) 1.pml:18 (state 1) [(run Sensor(level))]
  2:    proc  1 (Sensor) 1.pml:6 (state 11) [(1)]
  3:    proc  0 (:init:) 1.pml:20 (state 2) [lvl = 5]
  4:    proc  0 (:init:) 1.pml:20 (state 3) [level!lvl]
  4:    proc  1 (Sensor) 1.pml:8 (state 2)  [levelChan?x]
  5:    proc  1 (Sensor) 1.pml:9 (state 9)  [else]
  6:    proc  0 (:init:) 1.pml:21 (state 4) [lvl = 0]
normal 5  8:    proc  1 (Sensor) 1.pml:12 (state 8) [printf('normal %d',x)]
  9:    proc  0 (:init:) 1.pml:22 (state 10)    [(1)]
 12:    proc  1 (Sensor) 1.pml:6 (state 11) [(1)]
 13:    proc  0 (:init:) 1.pml:24 (state 6) [level!lvl]
 13:    proc  1 (Sensor) 1.pml:8 (state 2)  [levelChan?x]
 14:    proc  1 (Sensor) 1.pml:9 (state 9)  [((x<2))]
low 0 15:   proc  1 (Sensor) 1.pml:10 (state 4) [printf('low %d',x)]
 17:    proc  0 (:init:) 1.pml:25 (state 7) [lvl = (lvl+1)]
 19:    proc  1 (Sensor) 1.pml:6 (state 11) [(1)]
timeout
#processes: 2
 19:    proc  1 (Sensor) 1.pml:8 (state 2)
 19:    proc  0 (:init:) 1.pml:26 (state 8)
2 processes created

It seem to only do 1 iteration of the do loop why?

like image 584
Jiew Meng Avatar asked Nov 28 '25 05:11

Jiew Meng


1 Answers

The statements in the init process's do loop are run in sequence.

do 
:: true ->
    level ! lvl; 
    lvl++;
    (lvl > 9) -> break;
od

The very first time the do loop is run it will send lvl over the level channel, increase the lvl (so it is now 1) and then test (lvl > 9). This is false so will block and causes the timeout.

To have multiple options in a do loop you need :: to define the start of each option:

do
 :: true ->
    level ! lvl; 
    lvl++;
 :: (lvl > 9) -> break;
od

However this will still not perform as expected. When lvl is greater than 9 both options of the do loop are valid and either one can be chosen, so the loop will not necessarily break when lvl > 9 it could choose to continue to send the lvl over the level channel and increase lvl.

You need to have a condition on the first do option as well as the second:

do 
:: (lvl <= 9) ->
    level ! lvl; 
    lvl++;
:: (lvl > 9) -> break;
od

It might be nicer to use the for loop syntax for this example:

init {
  run Sensor(level);  
  int lvl = 5;
  level ! lvl;

  for (lvl : 0..9){
    level ! lvl; 
  }
}

Note that this example will still have a timeout error caused by Sensor's do loop, when the init process has finished Sensor will still try to read from the level channel and timeout.

like image 103
Crux Avatar answered Dec 01 '25 07:12

Crux



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!