Concurrency “进度”标签的正确使用

Concurrency “进度”标签的正确使用,concurrency,formal-verification,model-checking,promela,spin,Concurrency,Formal Verification,Model Checking,Promela,Spin,根据, 进度标签用于定义正确性声明。进度标签说明了在任何无限系统执行中必须无限频繁地访问标记的全局状态的要求。任何违反此要求的情况都可以由核查人员作为非进度周期报告 及 自旋有一个特殊的模式来证明不存在非进展循环。它通过预定义的LTL公式实现: (<>[] np_) 在我的理解中,assert应该保持,但验证失败,因为初始化+++只执行一次,而progress标签声称应该可以经常任意执行它 然而,即使使用上述LTL公式,这在ispin中也可以验证(见下文) 如何正确测试语句是否可以

根据,

进度标签用于定义正确性声明。进度标签说明了在任何无限系统执行中必须无限频繁地访问标记的全局状态的要求。任何违反此要求的情况都可以由核查人员作为非进度周期报告

自旋有一个特殊的模式来证明不存在非进展循环。它通过预定义的LTL公式实现:

(<>[] np_)
在我的理解中,
assert
应该保持,但验证失败,因为
初始化+++
只执行一次,而
progress
标签声称应该可以经常任意执行它

然而,即使使用上述LTL公式,这在ispin中也可以验证(见下文)

如何正确测试语句是否可以经常任意执行(例如,对于锁定方案)

(Spin版本6.4.7——2017年8月19日)

完整状态空间搜索:

never claim           + (:np_:)
assertion violations  + (if within scope of claim)
non-progress cycles   + (fairness disabled)
invalid end states    - (disabled by never claim)
状态向量28字节,深度达到7,错误:0

   6 states, stored (8 visited)
   3 states, matched
   11 transitions (= visited+matched)
   0 atomic steps
哈希冲突:0(已解决)

内存使用情况统计数据(以兆字节为单位):

在init中未实现

   (0 of 3 states)
平移:经过时间0.001秒

没有发现错误--您是否验证了所有索赔

更新

还是不知道怎么用这个

bool initialised = 0;

init{
    initialised = 1;
}

active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
    assert(true);
od
}

active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else -> 
    (initialised == 0)
progress_writer:
    assert(true);
od
}
让我们选择非进度周期的测试。然后ispin将其作为

spin -a  test.pml
gcc -DMEMLIM=1024 -O2 -DXUSAFE -DNP -DNOCLAIM -w -o pan pan.c
./pan -m10000  -l
它可以无误地进行验证

所以让我们用ltl属性试试这个

/*pid: 0 = init, 1-2 = reader, 3-4 =  writer*/

ltl progress_reader1{ []<> reader[1]@progress_reader }
ltl progress_reader2{ []<> reader[2]@progress_reader }
ltl progress_writer1{ []<> writer[3]@progress_writer }
ltl progress_writer2{ []<> writer[4]@progress_writer }

bool initialised = 0;



init{
    initialised = 1;
}

active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
    assert(true);
od
}

active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else -> 
    (initialised == 0)
progress_writer:
    assert(true);
od
}
好吧,我不在乎,我只是想让它最终运行,所以让我们继续保持
progress\u writer1
并担心以后如何将其缝合在一起:

/*pid: 0 = init, 1-2 = reader, 3-4 =  writer*/
/*ltl progress_reader1{ []<> reader[1]@progress_reader }*/
/*ltl progress_reader2{ []<> reader[2]@progress_reader }*/
ltl progress_writer1{ []<> writer[3]@progress_writer }
/*ltl progress_writer2{ []<> writer[4]@progress_writer }*/
bool initialised = 0;
init{
    initialised = 1;
}
active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
    assert(true);
od
}
active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else -> 
    (initialised == 0)
progress_writer:
    assert(true);
od
}
是吗?壮观的我完全不知道该怎么办


如何让它运行?

您的代码示例的问题是它没有任何无限系统执行

进度标签用于定义正确性声明。进步 label规定了标记的全局状态必须为 在任何无限系统执行中经常无限访问。任何 验证人可将违反此要求的情况作为 非进度周期


请尝试以下示例:

short val = 0;

