什么是 promela 中的无条件自循环?

what is unconditional self loop in promela?

我正在从事一个涉及 SPIN 模型 checker.SPIN 版本 6.4.7 和 ispin 版本 1.1.4 的项目,我在 ispin 上收到此错误说

state 76: unconditional self loop

    proctype TDMAProtocol(byte id; chan P1, P2, PR)

54  { 

55       byte id_j, members_j, r_j;

56     do 

57        ::nodeState[id].r == id ->  
58           nodeState[id].r =  (nodeState[id].r + 1) % 4;

59  
60        atomic {  
61  //       printf("-- %d New round %d member %d cmembers %d\n" , id, nodeState[id].r,nodeState[id].members, nodeState[id].cmembers);

62        
63           nodeState[id].r =  (nodeState[id].r + 1) % 4;

64           nodeState[id].messageLost[0] = nodeState[id].messageLost[0]+1;

65           nodeState[id].messageLost[1] = nodeState[id].messageLost[1]+1;

66           nodeState[id].messageLost[2] = nodeState[id].messageLost[2]+1;

67           nodeState[id].messageLost[id] = 0;

68  //       nodeState[id].round = 1;
69       
70            // Send aloha
71            if    
72            ::nodeState[id].state == ALOHA && nodeState[id].p == 0 -> 
73              
74  //            printf("%d --Sending \n" , id);
75                P1!id,nodeState[id].members,nodeState[id].r;  
76                P2!id,nodeState[id].members,nodeState[id].r;
77                 if 
78                    ::true ->  nodeState[id].p = 0;
79                    ::true ->  nodeState[id].p = 1;
80                    ::skip
81                fi;             
82            ::nodeState[id].state == ALOHA && nodeState[id].p == 1 -> 
83                if 
84                ::true ->  nodeState[id].p = 0;
85                ::true ->  nodeState[id].p = 1
86                fi;
87  //            printf("%d --Sending with proabality %d\n" , id, nodeState[id].p);
88                
89          // send TDMA
90            ::nodeState[id].state != ALOHA -> 
91  //          printf("%d --Sending TDM\n" , id)
92              
93              P1!id,nodeState[id].members,nodeState[id].r;  
94              P2!id,nodeState[id].members,nodeState[id].r 
95            ::skip
96            
97            fi;
98        }    
99      
100      :: empty(PR) ->
101           skip
102      :: nempty(PR) ->
103        PR?id_j,members_j,r_j;
104 //     printf("%d Size of channel %d\n", id, len(PR));
105        atomic {
106          if 
107           ::nodeState[id].state ==  ALOHA ->
108           nodeState[id].messageLost[id_j] = 0;
109           nodeState[id].members = nodeState[id].members | (1 << id_j); 
110           if 
111             ::nodeState[id].members == members_j ->
112               nodeState[id].cmembers = nodeState[id].members | (1 << id_j)
113             ::skip
114           fi;
115           if 
116             ::nodeState[id].cmembers == members_j ->
117               printf("%d reaches TDMA\n", id);
118               nodeState[id].state = TDMA
119               if 
120             ::nodeState[id].leader > members_j -> 
121               nodeState[id].leader = members_j
122             ::skip
123               fi;
124               if 
125             ::nodeState[id].leader == members_j -> 
126               nodeState[id].r = r_j
127             ::skip
128               fi;
129              ::nodeState[id].cmembers != members_j ->
130             skip
131           fi;
132 //         printf("%d --Receiving in ALOHA %d from %d\n" , id,  nodeState[id].members, id_j);
133 
134         ::nodeState[id].state !=  ALOHA -> 
135 //      printf("%d reaches TDMA\n" , id);
136         nodeState[id].messageLost[id_j] = 0
137          
138         fi; 
139       } 
140       //round
141          // Failure detector 
142      :: nodeState[id].state == TDMA && 
143           (nodeState[id].messageLost[0] > 3 || nodeState[id].messageLost[1] > 3 || nodeState[id].messageLost[2] > 3) ->
144           atomic {
145         printf("%d ALOHA from failure Detector\n", id);
146 
147         nodeState[id].state = ALOHA;
148         nodeState[id].members = 1 << id;
149         nodeState[id].cmembers = 1 << id;
150         nodeState[id].leader = id
151           } 
152 //   :: nodeState[id].round > 0 ->   
153 //      nodeState[id].round = (nodeState[id].round + 1) % 2
154      :: nodeState[id].r != id ->
155        // printf("%d in round %d\n" , id, nodeState[id].r);
156         nodeState[id].r =  (nodeState[id].r + 1) % 4
157         
158         //nodeState[id].round = (nodeState[id].round + 1) % 2
159      :: skip
160    od;
161 }

第 57.I 行出现错误,我不确定这是什么意思。当我 运行 我的代码在终端上工作正常 bt 与 ispin 接口它抛出这个错误。有人遇到过这个错误吗?

在花了很多时间浏览代码之后。我尝试了 hit 和 trial,并从模型中删除了最后一个 skip 语句。似乎许多可能的替代 guard 语句以及额外的 skip 语句使它成为一个无条件的自循环。 当我从 do loop.

中删除最后一个 ::skip 语句时它起作用了

看来 Spin 有一些非常简单的机制来检测 无条件自循环 由某些循环守卫等于 skip 或 [=16] =] 没有后续 指令 被执行,例如:

init
{
    do
        :: skip            // or true
    od;
}

打印:

~$ spin -search test.pml 
error: proctype ':init:' line 4, state 2: has unconditional self-loop

pan: elapsed time 1.76e+07 seconds
pan: rate         0 states/second

可以通过添加一个额外的空语句轻松绕过该例程:

init
{
    do
        :: skip -> skip            // or true -> true
    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 1, errors: 0
        2 states, stored
        1 states, matched
        3 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:6, state 6, "-end-"
    (1 of 6 states)

pan: elapsed time 0 seconds

有趣的是,例程没有考虑其他明显的情况,在这些情况下会出现无条件自循环例如当守卫是编号与 0 不同,并且没有可重入指令块。