Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of github.com:simgrid/simgrid
authorEhsan Azimi <eazimi@ehsan.irisa.fr>
Mon, 16 Nov 2020 17:16:17 +0000 (18:16 +0100)
committerEhsan Azimi <eazimi@ehsan.irisa.fr>
Mon, 16 Nov 2020 17:16:17 +0000 (18:16 +0100)
src/mc/checker/SafetyChecker.cpp
src/mc/checker/simgrid_mc.cpp
src/mc/mc_api.cpp [new file with mode: 0644]
src/mc/mc_api.hpp [new file with mode: 0644]
src/mc/mc_base.cpp
tools/cmake/DefinePackages.cmake

index 9f9716f..3a97114 100644 (file)
 #include "src/mc/mc_record.hpp"
 #include "src/mc/mc_request.hpp"
 #include "src/mc/mc_smx.hpp"
+#include "src/mc/mc_api.hpp"
 
 #include "src/xbt/mmalloc/mmprivate.h"
 
+using mcapi = simgrid::mc::mc_api;
+
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_safety, mc, "Logging specific to MC safety verification ");
 
 namespace simgrid {
@@ -34,16 +37,17 @@ namespace mc {
 void SafetyChecker::check_non_termination(const State* current_state)
 {
   for (auto state = stack_.rbegin(); state != stack_.rend(); ++state)
-    if (snapshot_equal((*state)->system_state_.get(), current_state->system_state_.get())) {
+    if (mcapi::get().snapshot_equal((*state)->system_state_.get(), current_state->system_state_.get())) {
       XBT_INFO("Non-progressive cycle: state %d -> state %d", (*state)->num_, current_state->num_);
       XBT_INFO("******************************************");
       XBT_INFO("*** NON-PROGRESSIVE CYCLE DETECTED ***");
       XBT_INFO("******************************************");
       XBT_INFO("Counter-example execution trace:");
-      for (auto const& s : mc_model_checker->getChecker()->get_textual_trace())
+      auto checker = mcapi::get().mc_get_checker();
+      for (auto const& s : checker->get_textual_trace())
         XBT_INFO("  %s", s.c_str());
-      dumpRecordPath();
-      session->log_state();
+      mcapi::get().mc_dump_record_path();
+      mcapi::get().s_log_state();
 
       throw TerminationError();
     }
@@ -64,7 +68,7 @@ std::vector<std::string> SafetyChecker::get_textual_trace() // override
     int value         = state->transition_.argument_;
     smx_simcall_t req = &state->executed_req_;
     if (req)
-      trace.push_back(request_to_string(req, value, RequestType::executed));
+      trace.push_back(mcapi::get().request_to_string(req, value, RequestType::executed));
   }
   return trace;
 }
@@ -72,8 +76,8 @@ std::vector<std::string> SafetyChecker::get_textual_trace() // override
 void SafetyChecker::log_state() // override
 {
   XBT_INFO("Expanded states = %lu", expanded_states_count_);
-  XBT_INFO("Visited states = %lu", mc_model_checker->visited_states);
-  XBT_INFO("Executed transitions = %lu", mc_model_checker->executed_transitions);
+  XBT_INFO("Visited states = %lu", mcapi::get().mc_get_visited_states());
+  XBT_INFO("Executed transitions = %lu", mcapi::get().mc_get_executed_trans());
 }
 
 void SafetyChecker::run()
@@ -90,7 +94,7 @@ void SafetyChecker::run()
     XBT_VERB("Exploration depth=%zu (state=%p, num %d)(%zu interleave)", stack_.size(), state, state->num_,
              state->interleave_size());
 
-    mc_model_checker->visited_states++;
+    mcapi::get().mc_inc_visited_states();
 
     // Backtrack if we reached the maximum depth
     if (stack_.size() > (std::size_t)_sg_mc_max_depth) {
@@ -111,7 +115,7 @@ void SafetyChecker::run()
 
     // Search an enabled transition in the current state; backtrack if the interleave set is empty
     // get_request also sets state.transition to be the one corresponding to the returned req
-    smx_simcall_t req = MC_state_choose_request(state);
+    smx_simcall_t req = mcapi::get().mc_state_choose_request(state);
     // req is now the transition of the process that was selected to be executed
 
     if (req == nullptr) {
@@ -123,16 +127,16 @@ void SafetyChecker::run()
 
     // If there are processes to interleave and the maximum depth has not been
     // reached then perform one step of the exploration algorithm.
-    XBT_DEBUG("Execute: %s", request_to_string(req, state->transition_.argument_, RequestType::simix).c_str());
+    XBT_DEBUG("Execute: %s", mcapi::get().request_to_string(req, state->transition_.argument_, RequestType::simix).c_str());
 
     std::string req_str;
     if (dot_output != nullptr)
-      req_str = request_get_dot_output(req, state->transition_.argument_);
+      req_str = mcapi::get().request_get_dot_output(req, state->transition_.argument_);
 
-    mc_model_checker->executed_transitions++;
+    mcapi::get().mc_inc_executed_trans();
 
     /* Actually answer the request: let execute the selected request (MCed does one step) */
-    this->get_session().execute(state->transition_);
+    mcapi::get().execute(state->transition_);
 
     /* Create the new expanded state (copy the state of MCed into our MCer data) */
     ++expanded_states_count_;
@@ -148,9 +152,10 @@ void SafetyChecker::run()
     /* If this is a new state (or if we don't care about state-equality reduction) */
     if (visited_state_ == nullptr) {
       /* Get an enabled process and insert it in the interleave set of the next state */
-      for (auto& remoteActor : mc_model_checker->get_remote_simulation().actors()) {
+      auto actors = mcapi::get().mc_get_remote_simulation().actors();
+      for (auto& remoteActor : actors) {
         auto actor = remoteActor.copy.get_buffer();
-        if (actor_is_enabled(actor)) {
+        if (mcapi::get().actor_is_enabled(actor->get_pid())) {
           next_state->add_interleaving_set(actor);
           if (reductionMode_ == ReductionMode::dpor)
             break; // With DPOR, we take the first enabled transition
@@ -169,7 +174,7 @@ void SafetyChecker::run()
   }
 
   XBT_INFO("No property violation found.");
-  session->log_state();
+  mcapi::get().s_log_state();
 }
 
 void SafetyChecker::backtrack()
@@ -177,8 +182,8 @@ void SafetyChecker::backtrack()
   stack_.pop_back();
 
   /* Check for deadlocks */
-  if (mc_model_checker->checkDeadlock()) {
-    MC_show_deadlock();
+  if (mcapi::get().mc_check_deadlock()) {
+    mcapi::get().mc_show_deadlock();
     throw DeadlockError();
   }
 
@@ -195,19 +200,19 @@ void SafetyChecker::backtrack()
       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 kernel::actor::ActorImpl* issuer = MC_smx_simcall_get_issuer(req);
+      const kernel::actor::ActorImpl* issuer = mcapi::get().mc_smx_simcall_get_issuer(req);
       for (auto i = stack_.rbegin(); i != stack_.rend(); ++i) {
         State* prev_state = i->get();
-        if (request_depend(req, &prev_state->internal_req_)) {
+        if (mcapi::get().request_depend(req, &prev_state->internal_req_)) {
           if (XBT_LOG_ISENABLED(mc_safety, xbt_log_priority_debug)) {
             XBT_DEBUG("Dependent Transitions:");
             int value              = prev_state->transition_.argument_;
             smx_simcall_t prev_req = &prev_state->executed_req_;
-            XBT_DEBUG("%s (state=%d)", simgrid::mc::request_to_string(prev_req, value, RequestType::internal).c_str(),
+            XBT_DEBUG("%s (state=%d)", mcapi::get().request_to_string(prev_req, value, RequestType::internal).c_str(),
                       prev_state->num_);
             value    = state->transition_.argument_;
             prev_req = &state->executed_req_;
-            XBT_DEBUG("%s (state=%d)", simgrid::mc::request_to_string(prev_req, value, RequestType::executed).c_str(),
+            XBT_DEBUG("%s (state=%d)", mcapi::get().request_to_string(prev_req, value, RequestType::executed).c_str(),
                       state->num_);
           }
 
@@ -217,14 +222,14 @@ void SafetyChecker::backtrack()
             XBT_DEBUG("Process %p is in done set", req->issuer_);
           break;
         } else if (req->issuer_ == prev_state->internal_req_.issuer_) {
-          XBT_DEBUG("Simcall %s and %s with same issuer", SIMIX_simcall_name(req->call_),
-                    SIMIX_simcall_name(prev_state->internal_req_.call_));
+          XBT_DEBUG("Simcall %s and %s with same issuer", mcapi::get().simix_simcall_name(req->call_),
+                    mcapi::get().simix_simcall_name(prev_state->internal_req_.call_));
           break;
         } else {
-          const kernel::actor::ActorImpl* previous_issuer = MC_smx_simcall_get_issuer(&prev_state->internal_req_);
+          const kernel::actor::ActorImpl* previous_issuer = mcapi::get().mc_smx_simcall_get_issuer(&prev_state->internal_req_);
           XBT_DEBUG("Simcall %s, process %ld (state %d) and simcall %s, process %ld (state %d) are independent",
-                    SIMIX_simcall_name(req->call_), issuer->get_pid(), state->num_,
-                    SIMIX_simcall_name(prev_state->internal_req_.call_), previous_issuer->get_pid(), prev_state->num_);
+                    mcapi::get().simix_simcall_name(req->call_), issuer->get_pid(), state->num_,
+                    mcapi::get().simix_simcall_name(prev_state->internal_req_.call_), previous_issuer->get_pid(), prev_state->num_);
         }
       }
     }
@@ -247,21 +252,21 @@ void SafetyChecker::restore_state()
   /* Intermediate backtracking */
   const State* last_state = stack_.back().get();
   if (last_state->system_state_) {
-    last_state->system_state_->restore(&mc_model_checker->get_remote_simulation());
+    last_state->system_state_->restore(&mcapi::get().mc_get_remote_simulation());
     return;
   }
 
   /* Restore the initial state */
-  session->restore_initial_state();
+  mcapi::get().s_restore_initial_state();
 
   /* Traverse the stack from the state at position start and re-execute the transitions */
   for (std::unique_ptr<State> const& state : stack_) {
     if (state == stack_.back())
       break;
-    session->execute(state->transition_);
+    mcapi::get().execute(state->transition_);
     /* Update statistics */
-    mc_model_checker->visited_states++;
-    mc_model_checker->executed_transitions++;
+    mcapi::get().mc_inc_visited_states();
+    mcapi::get().mc_inc_executed_trans();
   }
 }
 
@@ -279,7 +284,8 @@ SafetyChecker::SafetyChecker(Session& s) : Checker(s)
     XBT_INFO("Check a safety property. Reduction is: %s.",
              (reductionMode_ == ReductionMode::none ? "none"
                                                     : (reductionMode_ == ReductionMode::dpor ? "dpor" : "unknown")));
-  session->initialize();
+  
+  mcapi::get().s_initialize();  
 
   XBT_DEBUG("Starting the safety algorithm");
 
@@ -290,8 +296,9 @@ SafetyChecker::SafetyChecker(Session& s) : Checker(s)
   XBT_DEBUG("Initial state");
 
   /* Get an enabled actor and insert it in the interleave set of the initial state */
-  for (auto& actor : mc_model_checker->get_remote_simulation().actors())
-    if (actor_is_enabled(actor.copy.get_buffer())) {
+  auto actors = mcapi::get().get_actors();
+  for (auto& actor : actors)
+    if (mcapi::get().actor_is_enabled(actor.copy.get_buffer()->get_pid())) {
       initial_state->add_interleaving_set(actor.copy.get_buffer());
       if (reductionMode_ != ReductionMode::none)
         break;
index 9168cc9..e382e9f 100644 (file)
@@ -10,6 +10,7 @@
 #include "src/mc/mc_config.hpp"
 #include "src/mc/mc_exit.hpp"
 #include "src/internal_config.h"
+#include "src/mc/mc_api.hpp"
 
 #if HAVE_SMPI
 #include "smpi/smpi.h"
@@ -19,6 +20,8 @@
 #include <memory>
 #include <unistd.h>
 
+using mcapi = simgrid::mc::mc_api;
+
 static inline
 char** argvdup(int argc, char** argv)
 {
@@ -54,15 +57,7 @@ int main(int argc, char** argv)
   smpi_init_options(); // only performed once
 #endif
   sg_config_init(&argc, argv);
-  simgrid::mc::session = new simgrid::mc::Session([argv_copy] {
-    int i = 1;
-    while (argv_copy[i] != nullptr && argv_copy[i][0] == '-')
-      i++;
-    xbt_assert(argv_copy[i] != nullptr,
-               "Unable to find a binary to exec on the command line. Did you only pass config flags?");
-    execvp(argv_copy[i], argv_copy + i);
-    xbt_die("The model-checked process failed to exec(): %s", strerror(errno));
-  });
+  mcapi::get().initialize(argv_copy);
   delete[] argv_copy;
 
   auto checker = create_checker(*simgrid::mc::session);
@@ -77,6 +72,6 @@ int main(int argc, char** argv)
     res = SIMGRID_MC_EXIT_LIVENESS;
   }
   checker = nullptr;
-  simgrid::mc::session->close();
+  mcapi::get().s_close();
   return res;
 }
diff --git a/src/mc/mc_api.cpp b/src/mc/mc_api.cpp
new file mode 100644 (file)
index 0000000..e4b98cd
--- /dev/null
@@ -0,0 +1,182 @@
+#include "mc_api.hpp"
+
+#include "src/mc/Session.hpp"
+#include "src/mc/mc_private.hpp"
+#include "src/mc/mc_smx.hpp"
+#include "src/mc/remote/RemoteSimulation.hpp"
+#include "src/mc/mc_record.hpp"
+
+#include <xbt/asserts.h>
+#include <xbt/log.h>
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_api, mc, "Logging specific to MC Fasade APIs ");
+
+namespace simgrid {
+namespace mc {
+
+void mc_api::initialize(char** argv)
+{
+  simgrid::mc::session = new simgrid::mc::Session([argv] {
+    int i = 1;
+    while (argv[i] != nullptr && argv[i][0] == '-')
+      i++;
+    xbt_assert(argv[i] != nullptr,
+               "Unable to find a binary to exec on the command line. Did you only pass config flags?");
+    execvp(argv[i], argv + i);
+    xbt_die("The model-checked process failed to exec(): %s", strerror(errno));
+  });
+}
+
+std::vector<simgrid::mc::ActorInformation>& mc_api::get_actors() const
+{
+  return mc_model_checker->get_remote_simulation().actors();
+}
+
+bool mc_api::actor_is_enabled(aid_t pid) const
+{
+  return session->actor_is_enabled(pid);
+}
+
+void mc_api::s_initialize() const
+{
+  session->initialize();
+}
+
+ModelChecker* mc_api::get_model_checker() const
+{
+  return mc_model_checker;
+}
+
+void mc_api::mc_inc_visited_states() const
+{
+  mc_model_checker->visited_states++;
+}
+
+void mc_api::mc_inc_executed_trans() const
+{
+  mc_model_checker->executed_transitions++;
+}
+
+unsigned long mc_api::mc_get_visited_states() const
+{
+  return mc_model_checker->visited_states;
+}
+
+unsigned long mc_api::mc_get_executed_trans() const
+{
+  return mc_model_checker->executed_transitions;
+}
+
+bool mc_api::mc_check_deadlock() const
+{
+  return mc_model_checker->checkDeadlock();
+}
+
+void mc_api::mc_show_deadlock() const
+{
+  MC_show_deadlock();
+}
+
+smx_actor_t mc_api::mc_smx_simcall_get_issuer(s_smx_simcall const* req) const
+{
+  return MC_smx_simcall_get_issuer(req);
+}
+
+bool mc_api::mc_is_null() const
+{
+  auto is_null = (mc_model_checker == nullptr) ? true : false;
+  return is_null;
+}
+
+Checker* mc_api::mc_get_checker() const
+{
+  return mc_model_checker->getChecker();
+}
+
+RemoteSimulation& mc_api::mc_get_remote_simulation() const
+{
+  return mc_model_checker->get_remote_simulation();
+}
+
+void mc_api::handle_simcall(Transition const& transition) const
+{
+  mc_model_checker->handle_simcall(transition);
+}
+
+void mc_api::mc_wait_for_requests() const
+{
+  mc_model_checker->wait_for_requests();
+}
+
+void mc_api::mc_exit(int status) const
+{
+  mc_model_checker->exit(status);
+}
+
+std::string const& mc_api::mc_get_host_name(std::string const& hostname) const
+{
+  return mc_model_checker->get_host_name(hostname);
+}
+
+PageStore& mc_api::mc_page_store() const
+{
+  return mc_model_checker->page_store();
+}
+
+void mc_api::mc_dump_record_path() const
+{
+  simgrid::mc::dumpRecordPath();
+}
+
+smx_simcall_t mc_api::mc_state_choose_request(simgrid::mc::State* state) const
+{
+  return MC_state_choose_request(state);
+}
+
+bool mc_api::request_depend(smx_simcall_t req1, smx_simcall_t req2) const
+{
+  return simgrid::mc::request_depend(req1, req2);
+}
+
+std::string mc_api::request_to_string(smx_simcall_t req, int value, RequestType request_type) const
+{
+  return simgrid::mc::request_to_string(req, value, request_type).c_str();
+}
+
+std::string mc_api::request_get_dot_output(smx_simcall_t req, int value) const
+{
+  return simgrid::mc::request_get_dot_output(req, value);
+}
+
+const char* mc_api::simix_simcall_name(e_smx_simcall_t kind) const
+{
+  return SIMIX_simcall_name(kind);
+}
+
+bool mc_api::snapshot_equal(const Snapshot* s1, const Snapshot* s2) const
+{
+  return simgrid::mc::snapshot_equal(s1, s2);
+}
+
+void mc_api::s_close() const
+{
+  session->close();
+}
+
+void mc_api::s_restore_initial_state() const
+{
+  session->restore_initial_state();
+}
+
+void mc_api::execute(Transition const& transition)
+{
+  session->execute(transition);
+}
+
+void mc_api::s_log_state() const
+{
+  session->log_state();
+}
+
+} // namespace mc
+} // namespace simgrid
diff --git a/src/mc/mc_api.hpp b/src/mc/mc_api.hpp
new file mode 100644 (file)
index 0000000..be1f107
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef SIMGRID_MC_API_HPP
+#define SIMGRID_MC_API_HPP
+
+#include <memory>
+#include <vector>
+
+#include "simgrid/forward.h"
+#include "src/mc/mc_forward.hpp"
+#include "src/mc/mc_request.hpp"
+#include "src/mc/mc_state.hpp"
+#include "xbt/base.h"
+
+namespace simgrid {
+namespace mc {
+
+/*
+** This class aimes to implement FACADE APIs for simgrid. The FACADE layer sits between the CheckerSide
+** (Unfolding_Checker, DPOR, ...) layer and the
+** AppSide layer. The goal is to drill down into the entagled details in the CheckerSide layer and break down the
+** detailes in a way that the CheckerSide eventually
+** be capable to acquire the required information through the FACADE layer rather than the direct access to the AppSide.
+*/
+
+class mc_api {
+private:
+  mc_api() = default;
+
+public:
+  // No copy:
+  mc_api(mc_api const&) = delete;
+  void operator=(mc_api const&) = delete;
+
+  static mc_api& get()
+  {
+    static mc_api mcapi;
+    return mcapi;
+  }
+
+  void initialize(char** argv);
+
+  // ACTOR FUNCTIONS  
+  std::vector<simgrid::mc::ActorInformation>& get_actors() const;
+  bool actor_is_enabled(aid_t pid) const;
+
+  // MODEL_CHECKER FUNCTIONS
+  ModelChecker* get_model_checker() const;
+  void mc_inc_visited_states() const;
+  void mc_inc_executed_trans() const;
+  unsigned long mc_get_visited_states() const;
+  unsigned long mc_get_executed_trans() const;
+  bool mc_check_deadlock() const;
+  void mc_show_deadlock() const;
+  smx_actor_t mc_smx_simcall_get_issuer(s_smx_simcall const* req) const;
+  bool mc_is_null() const;
+  Checker* mc_get_checker() const;
+  RemoteSimulation& mc_get_remote_simulation() const;
+  void handle_simcall(Transition const& transition) const;
+  void mc_wait_for_requests() const;
+  void mc_exit(int status) const;
+  std::string const& mc_get_host_name(std::string const& hostname) const;
+  PageStore& mc_page_store() const;
+  void mc_dump_record_path() const;
+  smx_simcall_t mc_state_choose_request(simgrid::mc::State* state) const;
+
+  // SIMCALL FUNCTIONS
+  bool request_depend(smx_simcall_t req1, smx_simcall_t req2) const;
+  std::string request_to_string(smx_simcall_t req, int value, RequestType request_type) const;
+  std::string request_get_dot_output(smx_simcall_t req, int value) const;
+  const char *simix_simcall_name(e_smx_simcall_t kind) const;
+
+  // SNAPSHOT FUNCTIONS
+  bool snapshot_equal(const Snapshot* s1, const Snapshot* s2) const;
+
+  // SESSION FUNCTIONS
+  void s_initialize() const;
+  void s_close() const;
+  void s_restore_initial_state() const;
+  void execute(Transition const& transition);
+  void s_log_state() const;
+};
+
+} // namespace mc
+} // namespace simgrid
+
+#endif
\ No newline at end of file
index 2a59567..c081163 100644 (file)
@@ -70,12 +70,14 @@ void wait_for_requests()
 // Called from both MCer and MCed:
 bool actor_is_enabled(smx_actor_t actor)
 {
+// #del
 #if SIMGRID_HAVE_MC
   // If in the MCer, ask the client app since it has all the data
   if (mc_model_checker != nullptr) {
     return simgrid::mc::session->actor_is_enabled(actor->get_pid());
   }
 #endif
+// #
 
   // Now, we are in the client app, no need for remote memory reading.
   smx_simcall_t req = &actor->simcall_;
index 1062af7..2552584 100644 (file)
@@ -611,7 +611,7 @@ set(MC_SRC
   src/mc/checker/SimcallInspector.hpp
   src/mc/checker/LivenessChecker.cpp
   src/mc/checker/LivenessChecker.hpp
-  
+
   src/mc/inspect/DwarfExpression.hpp
   src/mc/inspect/DwarfExpression.cpp
   src/mc/inspect/Frame.hpp
@@ -661,6 +661,8 @@ set(MC_SRC
   src/mc/mc_comm_pattern.cpp
   src/mc/mc_comm_pattern.hpp
   src/mc/compare.cpp
+  src/mc/mc_api.cpp
+  src/mc/mc_api.hpp
   src/mc/mc_hash.hpp
   src/mc/mc_hash.cpp
   src/mc/mc_ignore.hpp