1 /* Copyright (c) 2008-2012 Da SimGrid Team. All rights reserved. */
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. */
11 #include "../surf/surf_private.h"
12 #include "../simix/smx_private.h"
14 #include "mc_private.h"
15 #include "xbt/automaton.h"
17 XBT_LOG_NEW_CATEGORY(mc, "All MC categories");
18 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_global, mc,
19 "Logging specific to MC (global)");
21 /* MC global data structures */
23 mc_state_t mc_current_state = NULL;
24 char mc_replay_mode = FALSE;
25 double *mc_time = NULL;
26 mc_snapshot_t initial_snapshot = NULL;
30 xbt_fifo_t mc_stack_safety = NULL;
31 mc_stats_t mc_stats = NULL;
35 mc_stats_pair_t mc_stats_pair = NULL;
36 xbt_fifo_t mc_stack_liveness = NULL;
37 mc_snapshot_t initial_snapshot_liveness = NULL;
39 xbt_automaton_t _mc_property_automaton = NULL;
41 static void MC_assert_pair(int prop);
45 * \brief Initialize the model-checker data structures
47 void MC_init_safety(void)
50 /* Check if MC is already initialized */
54 mc_time = xbt_new0(double, simix_process_maxpid);
56 /* Initialize the data structures that must be persistent across every
57 iteration of the model-checker (in RAW memory) */
60 /* Initialize statistics */
61 mc_stats = xbt_new0(s_mc_stats_t, 1);
62 mc_stats->state_size = 1;
64 /* Create exploration stack */
65 mc_stack_safety = xbt_fifo_new();
72 /* Save the initial state */
73 initial_snapshot = xbt_new0(s_mc_snapshot_t, 1);
74 MC_take_snapshot(initial_snapshot);
81 void MC_modelcheck(void)
88 void MC_modelcheck_liveness(){
90 XBT_DEBUG("Start init mc");
92 mc_time = xbt_new0(double, simix_process_maxpid);
94 /* Initialize the data structures that must be persistent across every
95 iteration of the model-checker (in RAW memory) */
99 /* Initialize statistics */
100 mc_stats_pair = xbt_new0(s_mc_stats_pair_t, 1);
102 XBT_DEBUG("Creating stack");
104 /* Create exploration stack */
105 mc_stack_liveness = xbt_fifo_new();
113 MC_print_statistics_pairs(mc_stats_pair);
122 MC_print_statistics(mc_stats);
128 int MC_random(int min, int max)
130 /*FIXME: return mc_current_state->executed_transition->random.value;*/
135 * \brief Schedules all the process that are ready to run
137 void MC_wait_for_requests(void)
139 smx_process_t process;
143 while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
144 SIMIX_process_runall();
145 xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
146 req = &process->simcall;
147 if (req->call != SIMCALL_NONE && !MC_request_is_visible(req))
148 SIMIX_simcall_pre(req, 0);
153 int MC_deadlock_check()
155 int deadlock = FALSE;
156 smx_process_t process;
157 if(xbt_swag_size(simix_global->process_list)){
159 xbt_swag_foreach(process, simix_global->process_list){
160 if(process->simcall.call != SIMCALL_NONE
161 && MC_request_is_enabled(&process->simcall)){
171 * \brief Re-executes from the state at position start all the transitions indicated by
172 * a given model-checker stack.
173 * \param stack The stack with the transitions to execute.
174 * \param start Start index to begin the re-execution.
176 void MC_replay(xbt_fifo_t stack, int start)
180 smx_simcall_t req = NULL, saved_req = NULL;
181 xbt_fifo_item_t item, start_item;
184 XBT_DEBUG("**** Begin Replay ****");
187 /* Restore the initial state */
188 MC_restore_snapshot(initial_snapshot);
189 /* At the moment of taking the snapshot the raw heap was set, so restoring
190 * it will set it back again, we have to unset it to continue */
194 start_item = xbt_fifo_get_last_item(stack);
197 start_item = xbt_fifo_get_prev_item(start_item);
202 /* Traverse the stack from the state at position start and re-execute the transitions */
203 for (item = start_item;
204 item != xbt_fifo_get_first_item(stack);
205 item = xbt_fifo_get_prev_item(item)) {
207 state = (mc_state_t) xbt_fifo_get_item_content(item);
208 saved_req = MC_state_get_executed_request(state, &value);
211 /* because we got a copy of the executed request, we have to fetch the
212 real one, pointed by the request field of the issuer process */
213 req = &saved_req->issuer->simcall;
215 /* Debug information */
216 if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
217 req_str = MC_request_to_string(req, value);
218 XBT_DEBUG("Replay: %s (%p)", req_str, state);
223 SIMIX_simcall_pre(req, value);
224 MC_wait_for_requests();
226 /* Update statistics */
227 mc_stats->visited_states++;
228 mc_stats->executed_transitions++;
230 XBT_DEBUG("**** End Replay ****");
233 void MC_replay_liveness(xbt_fifo_t stack, int all_stack)
237 smx_simcall_t req = NULL, saved_req = NULL;
238 xbt_fifo_item_t item;
240 mc_pair_stateless_t pair;
243 XBT_DEBUG("**** Begin Replay ****");
245 /* Restore the initial state */
246 MC_restore_snapshot(initial_snapshot_liveness);
247 /* At the moment of taking the snapshot the raw heap was set, so restoring
248 * it will set it back again, we have to unset it to continue */
253 item = xbt_fifo_get_last_item(stack);
255 while(depth <= xbt_fifo_size(stack)){
257 pair = (mc_pair_stateless_t) xbt_fifo_get_item_content(item);
258 state = (mc_state_t) pair->graph_state;
260 if(pair->requests > 0){
262 saved_req = MC_state_get_executed_request(state, &value);
263 //XBT_DEBUG("SavedReq->call %u", saved_req->call);
265 if(saved_req != NULL){
266 /* because we got a copy of the executed request, we have to fetch the
267 real one, pointed by the request field of the issuer process */
268 req = &saved_req->issuer->simcall;
269 //XBT_DEBUG("Req->call %u", req->call);
271 /* Debug information */
272 if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
273 req_str = MC_request_to_string(req, value);
274 XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
280 SIMIX_simcall_pre(req, value);
281 MC_wait_for_requests();
286 /* Update statistics */
287 mc_stats_pair->visited_pairs++;
289 item = xbt_fifo_get_prev_item(item);
294 /* Traverse the stack from the initial state and re-execute the transitions */
295 for (item = xbt_fifo_get_last_item(stack);
296 item != xbt_fifo_get_first_item(stack);
297 item = xbt_fifo_get_prev_item(item)) {
299 pair = (mc_pair_stateless_t) xbt_fifo_get_item_content(item);
300 state = (mc_state_t) pair->graph_state;
302 if(pair->requests > 0){
304 saved_req = MC_state_get_executed_request(state, &value);
305 //XBT_DEBUG("SavedReq->call %u", saved_req->call);
307 if(saved_req != NULL){
308 /* because we got a copy of the executed request, we have to fetch the
309 real one, pointed by the request field of the issuer process */
310 req = &saved_req->issuer->simcall;
311 //XBT_DEBUG("Req->call %u", req->call);
313 /* Debug information */
314 if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
315 req_str = MC_request_to_string(req, value);
316 XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
322 SIMIX_simcall_pre(req, value);
323 MC_wait_for_requests();
328 /* Update statistics */
329 mc_stats_pair->visited_pairs++;
333 XBT_DEBUG("**** End Replay ****");
337 * \brief Dumps the contents of a model-checker's stack and shows the actual
339 * \param stack The stack to dump
341 void MC_dump_stack_safety(xbt_fifo_t stack)
344 MC_show_stack_safety(stack);
346 if(!_surf_do_mc_checkpoint){
351 while ((state = (mc_state_t) xbt_fifo_pop(stack)) != NULL)
352 MC_state_delete(state);
359 void MC_show_stack_safety(xbt_fifo_t stack)
363 xbt_fifo_item_t item;
365 char *req_str = NULL;
367 for (item = xbt_fifo_get_last_item(stack);
368 (item ? (state = (mc_state_t) (xbt_fifo_get_item_content(item)))
369 : (NULL)); item = xbt_fifo_get_prev_item(item)) {
370 req = MC_state_get_executed_request(state, &value);
372 req_str = MC_request_to_string(req, value);
373 XBT_INFO("%s", req_str);
379 void MC_show_deadlock(smx_simcall_t req)
381 /*char *req_str = NULL;*/
382 XBT_INFO("**************************");
383 XBT_INFO("*** DEAD-LOCK DETECTED ***");
384 XBT_INFO("**************************");
385 XBT_INFO("Locked request:");
386 /*req_str = MC_request_to_string(req);
387 XBT_INFO("%s", req_str);
389 XBT_INFO("Counter-example execution trace:");
390 MC_dump_stack_safety(mc_stack_safety);
394 void MC_show_stack_liveness(xbt_fifo_t stack){
396 mc_pair_stateless_t pair;
397 xbt_fifo_item_t item;
399 char *req_str = NULL;
401 for (item = xbt_fifo_get_last_item(stack);
402 (item ? (pair = (mc_pair_stateless_t) (xbt_fifo_get_item_content(item)))
403 : (NULL)); item = xbt_fifo_get_prev_item(item)) {
404 req = MC_state_get_executed_request(pair->graph_state, &value);
406 if(pair->requests>0){
407 req_str = MC_request_to_string(req, value);
408 XBT_INFO("%s", req_str);
411 XBT_INFO("End of system requests but evolution in Büchi automaton");
417 void MC_dump_stack_liveness(xbt_fifo_t stack){
418 mc_pair_stateless_t pair;
421 while ((pair = (mc_pair_stateless_t) xbt_fifo_pop(stack)) != NULL)
422 MC_pair_stateless_delete(pair);
427 void MC_print_statistics(mc_stats_t stats)
429 //XBT_INFO("State space size ~= %lu", stats->state_size);
430 XBT_INFO("Expanded states = %lu", stats->expanded_states);
431 XBT_INFO("Visited states = %lu", stats->visited_states);
432 XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
433 XBT_INFO("Expanded / Visited = %lf",
434 (double) stats->visited_states / stats->expanded_states);
435 /*XBT_INFO("Exploration coverage = %lf",
436 (double)stats->expanded_states / stats->state_size); */
439 void MC_print_statistics_pairs(mc_stats_pair_t stats)
441 XBT_INFO("Expanded pairs = %lu", stats->expanded_pairs);
442 XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
443 //XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
444 XBT_INFO("Expanded / Visited = %lf",
445 (double) stats->visited_pairs / stats->expanded_pairs);
446 /*XBT_INFO("Exploration coverage = %lf",
447 (double)stats->expanded_states / stats->state_size); */
450 void MC_assert(int prop)
452 if (MC_IS_ENABLED && !prop){
453 XBT_INFO("**************************");
454 XBT_INFO("*** PROPERTY NOT VALID ***");
455 XBT_INFO("**************************");
456 XBT_INFO("Counter-example execution trace:");
457 MC_dump_stack_safety(mc_stack_safety);
458 MC_print_statistics(mc_stats);
463 static void MC_assert_pair(int prop){
464 if (MC_IS_ENABLED && !prop) {
465 XBT_INFO("**************************");
466 XBT_INFO("*** PROPERTY NOT VALID ***");
467 XBT_INFO("**************************");
468 //XBT_INFO("Counter-example execution trace:");
469 MC_show_stack_liveness(mc_stack_liveness);
470 //MC_dump_snapshot_stack(mc_snapshot_stack);
471 MC_print_statistics_pairs(mc_stats_pair);
476 void MC_process_clock_add(smx_process_t process, double amount)
478 mc_time[process->pid] += amount;
481 double MC_process_clock_get(smx_process_t process)
484 return mc_time[process->pid];
491 mc_snapshot_t sn = xbt_new0(s_mc_snapshot_t, 1);
492 MC_take_snapshot_liveness(sn);
496 XBT_INFO("Number of regions : %u", sn->num_reg);
498 for(i=0; i<sn->num_reg; i++){
500 switch(sn->regions[i]->type){
502 XBT_INFO("Size of heap : %zu", sn->regions[i]->size);
503 mmalloc_display_info_heap(sn->regions[i]->data);
505 case 1 : /* libsimgrid */
506 XBT_INFO("Size of libsimgrid : %zu", sn->regions[i]->size);
508 case 2 : /* data program */
509 XBT_INFO("Size of data program : %zu", sn->regions[i]->size);
512 XBT_INFO("Size of stack : %zu", sn->regions[i]->size);
513 XBT_INFO("Start addr of stack : %p", sn->regions[i]->start_addr);
521 void MC_automaton_load(const char *file){
523 if (_mc_property_automaton == NULL)
524 _mc_property_automaton = xbt_automaton_new();
525 xbt_automaton_load(_mc_property_automaton,file);
528 void MC_automaton_new_propositional_symbol(const char* id, void* fct) {
530 if (_mc_property_automaton == NULL)
531 _mc_property_automaton = xbt_automaton_new();
532 xbt_new_propositional_symbol(_mc_property_automaton,id,fct);