Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Avoid useless stuff when logging is disabled in SafetyChecker
[simgrid.git] / src / mc / SafetyChecker.cpp
index 0a05e4a..b1929fc 100644 (file)
@@ -51,7 +51,7 @@ static int snapshot_compare(simgrid::mc::State* state1, simgrid::mc::State* stat
   return snapshot_compare(num1, s1, num2, s2);
 }
 
-bool SafetyChecker::checkNonDeterminism(simgrid::mc::State* current_state)
+bool SafetyChecker::checkNonTermination(simgrid::mc::State* current_state)
 {
   for (auto i = stack_.rbegin(); i != stack_.rend(); ++i)
     if (snapshot_compare(i->get(), current_state) == 0){
@@ -96,8 +96,6 @@ int SafetyChecker::run()
   this->init();
 
   int value;
-  smx_simcall_t req = nullptr;
-  std::unique_ptr<simgrid::mc::VisitedState> visited_state = nullptr;
 
   while (!stack_.empty()) {
 
@@ -106,176 +104,183 @@ int SafetyChecker::run()
 
     XBT_DEBUG("**************************************************");
     XBT_DEBUG(
-      "Exploration depth=%zi (state=%p, num %d)(%u interleave, user_max_depth %d)",
+      "Exploration depth=%zi (state=%p, num %d)(%u interleave)",
       stack_.size(), state, state->num,
-      MC_state_interleave_size(state), user_max_depth_reached);
+      MC_state_interleave_size(state));
 
-    /* Update statistics */
     mc_stats->visited_states++;
 
-    /* If there are processes to interleave and the maximum depth has not been reached
-       then perform one step of the exploration algorithm */
-    if (stack_.size() <= (std::size_t) _sg_mc_max_depth && !user_max_depth_reached
-        && (req = MC_state_get_request(state, &value)) && visited_state == nullptr) {
+    // The interleave set is empty or the maximum depth is reached,
+    // let's back-track.
+    smx_simcall_t req = nullptr;
+    if (stack_.size() > (std::size_t) _sg_mc_max_depth
+        || (req = MC_state_get_request(state, &value)) == nullptr
+        || visitedState_ != nullptr) {
+      int res = this->backtrack();
+      if (res)
+        return res;
+      else
+        continue;
+    }
+
+    // If there are processes to interleave and the maximum depth has not been
+    // reached then perform one step of the exploration algorithm.
 
+    if (XBT_LOG_ISENABLED(mc_safety, xbt_log_priority_debug)) {
       char* req_str = simgrid::mc::request_to_string(req, value, simgrid::mc::RequestType::simix);
       XBT_DEBUG("Execute: %s", req_str);
       xbt_free(req_str);
+    }
 
-      if (dot_output != nullptr)
-        req_str = simgrid::mc::request_get_dot_output(req, value);
-
-      MC_state_set_executed_request(state, req, value);
-      mc_stats->executed_transitions++;
-
-      // TODO, bundle both operations in a single message
-      //   MC_execute_transition(req, value)
+    char* req_str = nullptr;
+    if (dot_output != nullptr)
+      req_str = simgrid::mc::request_get_dot_output(req, value);
 
-      /* Answer the request */
-      simgrid::mc::handle_simcall(req, value);
-      mc_model_checker->wait_for_requests();
+    MC_state_set_executed_request(state, req, value);
+    mc_stats->executed_transitions++;
 
-      /* Create the new expanded state */
-      std::unique_ptr<simgrid::mc::State> next_state =
-        std::unique_ptr<simgrid::mc::State>(MC_state_new());
+    // TODO, bundle both operations in a single message
+    //   MC_execute_transition(req, value)
 
-      if (_sg_mc_termination && this->checkNonDeterminism(next_state.get())){
-          MC_show_non_termination();
-          return SIMGRID_MC_EXIT_NON_TERMINATION;
-      }
+    /* Answer the request */
+    simgrid::mc::handle_simcall(req, value);
+    mc_model_checker->wait_for_requests();
 
-      if (_sg_mc_visited == 0
-          || (visited_state = visitedStates_.addVisitedState(next_state.get(), true)) == nullptr) {
+    /* Create the new expanded state */
+    std::unique_ptr<simgrid::mc::State> next_state =
+      std::unique_ptr<simgrid::mc::State>(MC_state_new());
 
-        /* Get an enabled process and insert it in the interleave set of the next state */
-        for (auto& p : mc_model_checker->process().simix_processes())
-          if (simgrid::mc::process_is_enabled(&p.copy)) {
-            MC_state_interleave_process(next_state.get(), &p.copy);
-            if (reductionMode_ != simgrid::mc::ReductionMode::none)
-              break;
-          }
-
-        if (dot_output != nullptr)
-          std::fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", state->num, next_state->num, req_str);
+    if (_sg_mc_termination && this->checkNonTermination(next_state.get())) {
+        MC_show_non_termination();
+        return SIMGRID_MC_EXIT_NON_TERMINATION;
+    }
 
-      } else if (dot_output != nullptr)
-        std::fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", state->num, visited_state->other_num == -1 ? visited_state->num : visited_state->other_num, req_str);
+    if (_sg_mc_visited == 0
+        || (visitedState_ = visitedStates_.addVisitedState(next_state.get(), true)) == nullptr) {
 
-      stack_.push_back(std::move(next_state));
+      /* Get an enabled process and insert it in the interleave set of the next state */
+      for (auto& p : mc_model_checker->process().simix_processes())
+        if (simgrid::mc::process_is_enabled(&p.copy)) {
+          MC_state_interleave_process(next_state.get(), &p.copy);
+          if (reductionMode_ != simgrid::mc::ReductionMode::none)
+            break;
+        }
 
       if (dot_output != nullptr)
-        xbt_free(req_str);
+        std::fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", state->num, next_state->num, req_str);
 
-      /* Let's loop again */
+    } else if (dot_output != nullptr)
+      std::fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n", state->num, visitedState_->other_num == -1 ? visitedState_->num : visitedState_->other_num, req_str);
 
-      /* The interleave set is empty or the maximum depth is reached, let's back-track */
-    } else {
+    stack_.push_back(std::move(next_state));
+
+    if (dot_output != nullptr)
+      xbt_free(req_str);
+  }
 
-      if (stack_.size() > (std::size_t) _sg_mc_max_depth
-          || user_max_depth_reached
-          || visited_state != nullptr) {
+  XBT_INFO("No property violation found.");
+  MC_print_statistics(mc_stats);
+  initial_global_state = nullptr;
+  return SIMGRID_MC_EXIT_SUCCESS;
+}
 
-        if (user_max_depth_reached && visited_state == nullptr)
-          XBT_DEBUG("User max depth reached !");
-        else if (visited_state == nullptr)
-          XBT_WARN("/!\\ Max depth reached ! /!\\ ");
-        else
-          XBT_DEBUG("State already visited (equal to state %d), exploration stopped on this path.", visited_state->other_num == -1 ? visited_state->num : visited_state->other_num);
+int SafetyChecker::backtrack()
+{
+  if (stack_.size() > (std::size_t) _sg_mc_max_depth
+      || visitedState_ != nullptr) {
+    if (visitedState_ == nullptr)
+      XBT_WARN("/!\\ Max depth reached ! /!\\ ");
+    else
+      XBT_DEBUG("State already visited (equal to state %d),"
+        " exploration stopped on this path.",
+        visitedState_->other_num == -1 ? visitedState_->num : visitedState_->other_num);
+  } else
+    XBT_DEBUG("There are no more processes to interleave. (depth %zi)",
+      stack_.size() + 1);
+
+  stack_.pop_back();
+
+  visitedState_ = nullptr;
+
+  /* Check for deadlocks */
+  if (mc_model_checker->checkDeadlock()) {
+    MC_show_deadlock();
+    return SIMGRID_MC_EXIT_DEADLOCK;
+  }
 
-      } else
-        XBT_DEBUG("There are no more processes to interleave. (depth %zi)",
-          stack_.size() + 1);
+  /* Traverse the stack backwards until a state with a non empty interleave
+     set is found, deleting all the states that have it empty in the way.
+     For each deleted state, check if the request that has generated it 
+     (from it's predecesor state), depends on any other previous request 
+     executed before it. If it does then add it to the interleave set of the
+     state that executed that previous request. */
 
-      /* Trash the current state, no longer needed */
-      XBT_DEBUG("Delete state %d at depth %zi", state->num, stack_.size());
-      stack_.pop_back();
+  while (!stack_.empty()) {
+    std::unique_ptr<simgrid::mc::State> state = std::move(stack_.back());
+    stack_.pop_back();
+    if (reductionMode_ == simgrid::mc::ReductionMode::dpor) {
+      smx_simcall_t req = MC_state_get_internal_request(state.get());
+      if (req->call == SIMCALL_MUTEX_LOCK || req->call == SIMCALL_MUTEX_TRYLOCK)
+        xbt_die("Mutex is currently not supported with DPOR, "
+          "use --cfg=model-check/reduction:none");
+      const smx_process_t issuer = MC_smx_simcall_get_issuer(req);
+      for (auto i = stack_.rbegin(); i != stack_.rend(); ++i) {
+        simgrid::mc::State* prev_state = i->get();
+        if (reductionMode_ != simgrid::mc::ReductionMode::none
+            && simgrid::mc::request_depend(req, MC_state_get_internal_request(prev_state))) {
+          if (XBT_LOG_ISENABLED(mc_safety, xbt_log_priority_debug)) {
+            XBT_DEBUG("Dependent Transitions:");
+            int value;
+            smx_simcall_t prev_req = MC_state_get_executed_request(prev_state, &value);
+            char* req_str = simgrid::mc::request_to_string(prev_req, value, simgrid::mc::RequestType::internal);
+            XBT_DEBUG("%s (state=%d)", req_str, prev_state->num);
+            xbt_free(req_str);
+            prev_req = MC_state_get_executed_request(state.get(), &value);
+            req_str = simgrid::mc::request_to_string(prev_req, value, simgrid::mc::RequestType::executed);
+            XBT_DEBUG("%s (state=%d)", req_str, state->num);
+            xbt_free(req_str);
+          }
 
-      visited_state = nullptr;
+          if (!MC_state_process_is_done(prev_state, issuer))
+            MC_state_interleave_process(prev_state, issuer);
+          else
+            XBT_DEBUG("Process %p is in done set", req->issuer);
 
-      /* Check for deadlocks */
-      if (mc_model_checker->checkDeadlock()) {
-        MC_show_deadlock();
-        return SIMGRID_MC_EXIT_DEADLOCK;
-      }
+          break;
 
-      /* Traverse the stack backwards until a state with a non empty interleave
-         set is found, deleting all the states that have it empty in the way.
-         For each deleted state, check if the request that has generated it 
-         (from it's predecesor state), depends on any other previous request 
-         executed before it. If it does then add it to the interleave set of the
-         state that executed that previous request. */
-
-      while (!stack_.empty()) {
-        std::unique_ptr<simgrid::mc::State> state = std::move(stack_.back());
-        stack_.pop_back();
-        if (reductionMode_ == simgrid::mc::ReductionMode::dpor) {
-          req = MC_state_get_internal_request(state.get());
-          if (req->call == SIMCALL_MUTEX_LOCK || req->call == SIMCALL_MUTEX_TRYLOCK)
-            xbt_die("Mutex is currently not supported with DPOR, "
-              "use --cfg=model-check/reduction:none");
-          const smx_process_t issuer = MC_smx_simcall_get_issuer(req);
-          for (auto i = stack_.rbegin(); i != stack_.rend(); ++i) {
-            simgrid::mc::State* prev_state = i->get();
-            if (reductionMode_ != simgrid::mc::ReductionMode::none
-                && simgrid::mc::request_depend(req, MC_state_get_internal_request(prev_state))) {
-              if (XBT_LOG_ISENABLED(mc_safety, xbt_log_priority_debug)) {
-                XBT_DEBUG("Dependent Transitions:");
-                smx_simcall_t prev_req = MC_state_get_executed_request(prev_state, &value);
-                char* req_str = simgrid::mc::request_to_string(prev_req, value, simgrid::mc::RequestType::internal);
-                XBT_DEBUG("%s (state=%d)", req_str, prev_state->num);
-                xbt_free(req_str);
-                prev_req = MC_state_get_executed_request(state.get(), &value);
-                req_str = simgrid::mc::request_to_string(prev_req, value, simgrid::mc::RequestType::executed);
-                XBT_DEBUG("%s (state=%d)", req_str, state->num);
-                xbt_free(req_str);
-              }
-
-              if (!MC_state_process_is_done(prev_state, issuer))
-                MC_state_interleave_process(prev_state, issuer);
-              else
-                XBT_DEBUG("Process %p is in done set", req->issuer);
-
-              break;
-
-            } else if (req->issuer == MC_state_get_internal_request(prev_state)->issuer) {
-
-              XBT_DEBUG("Simcall %d and %d with same issuer", req->call, MC_state_get_internal_request(prev_state)->call);
-              break;
-
-            } else {
-
-              const smx_process_t previous_issuer = MC_smx_simcall_get_issuer(MC_state_get_internal_request(prev_state));
-              XBT_DEBUG("Simcall %d, process %lu (state %d) and simcall %d, process %lu (state %d) are independant",
-                        req->call, issuer->pid, state->num,
-                        MC_state_get_internal_request(prev_state)->call,
-                        previous_issuer->pid,
-                        prev_state->num);
-
-            }
-          }
-        }
+        } else if (req->issuer == MC_state_get_internal_request(prev_state)->issuer) {
 
-        if (MC_state_interleave_size(state.get())
-            && stack_.size() < (std::size_t) _sg_mc_max_depth) {
-          /* We found a back-tracking point, let's loop */
-          XBT_DEBUG("Back-tracking to state %d at depth %zi",
-            state->num, stack_.size() + 1);
-          stack_.push_back(std::move(state));
-          simgrid::mc::replay(stack_);
-          XBT_DEBUG("Back-tracking to state %d at depth %zi done",
-            stack_.back()->num, stack_.size());
+          XBT_DEBUG("Simcall %d and %d with same issuer", req->call, MC_state_get_internal_request(prev_state)->call);
           break;
+
         } else {
-          XBT_DEBUG("Delete state %d at depth %zi",
-            state->num, stack_.size() + 1);
+
+          const smx_process_t previous_issuer = MC_smx_simcall_get_issuer(MC_state_get_internal_request(prev_state));
+          XBT_DEBUG("Simcall %d, process %lu (state %d) and simcall %d, process %lu (state %d) are independant",
+                    req->call, issuer->pid, state->num,
+                    MC_state_get_internal_request(prev_state)->call,
+                    previous_issuer->pid,
+                    prev_state->num);
+
         }
       }
     }
-  }
 
-  XBT_INFO("No property violation found.");
-  MC_print_statistics(mc_stats);
-  initial_global_state = nullptr;
+    if (MC_state_interleave_size(state.get())
+        && stack_.size() < (std::size_t) _sg_mc_max_depth) {
+      /* We found a back-tracking point, let's loop */
+      XBT_DEBUG("Back-tracking to state %d at depth %zi",
+        state->num, stack_.size() + 1);
+      stack_.push_back(std::move(state));
+      simgrid::mc::replay(stack_);
+      XBT_DEBUG("Back-tracking to state %d at depth %zi done",
+        stack_.back()->num, stack_.size());
+      break;
+    } else {
+      XBT_DEBUG("Delete state %d at depth %zi",
+        state->num, stack_.size() + 1);
+    }
+  }
   return SIMGRID_MC_EXIT_SUCCESS;
 }