Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
model-checker : restore previous version of MC_state_set_executed_request, fixed...
[simgrid.git] / src / mc / mc_dpor.c
1 /* Copyright (c) 2008-2012. Da SimGrid Team. All rights reserved.           */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "mc_private.h"
7
8 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dpor, mc,
9                                 "Logging specific to MC DPOR exploration");
10
11 xbt_dynar_t visited_states;
12
13 static int is_visited_state(void);
14
15 static int is_visited_state(){
16
17   if(_surf_mc_visited == 0)
18     return 0;
19
20   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
21
22   MC_SET_RAW_MEM;
23
24   mc_snapshot_t new_state = NULL;
25   new_state = MC_take_snapshot();  
26
27   MC_UNSET_RAW_MEM;
28   
29   if(xbt_dynar_is_empty(visited_states)){
30
31     MC_SET_RAW_MEM;
32     xbt_dynar_push(visited_states, &new_state); 
33     MC_UNSET_RAW_MEM;
34
35     if(raw_mem_set)
36       MC_SET_RAW_MEM;
37  
38     return 0;
39
40   }else{
41
42     MC_SET_RAW_MEM;
43     
44     unsigned int cursor = 0;
45     mc_snapshot_t state_test = NULL;
46      
47     xbt_dynar_foreach(visited_states, cursor, state_test){
48       if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug))
49         XBT_DEBUG("****** Pair visited #%d ******", cursor + 1);
50       if(snapshot_compare(new_state, state_test, NULL, NULL) == 0){
51         if(raw_mem_set)
52           MC_SET_RAW_MEM;
53         else
54           MC_UNSET_RAW_MEM;
55         
56         return 1;
57       }   
58     }
59
60     if(xbt_dynar_length(visited_states) == _surf_mc_visited){
61       mc_snapshot_t state_to_remove = NULL;
62       xbt_dynar_shift(visited_states, &state_to_remove);
63       MC_free_snapshot(state_to_remove);
64     }
65
66     xbt_dynar_push(visited_states, &new_state); 
67     
68     MC_UNSET_RAW_MEM;
69
70     if(raw_mem_set)
71       MC_SET_RAW_MEM;
72     
73     return 0;
74     
75   }
76 }
77
78 /**
79  *  \brief Initialize the DPOR exploration algorithm
80  */
81 void MC_dpor_init()
82 {
83   
84   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
85
86   mc_state_t initial_state = NULL;
87   smx_process_t process;
88   
89   /* Create the initial state and push it into the exploration stack */
90   MC_SET_RAW_MEM;
91
92   initial_state = MC_state_new();
93   visited_states = xbt_dynar_new(sizeof(mc_snapshot_t), NULL);
94
95   MC_UNSET_RAW_MEM;
96
97   XBT_DEBUG("**************************************************");
98   XBT_DEBUG("Initial state");
99
100   /* Wait for requests (schedules processes) */
101   MC_wait_for_requests();
102
103   MC_SET_RAW_MEM;
104
105   xbt_swag_foreach(process, simix_global->process_list){
106     if(MC_process_is_enabled(process)){
107       XBT_DEBUG("Process %lu enabled with simcall : %d", process->pid, (&process->simcall)->call); 
108     }
109   }
110   
111   /* Get an enabled process and insert it in the interleave set of the initial state */
112   xbt_swag_foreach(process, simix_global->process_list){
113     if(MC_process_is_enabled(process)){
114       MC_state_interleave_process(initial_state, process);
115       break;
116     }
117   }
118
119   xbt_fifo_unshift(mc_stack_safety, initial_state);
120
121   MC_UNSET_RAW_MEM;
122
123   if(raw_mem_set)
124     MC_SET_RAW_MEM;
125   else
126     MC_UNSET_RAW_MEM;
127   
128     
129   /* FIXME: Update Statistics 
130      mc_stats->state_size +=
131      xbt_setset_set_size(initial_state->enabled_transitions); */
132 }
133
134
135 /**
136  *   \brief Perform the model-checking operation using a depth-first search exploration
137  *         with Dynamic Partial Order Reductions
138  */
139 void MC_dpor(void)
140 {
141
142   char *req_str;
143   int value;
144   smx_simcall_t req = NULL, prev_req = NULL;
145   mc_state_t state = NULL, prev_state = NULL, next_state = NULL, restore_state=NULL;
146   smx_process_t process = NULL;
147   xbt_fifo_item_t item = NULL;
148   int pos;
149
150   while (xbt_fifo_size(mc_stack_safety) > 0) {
151
152     /* Get current state */
153     state = (mc_state_t) 
154       xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_stack_safety));
155
156     XBT_DEBUG("**************************************************");
157     XBT_DEBUG("Exploration depth=%d (state=%p)(%u interleave)",
158               xbt_fifo_size(mc_stack_safety), state,
159               MC_state_interleave_size(state));
160
161     /* Update statistics */
162     mc_stats->visited_states++;
163
164     /* If there are processes to interleave and the maximum depth has not been reached
165        then perform one step of the exploration algorithm */
166     if (xbt_fifo_size(mc_stack_safety) < _surf_mc_max_depth &&
167         (req = MC_state_get_request(state, &value))) {
168
169       /* Debug information */
170       if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
171         req_str = MC_request_to_string(req, value);
172         XBT_DEBUG("Execute: %s", req_str);
173         xbt_free(req_str);
174       }
175
176       MC_state_set_executed_request(state, req, value);
177       mc_stats->executed_transitions++;
178
179       /* Answer the request */
180       SIMIX_simcall_pre(req, value); /* After this call req is no longer usefull */
181
182       /* Wait for requests (schedules processes) */
183       MC_wait_for_requests();
184
185       /* Create the new expanded state */
186       MC_SET_RAW_MEM;
187
188       next_state = MC_state_new();
189
190       if(!is_visited_state()){
191      
192         /* Get an enabled process and insert it in the interleave set of the next state */
193         xbt_swag_foreach(process, simix_global->process_list){
194           if(MC_process_is_enabled(process)){
195             MC_state_interleave_process(next_state, process);
196             XBT_DEBUG("Process %lu enabled with simcall : %d", process->pid, (&process->simcall)->call); 
197           }
198         }
199
200         if(_surf_mc_checkpoint && ((xbt_fifo_size(mc_stack_safety) + 1) % _surf_mc_checkpoint == 0)){
201           next_state->system_state = MC_take_snapshot();
202         }
203
204       }else{
205
206         XBT_DEBUG("State already visited !");
207         
208       }
209
210       xbt_fifo_unshift(mc_stack_safety, next_state);
211       MC_UNSET_RAW_MEM;
212
213       /* FIXME: Update Statistics
214          mc_stats->state_size +=
215          xbt_setset_set_size(next_state->enabled_transitions);*/
216
217       /* Let's loop again */
218
219       /* The interleave set is empty or the maximum depth is reached, let's back-track */
220     } else {
221
222       if(xbt_fifo_size(mc_stack_safety) == _surf_mc_max_depth){
223         
224         XBT_WARN("/!\\ Max depth reached ! /!\\ ");
225         if(req != NULL){
226           XBT_WARN("/!\\ But, there are still processes to interleave. Model-checker will not be able to ensure the soundness of the verification from now. /!\\ "); 
227           XBT_WARN("Notice : the default value of max depth is 1000 but you can change it with cfg=model-check/max_depth:value.");
228         }
229
230       }else{
231
232         XBT_DEBUG("There are no more processes to interleave.");
233
234       }
235
236       /* Trash the current state, no longer needed */
237       MC_SET_RAW_MEM;
238       xbt_fifo_shift(mc_stack_safety);
239       MC_state_delete(state);
240       MC_UNSET_RAW_MEM;
241
242       /* Check for deadlocks */
243       if(MC_deadlock_check()){
244         MC_show_deadlock(NULL);
245         return;
246       }
247
248       MC_SET_RAW_MEM;
249       /* Traverse the stack backwards until a state with a non empty interleave
250          set is found, deleting all the states that have it empty in the way.
251          For each deleted state, check if the request that has generated it 
252          (from it's predecesor state), depends on any other previous request 
253          executed before it. If it does then add it to the interleave set of the
254          state that executed that previous request. */
255       
256       while ((state = xbt_fifo_shift(mc_stack_safety)) != NULL) {
257         if(MC_state_interleave_size(state) == 0){
258           req = MC_state_get_internal_request(state);
259           xbt_fifo_foreach(mc_stack_safety, item, prev_state, mc_state_t) {
260             if(MC_request_depend(req, MC_state_get_internal_request(prev_state))){
261               if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
262                 XBT_DEBUG("Dependent Transitions:");
263                 prev_req = MC_state_get_executed_request(prev_state, &value);
264                 req_str = MC_request_to_string(prev_req, value);
265                 XBT_DEBUG("%s (state=%p)", req_str, prev_state);
266                 xbt_free(req_str);
267                 prev_req = MC_state_get_executed_request(state, &value);
268                 req_str = MC_request_to_string(prev_req, value);
269                 XBT_DEBUG("%s (state=%p)", req_str, state);
270                 xbt_free(req_str);              
271               }
272
273               break;
274
275             }else if(req->issuer == MC_state_get_executed_request(prev_state, &value)->issuer){
276
277               break;
278
279             }else{
280               
281               MC_state_remove_interleave_process(prev_state, req->issuer);
282
283             }
284           }
285         }
286         if (MC_state_interleave_size(state)) {
287           /* We found a back-tracking point, let's loop */
288           if(_surf_mc_checkpoint){
289             if(state->system_state != NULL){
290               MC_restore_snapshot(state->system_state);
291               xbt_fifo_unshift(mc_stack_safety, state);
292               XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack_safety));
293               MC_UNSET_RAW_MEM;
294             }else{
295               pos = xbt_fifo_size(mc_stack_safety);
296               item = xbt_fifo_get_first_item(mc_stack_safety);
297               while(pos>0){
298                 restore_state = (mc_state_t) xbt_fifo_get_item_content(item);
299                 if(restore_state->system_state != NULL){
300                   break;
301                 }else{
302                   item = xbt_fifo_get_next_item(item);
303                   pos--;
304                 }
305               }
306               MC_restore_snapshot(restore_state->system_state);
307               xbt_fifo_unshift(mc_stack_safety, state);
308               XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack_safety));
309               MC_UNSET_RAW_MEM;
310               MC_replay(mc_stack_safety, pos);
311             }
312           }else{
313             xbt_fifo_unshift(mc_stack_safety, state);
314             XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack_safety));
315             MC_UNSET_RAW_MEM;
316             MC_replay(mc_stack_safety, -1);
317           }
318           break;
319         } else {
320           MC_state_delete(state);
321         }
322       }
323       MC_UNSET_RAW_MEM;
324     }
325   }
326   MC_print_statistics(mc_stats);
327   MC_UNSET_RAW_MEM;  
328
329   return;
330 }
331
332
333
334