Logo AND Algorithmique Numérique Distribuée

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