init {
    do
        :: val == 0 ->
           val = 1;
           // ...
           val = 0;

        :: else ->
progress:
           // super-important progress state
           printf("progress-state\n");
           assert(val != 0);
    od;
};
正常检查未发现任何错误:

~$ spin -search test.pml 

(Spin Version 6.4.3 -- 16 December 2014)
    + Partial Order Reduction

Full statespace search for:
    never claim             - (none specified)
    assertion violations    +
    cycle checks            - (disabled by -DSAFETY)
    invalid end states      +

State-vector 12 byte, depth reached 2, errors: 0
        3 states, stored
        1 states, matched
        4 transitions (= stored+matched)
        0 atomic steps
hash conflicts:         0 (resolved)

Stats on memory usage (in Megabytes):
    0.000   equivalent memory usage for states (stored*(State-vector + overhead))
    0.292   actual memory usage for states
  128.000   memory used for hash table (-w24)
    0.534   memory used for DFS stack (-m10000)
  128.730   total actual memory usage


unreached in init
    test.pml:12, state 5, "printf('progress-state\n')"
    test.pml:13, state 6, "assert((val!=0))"
    test.pml:15, state 10, "-end-"
    (3 of 10 states)

pan: elapsed time 0 seconds
然而,检查进度会产生错误:

~$ spin -search -l test.pml 

pan:1: non-progress cycle (at depth 2)
pan: wrote test.pml.trail

