使用远程 varrefs 时,自旋模型检查器未发现错误

Spin Model Checker does not find a bug when using remote varrefs

我正在尝试在以下Promela 模型 上正式验证互斥

/* Mutex with (bugged) Peterson algorithm */

bool flag[2];
int turn = -1;

active [2] proctype agent() {
    bool in_cs;
    int other = 1 - _pid;

    do
        :: true ->

            /* trying section */
            turn = other;
            flag[_pid] = true;
            !( flag[other] && (turn == other));

            /* critical section */
            in_cs = true;
            printf("Agent %d in CS\n", _pid);
            in_cs = false;

            /* exit section */
            flag[_pid] = false;
    od;
}

ltl mutex { [] ! (agent[0]:in_cs && agent[1]:in_cs) }

为了验证它,我使用以下命令链:

~$ spin -a test.pml ; gcc -o run pan.c -DNOREDUCE ; ./run -a -N p1

打印以下输出:

...
Full statespace search for:
    never claim             + (mutex)
    assertion violations    + (if within scope of claim)
    acceptance   cycles     + (fairness disabled)
    invalid end states      - (disabled by never claim)

State-vector 40 byte, depth reached 53, errors: 0
...

问: 我知道 Promela 模型 不满足 互斥,但 Spin 声称确实如此。为什么会这样?


注意: 我在使用 gcc 编译时添加了选项 -DNOREDUCE 因为 Spin 6.4.8 会打印一条警告消息,要求我这样做,如果我不要:

~$ spin -a test.pml ; gcc -o run pan.c ; ./run -a -N p1
...
pan.c: In function ‘main’:
pan.c:9478:3: warning: #warning p.o. reduction not compatible with remote varrefs (use -DNOREDUCE) [-Wcpp]
  #warning p.o. reduction not compatible with remote varrefs (use -DNOREDUCE)
   ^~~~~~~
...

解决方法如下:

The problem here is that to disable partial order reduction you not only have to compile with -DNOREDUCE but also generate the model while disabling statement merging (merging of subsequent local actions) -- which is also a partial order reduction strategy. So, for the second example you also get the counter-example if you do:

spin -o3 -a test.pml; gcc -DNOREDUCE -o pan pan.c; ./pan -a

[G. H., private communication]

建议解决方案的输出符合我们的预期:

~$ spin -o3 -a test.pml ; gcc -o run pan.c -DNOREDUCE ; ./run -a -N p1
...
pan:1: assertion violated  !( !( !((agent[0].in_cs&&agent[1].in_cs)))) (at depth 55)
pan: wrote test.pml.trail

...

Full statespace search for:
    never claim             + (mutex)
    assertion violations    + (if within scope of claim)
    acceptance   cycles     + (fairness disabled)
    invalid end states  - (disabled by never claim)

State-vector 40 byte, depth reached 69, errors: 1
...

或者,可以通过使用标签远程引用而不是变量远程引用来解决这个问题,例如:

/* Mutex with (bugged) Peterson algorithm */

bool flag[2];
int turn = -1;

active [2] proctype agent() {
    int other = 1 - _pid;

    do
        :: true ->

            /* trying section */
            turn = other;
            flag[_pid] = true;
            !( flag[other] && (turn == other));

            /* critical section */
cs:
            printf("Agent %d in CS\n", _pid);

            /* exit section */
            flag[_pid] = false;
    od;
}

ltl mutex { [] ! (agent[0]@cs && agent[1]@cs) }

有了这个模型,我们找到了一个反例,正如预期的那样:

~$ spin -search test.pml
...
pan:1: assertion violated  !( !( !(((agent[0]._p==cs)&&(agent[1]._p==cs))))) (at depth 28)
pan: wrote test.pml.trail
...