(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
    + Partial Order Reduction

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

State-vector 20 byte, depth reached 7, errors: 1
        4 states, stored
        0 states, matched
        4 transitions (= stored+matched)
        0 atomic steps
hash conflicts:         0 (resolved)

Stats on memory usage (in Megabytes):
    0.000   equivalent memory usage for states (stored*(State-vector + overhead))
    0.292   actual memory usage for states
  128.000   memory used for hash table (-w24)
    0.534   memory used for DFS stack (-m10000)
  128.730   total actual memory usage



pan: elapsed time 0 seconds

警告:确保在选项
-search
之后写入
-l
,否则不会将其移交给验证器


你问:

如何正确测试语句是否可以经常任意执行(例如,对于锁定方案)

只需编写一个活动属性:

ltl prop { [] <> proc[0]@label };
ltl prop{[]proc[0]@label};
这检查名为
proc
和pid
0
的进程是否经常无限执行与
标签

对应的语句,因为您的编辑实质上改变了问题,所以我编写了一个新的答案以避免混淆。这个答案只针对新内容。下一次,请考虑创建一个新的、独立的问题。p>
在这种情况下,注意…中未获取的
警告消息非常重要,因为它会影响验证过程的结果

警告信息:

与编译过程中创建的文件
\u spin\u nvr.tmp
的内容相关:

...
never progress_writer1 {    /* !([] (<> ((writer[3]@progress_writer)))) */
T0_init:
    do
    :: (! (((writer[3]@progress_writer)))) -> goto accept_S4    // state 5
    :: (1) -> goto T0_init
    od;
accept_S4:
    do
    :: (! (((writer[3]@progress_writer)))) -> goto accept_S4    // state 10
    od;
}                                                               // state 13 '-end-'
...
在第
2:
行,检查
初始化==1
。此语句强制
writer
2:
行阻塞,直到
initialized
设置为
1
。幸运的是,这是通过
init
过程完成的

在第
5:
行,检查
初始化==0
。此语句强制
writer
5:
行阻塞,直到
initialized
设置为
0
。但是,没有任何进程将
初始化设置为
0
。因此,标有
progress\u writer:
的代码行实际上是不可访问的

见:

条件语句只有在其有效时才能执行(传递)。[……]


谢谢,但我恐怕还是不知道如何“简单地编写一个活动属性”(见上面的编辑)。你认为你能帮我吗?@User1291你可能想快速阅读一下。但是当我删除
(初始化==0)
时,我也会得到
未读的
语句。@User1291当我删除
(初始化==0)
Spin 6.4.3
时,我会得到
错误:1
。确保您拥有最新版本的
Spin
,然后执行
~$Spin-search-a-ltl progress\u writer1 file\u name.pml
。是的,最终得到了错误(必须切换到“验收周期”测试,在ispin中…但我不知道如何操作。删除
初始化==0
后,写入程序与读取器相同,处于
状态(true)
循环,只执行
assert(true)
。我看不出它“最终总是执行
assert(true)”的说法
可能是错误的。@User1291这是因为在不公平的执行中,调度程序可以在某个点上选择只执行
\u pid
等于
1
2
4
的进程,从而防止
编写器到达
进程:
应该在属性中添加一些公平性约束,以确保每个进程都有机会无限频繁地执行。如果在只有一个
writer
实例而没有
reader
实例的情况下尝试相同的属性,则该属性成立。我必须承认,我没有想到spin会如此烦人,以至于假设一个非阻塞的p进程可能会因为没有被调度而饿死。我是说,说真的,如果调度程序没有被调度,谁会关心它呢
unreached in claim progress_writer1
    _spin_nvr.tmp:3, state 5, "(!((writer[3]._p==progress_writer)))"
    _spin_nvr.tmp:3, state 5, "(1)"
    _spin_nvr.tmp:8, state 10, "(!((writer[3]._p==progress_writer)))"
    _spin_nvr.tmp:10, state 13, "-end-"
    (3 of 13 states)    
short val = 0;

init {
    do
        :: val == 0 ->
           val = 1;
           // ...
           val = 0;

        :: else ->
progress:
           // super-important progress state
           printf("progress-state\n");
           assert(val != 0);
    od;
};
~$ spin -search test.pml 

(Spin Version 6.4.3 -- 16 December 2014)
    + Partial Order Reduction

Full statespace search for:
    never claim             - (none specified)
    assertion violations    +
    cycle checks            - (disabled by -DSAFETY)
    invalid end states      +

State-vector 12 byte, depth reached 2, errors: 0
        3 states, stored
        1 states, matched
        4 transitions (= stored+matched)
        0 atomic steps
hash conflicts:         0 (resolved)

Stats on memory usage (in Megabytes):
    0.000   equivalent memory usage for states (stored*(State-vector + overhead))
    0.292   actual memory usage for states
  128.000   memory used for hash table (-w24)
    0.534   memory used for DFS stack (-m10000)
  128.730   total actual memory usage


unreached in init
    test.pml:12, state 5, "printf('progress-state\n')"
    test.pml:13, state 6, "assert((val!=0))"
    test.pml:15, state 10, "-end-"
    (3 of 10 states)

pan: elapsed time 0 seconds
~$ spin -search -l test.pml 

pan:1: non-progress cycle (at depth 2)
pan: wrote test.pml.trail

(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
    + Partial Order Reduction

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

State-vector 20 byte, depth reached 7, errors: 1
        4 states, stored
        0 states, matched
        4 transitions (= stored+matched)
        0 atomic steps
hash conflicts:         0 (resolved)

Stats on memory usage (in Megabytes):
    0.000   equivalent memory usage for states (stored*(State-vector + overhead))
    0.292   actual memory usage for states
  128.000   memory used for hash table (-w24)
    0.534   memory used for DFS stack (-m10000)
  128.730   total actual memory usage



pan: elapsed time 0 seconds
ltl prop { [] <> proc[0]@label };
unreached in claim progress_writer1
    _spin_nvr.tmp:3, state 5, "(!((writer[3]._p==progress_writer)))"
    _spin_nvr.tmp:3, state 5, "(1)"
    _spin_nvr.tmp:8, state 10, "(!((writer[3]._p==progress_writer)))"
    _spin_nvr.tmp:10, state 13, "-end-"
    (3 of 13 states)   
...
never progress_writer1 {    /* !([] (<> ((writer[3]@progress_writer)))) */
T0_init:
    do
    :: (! (((writer[3]@progress_writer)))) -> goto accept_S4    // state 5
    :: (1) -> goto T0_init
    od;
accept_S4:
    do
    :: (! (((writer[3]@progress_writer)))) -> goto accept_S4    // state 10
    od;
}                                                               // state 13 '-end-'
...
   active [2] proctype writer()
   {
1:     assert(_pid >= 1);
2:     (initialised == 1)
3:     do
4:         :: else ->
5:             (initialised == 0);
6: progress_writer:
7:             assert(true);
8:     od
   }
(1)       /* always executable               */
(0)       /* never executable                */
skip      /* always executable, same as (1)  */
true      /* always executable, same as skip */
false     /* always blocks, same as (0)      */
a == b    /* executable only when a equals b */