Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Introduce mc::mc_api (pull request 1 -- #349)
authorEhsan Azimi <azimi.ehsan@outlook.com>
Fri, 27 Nov 2020 23:12:04 +0000 (00:12 +0100)
committerGitHub <noreply@github.com>
Fri, 27 Nov 2020 23:12:04 +0000 (00:12 +0100)
* mc_api class introduced, SafetyChecher's constructor and main() in simgrid_mc.cpp call mc_api's functions

* SafetyChecker::restore_state() calls mc_api functions

* SafetyChecker::backtrack() calls mc_api functions

* SafetyChecker::log_state() calls  APIs of mc_api

* SafetyChecker::get_textual_trace() uses mc_api

* SafetyChecker::check_non_termination() uses mc_api

* SafetyChecker::run() uses mc_api

* mc_assert() deleted

* get_maxpid() and take_snapshot() in mc_api

* copy_incomplete_comm_pattern() and copy_index_comm_pattern() in mc_api

* mc_api::mc_state_choose_request() updated

* In VisitedState class, get_remote_heap_bytes() from mc_api is called

* prepare() and run() call APIs of mc_api

* CommunicationDeterminismChecker::real_run() uses APIs of mc_api

* CommunicationDeterminismChecker::restoreState() uses APIs of mc_api

* CommunicationDeterminismChecker::log_state() uses APIs of mc_api

* mc_pattern.hpp created

* get_pattern_comm_rdv() defined in mc_api and used in CommDet checker

* mc_api::get_pattern_comm_rdv()
mc_api::get_pattern_comm_addr()
mc_api::get_pattern_comm_src_proc()
mc_api::get_pattern_comm_data()
mc_api::get_actor_host_name()
The above functions are defined in mc_api and being used in comm_dete checker

* conflict with simgrid/master resolved

* unused variable removed

* call APIs from facade layer

* mc_api::get_smpi_request_tag() defined and used in comm_deter checker

* mc_api::get_pattern_comm_dst_proc() defined and used in comm_deter checker

* mc_api::check_send_request_detached() defined and used in comm_deter checker

* CommunicationDeterminismChecker::deterministic_comm_pattern() uses APIs of mc_api

* mc_api clean up

* mc_api::get_src_actor() defined,
it used in update_comm_pattern() of comm. deter. checker

* mc_api::get_dst_actor() defined,
it used in update_comm_pattern() of comm. deter. checker

* mc_api::get_actor_host_name() used by update_comm_pattern() in comm. deter. checker

* mc_api::get_pattern_comm_data() defined,
it used by update_comm_pattern() in comm. deter. checker

Co-authored-by: Ehsan Azimi <eazimi@ehsan.irisa.fr>
12 files changed:
src/mc/VisitedState.cpp
src/mc/checker/CommunicationDeterminismChecker.cpp
src/mc/checker/LivenessChecker.cpp
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
src/mc/mc_pattern.hpp [new file with mode: 0644]
src/mc/mc_state.cpp
src/mc/mc_state.hpp
tools/cmake/DefinePackages.cmake

index 1f30705..fa49142 100644 (file)
 #include <sys/wait.h>
 #include <memory>
 #include <boost/range/algorithm.hpp>
+#include "src/mc/mc_api.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_VisitedState, mc, "Logging specific to state equality detection mechanisms");
 
+using mcapi = simgrid::mc::mc_api;
+
 namespace simgrid {
 namespace mc {
 
 /** @brief Save the current state */
 VisitedState::VisitedState(unsigned long state_number) : num(state_number)
-{
-  simgrid::mc::RemoteSimulation* process = &(mc_model_checker->get_remote_simulation());
-  this->heap_bytes_used = mmalloc_get_bytes_used_remote(
-    process->get_heap()->heaplimit,
-    process->get_malloc_info());
-
-  this->actors_count = mc_model_checker->get_remote_simulation().actors().size();
-
+{  
+  this->heap_bytes_used = mcapi::get().get_remote_heap_bytes();
+  this->actors_count = mcapi::get().mc_get_remote_simulation().actors().size();
   this->system_state = std::make_shared<simgrid::mc::Snapshot>(state_number);
 }
 
@@ -58,7 +56,7 @@ VisitedStates::addVisitedState(unsigned long state_number, simgrid::mc::State* g
   if (compare_snapshots)
     for (auto i = range.first; i != range.second; ++i) {
       auto& visited_state = *i;
-      if (snapshot_equal(visited_state->system_state.get(), new_state->system_state.get())) {
+      if (mcapi::get().snapshot_equal(visited_state->system_state.get(), new_state->system_state.get())) {
         // The state has been visited:
 
         std::unique_ptr<simgrid::mc::VisitedState> old_state =
index 4022f90..9ac7aa3 100644 (file)
@@ -6,6 +6,7 @@
 #include "src/mc/checker/CommunicationDeterminismChecker.hpp"
 #include "src/kernel/activity/MailboxImpl.hpp"
 #include "src/mc/Session.hpp"
+#include "src/mc/mc_api.hpp"
 #include "src/mc/mc_config.hpp"
 #include "src/mc/mc_exit.hpp"
 #include "src/mc/mc_private.hpp"
@@ -19,6 +20,7 @@
 #include <cstdint>
 
 using simgrid::mc::remote;
+using mcapi = simgrid::mc::mc_api;
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_comm_determinism, mc, "Logging specific to MC communication determinism detection");
 
@@ -33,7 +35,7 @@ static simgrid::mc::CommPatternDifference compare_comm_pattern(const simgrid::mc
                                                                const simgrid::mc::PatternCommunication* comm2)
 {
   using simgrid::mc::CommPatternDifference;
-  if(comm1->type != comm2->type)
+  if (comm1->type != comm2->type)
     return CommPatternDifference::TYPE;
   if (comm1->rdv != comm2->rdv)
     return CommPatternDifference::RDV;
@@ -62,7 +64,7 @@ static char* print_determinism_result(simgrid::mc::CommPatternDifference diff, i
     type = bprintf("The recv communications pattern of the process %d is different!", process - 1);
 
   using simgrid::mc::CommPatternDifference;
-  switch(diff) {
+  switch (diff) {
     case CommPatternDifference::TYPE:
       res = bprintf("%s Different type for communication #%u", type, cursor);
       break;
@@ -95,26 +97,21 @@ static char* print_determinism_result(simgrid::mc::CommPatternDifference diff, i
 static void update_comm_pattern(simgrid::mc::PatternCommunication* comm_pattern,
                                 simgrid::mc::RemotePtr<simgrid::kernel::activity::CommImpl> comm_addr)
 {
-  // HACK, type punning
-  simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_comm;
-  mc_model_checker->get_remote_simulation().read(temp_comm, comm_addr);
-  const simgrid::kernel::activity::CommImpl* comm = temp_comm.get_buffer();
-
-  smx_actor_t src_proc =
-      mc_model_checker->get_remote_simulation().resolve_actor(simgrid::mc::remote(comm->src_actor_.get()));
-  smx_actor_t dst_proc =
-      mc_model_checker->get_remote_simulation().resolve_actor(simgrid::mc::remote(comm->dst_actor_.get()));
+  auto src_proc = mcapi::get().get_src_actor(comm_addr);
+  auto dst_proc = mcapi::get().get_dst_actor(comm_addr);
   comm_pattern->src_proc = src_proc->get_pid();
   comm_pattern->dst_proc = dst_proc->get_pid();
-  comm_pattern->src_host = MC_smx_actor_get_host_name(src_proc);
-  comm_pattern->dst_host = MC_smx_actor_get_host_name(dst_proc);
-  if (comm_pattern->data.empty() && comm->src_buff_ != nullptr) {
-    size_t buff_size;
-    mc_model_checker->get_remote_simulation().read(&buff_size, remote(comm->dst_buff_size_));
-    comm_pattern->data.resize(buff_size);
-    mc_model_checker->get_remote_simulation().read_bytes(comm_pattern->data.data(), comm_pattern->data.size(),
-                                                         remote(comm->src_buff_));
-  }
+  comm_pattern->src_host = mcapi::get().get_actor_host_name(src_proc);
+  comm_pattern->dst_host = mcapi::get().get_actor_host_name(dst_proc);
+
+  if (comm_pattern->data.empty()) {
+    auto pattern_data = mcapi::get().get_pattern_comm_data(comm_addr);
+    if (pattern_data.data() != nullptr) {
+      auto data_size = pattern_data.size();
+      comm_pattern->data.resize(data_size);
+      memcpy(comm_pattern->data.data(), pattern_data.data(), data_size);
+    }
+   }
 }
 
 namespace simgrid {
@@ -124,8 +121,8 @@ void CommunicationDeterminismChecker::deterministic_comm_pattern(int process, co
                                                                  int backtracking)
 {
   if (not backtracking) {
-    PatternCommunicationList& list      = initial_communications_pattern[process];
-    CommPatternDifference diff          = compare_comm_pattern(list.list[list.index_comm].get(), comm);
+    PatternCommunicationList& list = initial_communications_pattern[process];
+    CommPatternDifference diff     = compare_comm_pattern(list.list[list.index_comm].get(), comm);
 
     if (diff != CommPatternDifference::NONE) {
       if (comm->type == PatternCommunicationType::send) {
@@ -146,8 +143,8 @@ void CommunicationDeterminismChecker::deterministic_comm_pattern(int process, co
         XBT_INFO("%s", this->send_diff);
         xbt_free(this->send_diff);
         this->send_diff = nullptr;
-        mc::session->log_state();
-        mc_model_checker->exit(SIMGRID_MC_EXIT_NON_DETERMINISM);
+        mcapi::get().s_log_state();
+        mcapi::get().mc_exit(SIMGRID_MC_EXIT_NON_DETERMINISM);
       } else if (_sg_mc_comms_determinism && (not this->send_deterministic && not this->recv_deterministic)) {
         XBT_INFO("****************************************************");
         XBT_INFO("***** Non-deterministic communications pattern *****");
@@ -162,8 +159,8 @@ void CommunicationDeterminismChecker::deterministic_comm_pattern(int process, co
           xbt_free(this->recv_diff);
           this->recv_diff = nullptr;
         }
-        mc::session->log_state();
-        mc_model_checker->exit(SIMGRID_MC_EXIT_NON_DETERMINISM);
+        mcapi::get().s_log_state();
+        mcapi::get().mc_exit(SIMGRID_MC_EXIT_NON_DETERMINISM);
       }
     }
   }
@@ -173,7 +170,7 @@ void CommunicationDeterminismChecker::deterministic_comm_pattern(int process, co
 
 void CommunicationDeterminismChecker::get_comm_pattern(smx_simcall_t request, CallType call_type, int backtracking)
 {
-  const smx_actor_t issuer = MC_smx_simcall_get_issuer(request);
+  const smx_actor_t issuer                                     = mcapi::get().mc_smx_simcall_get_issuer(request);
   const mc::PatternCommunicationList& initial_pattern          = initial_communications_pattern[issuer->get_pid()];
   const std::vector<PatternCommunication*>& incomplete_pattern = incomplete_communications_pattern[issuer->get_pid()];
 
@@ -183,33 +180,24 @@ void CommunicationDeterminismChecker::get_comm_pattern(smx_simcall_t request, Ca
   if (call_type == CallType::SEND) {
     /* Create comm pattern */
     pattern->type      = PatternCommunicationType::send;
-    pattern->comm_addr = static_cast<kernel::activity::CommImpl*>(simcall_comm_isend__getraw__result(request));
-
-    Remote<kernel::activity::CommImpl> temp_synchro;
-    mc_model_checker->get_remote_simulation().read(temp_synchro, remote(pattern->comm_addr));
-    const kernel::activity::CommImpl* synchro = temp_synchro.get_buffer();
-
-    char* remote_name = mc_model_checker->get_remote_simulation().read<char*>(RemotePtr<char*>(
-        (uint64_t)(synchro->get_mailbox() ? &synchro->get_mailbox()->name_ : &synchro->mbox_cpy->name_)));
-    pattern->rdv      = mc_model_checker->get_remote_simulation().read_string(RemotePtr<char>(remote_name));
-    pattern->src_proc =
-        mc_model_checker->get_remote_simulation().resolve_actor(mc::remote(synchro->src_actor_.get()))->get_pid();
-    pattern->src_host = MC_smx_actor_get_host_name(issuer);
+    pattern->comm_addr = mcapi::get().get_pattern_comm_addr(request);
+    pattern->rdv      = mcapi::get().get_pattern_comm_rdv(pattern->comm_addr);
+    pattern->src_proc = mcapi::get().get_pattern_comm_src_proc(pattern->comm_addr);
+    pattern->src_host = mc_api::get().get_actor_host_name(issuer);
 
 #if HAVE_SMPI
-    simgrid::smpi::Request mpi_request;
-    mc_model_checker->get_remote_simulation().read(
-        &mpi_request, remote(static_cast<smpi::Request*>(simcall_comm_isend__get__data(request))));
-    pattern->tag = mpi_request.tag();
+    pattern->tag = mcapi::get().get_smpi_request_tag(request, simgrid::simix::Simcall::COMM_ISEND);
 #endif
-
-    if (synchro->src_buff_ != nullptr) {
-      pattern->data.resize(synchro->src_buff_size_);
-      mc_model_checker->get_remote_simulation().read_bytes(pattern->data.data(), pattern->data.size(),
-                                                           remote(synchro->src_buff_));
+    auto pattern_data = mcapi::get().get_pattern_comm_data(pattern->comm_addr);
+    if (pattern_data.data() != nullptr) {
+      auto data_size = pattern_data.size();
+      pattern->data.resize(data_size);
+      memcpy(pattern->data.data(), pattern_data.data(), data_size);
     }
+
 #if HAVE_SMPI
-    if(mpi_request.detached()){
+    auto send_detached = mcapi::get().check_send_request_detached(request);
+    if (send_detached) {
       if (this->initial_communications_pattern_done) {
         /* Evaluate comm determinism */
         this->deterministic_comm_pattern(pattern->src_proc, pattern.get(), backtracking);
@@ -222,30 +210,18 @@ void CommunicationDeterminismChecker::get_comm_pattern(smx_simcall_t request, Ca
     }
 #endif
   } else if (call_type == CallType::RECV) {
-    pattern->type      = PatternCommunicationType::receive;
-    pattern->comm_addr = static_cast<kernel::activity::CommImpl*>(simcall_comm_irecv__getraw__result(request));
+    pattern->type = PatternCommunicationType::receive;
+    pattern->comm_addr = mcapi::get().get_pattern_comm_addr(request);
 
 #if HAVE_SMPI
-    smpi::Request mpi_request;
-    mc_model_checker->get_remote_simulation().read(
-        &mpi_request, remote(static_cast<smpi::Request*>(simcall_comm_irecv__get__data(request))));
-    pattern->tag = mpi_request.tag();
+    pattern->tag = mcapi::get().get_smpi_request_tag(request, simgrid::simix::Simcall::COMM_IRECV);
 #endif
-
-    Remote<kernel::activity::CommImpl> temp_comm;
-    mc_model_checker->get_remote_simulation().read(temp_comm, remote(pattern->comm_addr));
-    const kernel::activity::CommImpl* comm = temp_comm.get_buffer();
-
-    char* remote_name;
-    mc_model_checker->get_remote_simulation().read(
-        &remote_name, remote(comm->get_mailbox() ? &xbt::string::to_string_data(comm->get_mailbox()->name_).data
-                                                 : &xbt::string::to_string_data(comm->mbox_cpy->name_).data));
-    pattern->rdv = mc_model_checker->get_remote_simulation().read_string(RemotePtr<char>(remote_name));
-    pattern->dst_proc =
-        mc_model_checker->get_remote_simulation().resolve_actor(mc::remote(comm->dst_actor_.get()))->get_pid();
-    pattern->dst_host = MC_smx_actor_get_host_name(issuer);
+    auto comm_addr = pattern->comm_addr;
+    pattern->rdv = mcapi::get().get_pattern_comm_rdv(comm_addr);
+    pattern->dst_proc = mcapi::get().get_pattern_comm_dst_proc(comm_addr);
+    pattern->dst_host = mcapi::get().get_actor_host_name(issuer);
   } else
-    xbt_die("Unexpected call_type %i", (int) call_type);
+    xbt_die("Unexpected call_type %i", (int)call_type);
 
   XBT_DEBUG("Insert incomplete comm pattern %p for process %ld", pattern.get(), issuer->get_pid());
   incomplete_communications_pattern[issuer->get_pid()].push_back(pattern.release());
@@ -278,9 +254,7 @@ void CommunicationDeterminismChecker::complete_comm_pattern(RemotePtr<kernel::ac
   }
 }
 
-CommunicationDeterminismChecker::CommunicationDeterminismChecker(Session& s) : Checker(s)
-{
-}
+CommunicationDeterminismChecker::CommunicationDeterminismChecker(Session& s) : Checker(s) {}
 
 CommunicationDeterminismChecker::~CommunicationDeterminismChecker() = default;
 
@@ -297,7 +271,7 @@ std::vector<std::string> CommunicationDeterminismChecker::get_textual_trace() //
   std::vector<std::string> trace;
   for (auto const& state : stack_) {
     smx_simcall_t req = &state->executed_req_;
-    trace.push_back(request_to_string(req, state->transition_.argument_, RequestType::executed));
+    trace.push_back(mcapi::get().request_to_string(req, state->transition_.argument_, RequestType::executed));
   }
   return trace;
 }
@@ -319,8 +293,8 @@ void CommunicationDeterminismChecker::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());
   XBT_INFO("Send-deterministic : %s", this->send_deterministic ? "Yes" : "No");
   if (_sg_mc_comms_determinism)
     XBT_INFO("Recv-deterministic : %s", this->recv_deterministic ? "Yes" : "No");
@@ -328,7 +302,7 @@ void CommunicationDeterminismChecker::log_state() // override
 
 void CommunicationDeterminismChecker::prepare()
 {
-  const int maxpid = MC_smx_get_maxpid();
+  const int maxpid = mcapi::get().get_maxpid();
 
   initial_communications_pattern.resize(maxpid);
   incomplete_communications_pattern.resize(maxpid);
@@ -339,8 +313,9 @@ void CommunicationDeterminismChecker::prepare()
   XBT_DEBUG("********* Start communication determinism verification *********");
 
   /* 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 (mc::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());
 
   stack_.push_back(std::move(initial_state));
@@ -348,7 +323,8 @@ void CommunicationDeterminismChecker::prepare()
 
 static inline bool all_communications_are_finished()
 {
-  for (size_t current_actor = 1; current_actor < MC_smx_get_maxpid(); current_actor++) {
+  auto maxpid = mcapi::get().get_maxpid();
+  for (size_t current_actor = 1; current_actor < maxpid; current_actor++) {
     if (not incomplete_communications_pattern[current_actor].empty()) {
       XBT_DEBUG("Some communications are not finished, cannot stop the exploration! State not visited.");
       return false;
@@ -362,18 +338,18 @@ void CommunicationDeterminismChecker::restoreState()
   /* Intermediate backtracking */
   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());
     MC_restore_communications_pattern(last_state);
     return;
   }
 
   /* Restore the initial state */
-  mc::session->restore_initial_state();
+  mcapi::get().s_restore_initial_state();
 
-  unsigned n = MC_smx_get_maxpid();
+  unsigned n = mcapi::get().get_maxpid();
   assert(n == incomplete_communications_pattern.size());
   assert(n == initial_communications_pattern.size());
-  for (unsigned j=0; j < n ; j++) {
+  for (unsigned j = 0; j < n; j++) {
     incomplete_communications_pattern[j].clear();
     initial_communications_pattern[j].index_comm = 0;
   }
@@ -383,32 +359,32 @@ void CommunicationDeterminismChecker::restoreState()
     if (state == stack_.back())
       break;
 
-    int req_num             = state->transition_.argument_;
+    int req_num                    = state->transition_.argument_;
     const s_smx_simcall* saved_req = &state->executed_req_;
     xbt_assert(saved_req);
 
     /* because we got a copy of the executed request, we have to fetch the
        real one, pointed by the request field of the issuer process */
 
-    const smx_actor_t issuer = MC_smx_simcall_get_issuer(saved_req);
+    const smx_actor_t issuer = mcapi::get().mc_smx_simcall_get_issuer(saved_req);
     smx_simcall_t req        = &issuer->simcall_;
 
     /* TODO : handle test and testany simcalls */
     CallType call = MC_get_call_type(req);
-    mc_model_checker->handle_simcall(state->transition_);
+    mcapi::get().handle_simcall(state->transition_);
     MC_handle_comm_pattern(call, req, req_num, 1);
-    mc_model_checker->wait_for_requests();
+    mcapi::get().mc_wait_for_requests();
 
     /* Update statistics */
-    mc_model_checker->visited_states++;
-    mc_model_checker->executed_transitions++;
+    mcapi::get().mc_inc_visited_states();
+    mcapi::get().mc_inc_executed_trans();
   }
 }
 
 void CommunicationDeterminismChecker::real_run()
 {
   std::unique_ptr<VisitedState> visited_state = nullptr;
-  smx_simcall_t req = nullptr;
+  smx_simcall_t req                           = nullptr;
 
   while (not stack_.empty()) {
     /* Get current state */
@@ -419,23 +395,23 @@ void CommunicationDeterminismChecker::real_run()
               cur_state->interleave_size());
 
     /* Update statistics */
-    mc_model_checker->visited_states++;
+    mcapi::get().mc_inc_visited_states();
 
     if (stack_.size() <= (std::size_t)_sg_mc_max_depth)
-      req = MC_state_choose_request(cur_state);
+      req = mcapi::get().mc_state_choose_request(cur_state);
     else
       req = nullptr;
 
     if (req != nullptr && visited_state == nullptr) {
       int req_num = cur_state->transition_.argument_;
 
-      XBT_DEBUG("Execute: %s", request_to_string(req, req_num, RequestType::simix).c_str());
+      XBT_DEBUG("Execute: %s", mcapi::get().request_to_string(req, req_num, RequestType::simix).c_str());
 
       std::string req_str;
       if (dot_output != nullptr)
-        req_str = request_get_dot_output(req, req_num);
+        req_str = mcapi::get().request_get_dot_output(req, req_num);
 
-      mc_model_checker->executed_transitions++;
+      mcapi::get().mc_inc_executed_trans();
 
       /* TODO : handle test and testany simcalls */
       CallType call = CallType::NONE;
@@ -443,13 +419,13 @@ void CommunicationDeterminismChecker::real_run()
         call = MC_get_call_type(req);
 
       /* Answer the request */
-      mc_model_checker->handle_simcall(cur_state->transition_);
+      mcapi::get().handle_simcall(cur_state->transition_);
       /* After this call req is no longer useful */
 
       MC_handle_comm_pattern(call, req, req_num, 0);
 
       /* Wait for requests (schedules processes) */
-      mc_model_checker->wait_for_requests();
+      mcapi::get().mc_wait_for_requests();
 
       /* Create the new expanded state */
       ++expanded_states_count_;
@@ -467,8 +443,9 @@ void CommunicationDeterminismChecker::real_run()
 
       if (visited_state == nullptr) {
         /* Get enabled actors and insert them in the interleave set of the next state */
-        for (auto& actor : mc_model_checker->get_remote_simulation().actors())
-          if (simgrid::mc::actor_is_enabled(actor.copy.get_buffer()))
+        auto actors = mcapi::get().mc_get_remote_simulation().actors();
+        for (auto& actor : actors)
+          if (mcapi::get().actor_is_enabled(actor.copy.get_buffer()->get_pid()))
             next_state->add_interleaving_set(actor.copy.get_buffer());
 
         if (dot_output != nullptr)
@@ -480,11 +457,11 @@ void CommunicationDeterminismChecker::real_run()
 
       stack_.push_back(std::move(next_state));
     } else {
-      if (stack_.size() > (std::size_t) _sg_mc_max_depth)
+      if (stack_.size() > (std::size_t)_sg_mc_max_depth)
         XBT_WARN("/!\\ Max depth reached! /!\\ ");
       else if (visited_state != nullptr)
         XBT_DEBUG("State already visited (equal to state %d), exploration stopped on this path.",
-            visited_state->original_num == -1 ? visited_state->num : visited_state->original_num);
+                  visited_state->original_num == -1 ? visited_state->num : visited_state->original_num);
       else
         XBT_DEBUG("There are no more processes to interleave. (depth %zu)", stack_.size());
 
@@ -497,8 +474,8 @@ void CommunicationDeterminismChecker::real_run()
       visited_state = nullptr;
 
       /* Check for deadlocks */
-      if (mc_model_checker->checkDeadlock()) {
-        MC_show_deadlock();
+      if (mcapi::get().mc_check_deadlock()) {
+        mcapi::get().mc_show_deadlock();
         throw simgrid::mc::DeadlockError();
       }
 
@@ -522,13 +499,13 @@ void CommunicationDeterminismChecker::real_run()
     }
   }
 
-  mc::session->log_state();
+  mcapi::get().s_log_state();
 }
 
 void CommunicationDeterminismChecker::run()
 {
   XBT_INFO("Check communication determinism");
-  mc::session->initialize();
+  mcapi::get().s_initialize();
 
   this->prepare();
   this->real_run();
index 377c3aa..4d36052 100644 (file)
 #include "src/mc/mc_private.hpp"
 #include "src/mc/mc_request.hpp"
 #include "src/mc/mc_smx.hpp"
+#include "src/mc/mc_api.hpp"
 
 #include <boost/range/algorithm.hpp>
 #include <cstring>
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_liveness, mc, "Logging specific to algorithms for liveness properties verification");
 
+using mcapi = simgrid::mc::mc_api;
+
 /********* Static functions *********/
 
 namespace simgrid {
@@ -368,7 +371,7 @@ void LivenessChecker::run()
       }
     }
 
-    smx_simcall_t req = MC_state_choose_request(current_pair->graph_state.get());
+    smx_simcall_t req = mcapi::get().mc_state_choose_request(current_pair->graph_state.get());
     int req_num       = current_pair->graph_state->transition_.argument_;
 
     if (dot_output != nullptr) {
index feb4463..c8d29ec 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();
     }
@@ -63,7 +67,7 @@ std::vector<std::string> SafetyChecker::get_textual_trace() // override
   for (auto const& state : stack_) {
     int value         = state->transition_.argument_;
     smx_simcall_t req = &state->executed_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;
 }
@@ -71,8 +75,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()
@@ -89,7 +93,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) {
@@ -110,7 +114,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) {
@@ -122,16 +126,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_;
@@ -147,9 +151,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().get_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
@@ -168,7 +173,7 @@ void SafetyChecker::run()
   }
 
   XBT_INFO("No property violation found.");
-  session->log_state();
+  mcapi::get().s_log_state();
 }
 
 void SafetyChecker::backtrack()
@@ -176,8 +181,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();
   }
 
@@ -194,19 +199,19 @@ void SafetyChecker::backtrack()
       if (req->call_ == simix::Simcall::MUTEX_LOCK || req->call_ == simix::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_);
           }
 
@@ -216,14 +221,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_);
         }
       }
     }
@@ -246,21 +251,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();
   }
 }
 
@@ -278,7 +283,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");
 
@@ -289,8 +295,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..29e895b
--- /dev/null
@@ -0,0 +1,491 @@
+#include "mc_api.hpp"
+
+#include "src/kernel/activity/MailboxImpl.hpp"
+#include "src/mc/Session.hpp"
+#include "src/mc/mc_comm_pattern.hpp"
+#include "src/mc/mc_private.hpp"
+#include "src/mc/mc_record.hpp"
+#include "src/mc/mc_smx.hpp"
+#include "src/mc/remote/RemoteSimulation.hpp"
+#include "src/mc/mc_pattern.hpp"
+
+#include <xbt/asserts.h>
+#include <xbt/log.h>
+
+#if HAVE_SMPI
+#include "src/smpi/include/smpi_request.hpp"
+#endif
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_api, mc, "Logging specific to MC Fasade APIs ");
+
+using Simcall = simgrid::simix::Simcall;
+
+namespace simgrid {
+namespace mc {
+
+/* Search an enabled transition for the given process.
+ *
+ * This can be seen as an iterator returning the next transition of the process.
+ *
+ * We only consider the processes that are both
+ *  - marked "to be interleaved" in their ActorState (controlled by the checker algorithm).
+ *  - which simcall can currently be executed (like a comm where the other partner is already known)
+ * Once we returned the last enabled transition of a process, it is marked done.
+ *
+ * Things can get muddled with the WAITANY and TESTANY simcalls, that are rewritten on the fly to a bunch of WAIT
+ * (resp TEST) transitions using the transition.argument field to remember what was the last returned sub-transition.
+ */
+static inline smx_simcall_t MC_state_choose_request_for_process(simgrid::mc::State* state, smx_actor_t actor)
+{
+  /* reset the outgoing transition */
+  simgrid::mc::ActorState* procstate = &state->actor_states_[actor->get_pid()];
+  state->transition_.pid_            = -1;
+  state->transition_.argument_       = -1;
+  state->executed_req_.call_         =  Simcall::NONE;
+
+  if (not simgrid::mc::actor_is_enabled(actor))
+    return nullptr; // Not executable in the application
+
+  smx_simcall_t req = nullptr;
+  switch (actor->simcall_.call_) {
+    case Simcall::COMM_WAITANY:
+      state->transition_.argument_ = -1;
+      while (procstate->times_considered < simcall_comm_waitany__get__count(&actor->simcall_)) {
+        if (simgrid::mc::request_is_enabled_by_idx(&actor->simcall_, procstate->times_considered)) {
+          state->transition_.argument_ = procstate->times_considered;
+          ++procstate->times_considered;
+          break;
+        }
+        ++procstate->times_considered;
+      }
+
+      if (procstate->times_considered >= simcall_comm_waitany__get__count(&actor->simcall_))
+        procstate->set_done();
+      if (state->transition_.argument_ != -1)
+        req = &actor->simcall_;
+      break;
+
+    case Simcall::COMM_TESTANY: {
+      unsigned start_count         = procstate->times_considered;
+      state->transition_.argument_ = -1;
+      while (procstate->times_considered < simcall_comm_testany__get__count(&actor->simcall_)) {
+        if (simgrid::mc::request_is_enabled_by_idx(&actor->simcall_, procstate->times_considered)) {
+          state->transition_.argument_ = procstate->times_considered;
+          ++procstate->times_considered;
+          break;
+        }
+        ++procstate->times_considered;
+      }
+
+      if (procstate->times_considered >= simcall_comm_testany__get__count(&actor->simcall_))
+        procstate->set_done();
+
+      if (state->transition_.argument_ != -1 || start_count == 0)
+        req = &actor->simcall_;
+
+      break;
+    }
+
+    case Simcall::COMM_WAIT: {
+      simgrid::mc::RemotePtr<simgrid::kernel::activity::CommImpl> remote_act =
+          remote(simcall_comm_wait__getraw__comm(&actor->simcall_));
+      simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_act;
+      mc_model_checker->get_remote_simulation().read(temp_act, remote_act);
+      const simgrid::kernel::activity::CommImpl* act = temp_act.get_buffer();
+      if (act->src_actor_.get() && act->dst_actor_.get())
+        state->transition_.argument_ = 0; // OK
+      else if (act->src_actor_.get() == nullptr && act->type_ == simgrid::kernel::activity::CommImpl::Type::READY &&
+               act->detached())
+        state->transition_.argument_ = 0; // OK
+      else
+        state->transition_.argument_ = -1; // timeout
+      procstate->set_done();
+      req = &actor->simcall_;
+      break;
+    }
+
+    case Simcall::MC_RANDOM: {
+      int min_value                = simcall_mc_random__get__min(&actor->simcall_);
+      state->transition_.argument_ = procstate->times_considered + min_value;
+      procstate->times_considered++;
+      if (state->transition_.argument_ == simcall_mc_random__get__max(&actor->simcall_))
+        procstate->set_done();
+      req = &actor->simcall_;
+      break;
+    }
+
+    default:
+      procstate->set_done();
+      state->transition_.argument_ = 0;
+      req                          = &actor->simcall_;
+      break;
+  }
+  if (not req)
+    return nullptr;
+
+  state->transition_.pid_ = actor->get_pid();
+  state->executed_req_    = *req;
+  // Fetch the data of the request and translate it:
+  state->internal_req_ = *req;
+
+  /* The waitany and testany request are transformed into a wait or test request over the corresponding communication
+   * action so it can be treated later by the dependence function. */
+  switch (req->call_) {
+    case Simcall::COMM_WAITANY: {
+      state->internal_req_.call_ = Simcall::COMM_WAIT;
+      simgrid::kernel::activity::CommImpl* remote_comm;
+      remote_comm = mc_model_checker->get_remote_simulation().read(
+          remote(simcall_comm_waitany__get__comms(req) + state->transition_.argument_));
+      mc_model_checker->get_remote_simulation().read(state->internal_comm_, remote(remote_comm));
+      simcall_comm_wait__set__comm(&state->internal_req_, state->internal_comm_.get_buffer());
+      simcall_comm_wait__set__timeout(&state->internal_req_, 0);
+      break;
+    }
+
+    case Simcall::COMM_TESTANY:
+      state->internal_req_.call_ = Simcall::COMM_TEST;
+
+      if (state->transition_.argument_ > 0) {
+        simgrid::kernel::activity::CommImpl* remote_comm = mc_model_checker->get_remote_simulation().read(
+            remote(simcall_comm_testany__get__comms(req) + state->transition_.argument_));
+        mc_model_checker->get_remote_simulation().read(state->internal_comm_, remote(remote_comm));
+      }
+
+      simcall_comm_test__set__comm(&state->internal_req_, state->internal_comm_.get_buffer());
+      simcall_comm_test__set__result(&state->internal_req_, state->transition_.argument_);
+      break;
+
+    case Simcall::COMM_WAIT:
+      mc_model_checker->get_remote_simulation().read_bytes(&state->internal_comm_, sizeof(state->internal_comm_),
+                                                           remote(simcall_comm_wait__getraw__comm(req)));
+      simcall_comm_wait__set__comm(&state->executed_req_, state->internal_comm_.get_buffer());
+      simcall_comm_wait__set__comm(&state->internal_req_, state->internal_comm_.get_buffer());
+      break;
+
+    case Simcall::COMM_TEST:
+      mc_model_checker->get_remote_simulation().read_bytes(&state->internal_comm_, sizeof(state->internal_comm_),
+                                                           remote(simcall_comm_test__getraw__comm(req)));
+      simcall_comm_test__set__comm(&state->executed_req_, state->internal_comm_.get_buffer());
+      simcall_comm_test__set__comm(&state->internal_req_, state->internal_comm_.get_buffer());
+      break;
+
+    default:
+      /* No translation needed */
+      break;
+  }
+
+  return req;
+}
+
+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);
+}
+
+unsigned long mc_api::get_maxpid() const
+{
+  return MC_smx_get_maxpid();
+}
+
+void mc_api::copy_incomplete_comm_pattern(const simgrid::mc::State* state) const
+{
+  MC_state_copy_incomplete_communications_pattern((simgrid::mc::State*)state);
+}
+
+void mc_api::copy_index_comm_pattern(const simgrid::mc::State* state) const
+{
+  MC_state_copy_index_communications_pattern((simgrid::mc::State*)state);
+}
+
+kernel::activity::CommImpl* mc_api::get_pattern_comm_addr(smx_simcall_t request) const
+{
+  auto comm_addr = simcall_comm_isend__getraw__result(request);
+  return static_cast<kernel::activity::CommImpl*>(comm_addr);
+}
+
+std::string mc_api::get_pattern_comm_rdv(void* addr) const
+{
+  Remote<kernel::activity::CommImpl> temp_synchro;
+  mc_model_checker->get_remote_simulation().read(temp_synchro, remote((simgrid::kernel::activity::CommImpl*)addr));
+  const kernel::activity::CommImpl* synchro = temp_synchro.get_buffer();
+
+  char* remote_name = mc_model_checker->get_remote_simulation().read<char*>(RemotePtr<char*>(
+      (uint64_t)(synchro->get_mailbox() ? &synchro->get_mailbox()->get_name() : &synchro->mbox_cpy->get_name())));
+  auto rdv = mc_model_checker->get_remote_simulation().read_string(RemotePtr<char>(remote_name));
+  return rdv;
+}
+
+unsigned long mc_api::get_pattern_comm_src_proc(void* addr) const
+{
+  Remote<kernel::activity::CommImpl> temp_synchro;
+  mc_model_checker->get_remote_simulation().read(temp_synchro, remote((simgrid::kernel::activity::CommImpl*)addr));
+  const kernel::activity::CommImpl* synchro = temp_synchro.get_buffer();
+  auto src_proc = mc_model_checker->get_remote_simulation().resolve_actor(mc::remote(synchro->src_actor_.get()))->get_pid();
+  return src_proc;
+}
+
+unsigned long mc_api::get_pattern_comm_dst_proc(void* addr) const
+{
+  Remote<kernel::activity::CommImpl> temp_synchro;
+  mc_model_checker->get_remote_simulation().read(temp_synchro, remote((simgrid::kernel::activity::CommImpl*)addr));
+  const kernel::activity::CommImpl* synchro = temp_synchro.get_buffer();
+  auto src_proc = mc_model_checker->get_remote_simulation().resolve_actor(mc::remote(synchro->dst_actor_.get()))->get_pid();
+  return src_proc;
+}
+
+std::vector<char> mc_api::get_pattern_comm_data(void* addr) const
+{
+  Remote<kernel::activity::CommImpl> temp_synchro;
+  mc_model_checker->get_remote_simulation().read(temp_synchro, remote((simgrid::kernel::activity::CommImpl*)addr));
+  const kernel::activity::CommImpl* synchro = temp_synchro.get_buffer();
+
+  std::vector<char> buffer {};
+  if (synchro->src_buff_ != nullptr) {
+    buffer.resize(synchro->src_buff_size_);
+    mc_model_checker->get_remote_simulation().read_bytes(buffer.data(), buffer.size(),
+                                                         remote(synchro->src_buff_));
+  }
+  return buffer;
+}
+
+std::vector<char> mc_api::get_pattern_comm_data(mc::RemotePtr<kernel::activity::CommImpl> const& comm_addr) const
+{
+  simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_comm;
+  mc_model_checker->get_remote_simulation().read(temp_comm, comm_addr);
+  const simgrid::kernel::activity::CommImpl* comm = temp_comm.get_buffer();
+  
+  std::vector<char> buffer {};
+  if (comm->src_buff_ != nullptr) {
+    buffer.resize(comm->src_buff_size_);
+    mc_model_checker->get_remote_simulation().read_bytes(buffer.data(), buffer.size(),
+                                                         remote(comm->src_buff_));
+  }
+  return buffer;
+}
+
+const char* mc_api::get_actor_host_name(smx_actor_t actor) const
+{
+  const char* host_name = MC_smx_actor_get_host_name(actor);
+  return host_name;
+}
+
+bool mc_api::check_send_request_detached(smx_simcall_t const& simcall) const
+{
+  simgrid::smpi::Request mpi_request;
+  mc_model_checker->get_remote_simulation().read(
+      &mpi_request, remote(static_cast<smpi::Request*>(simcall_comm_isend__get__data(simcall))));
+  return mpi_request.detached();
+}
+
+smx_actor_t mc_api::get_src_actor(mc::RemotePtr<kernel::activity::CommImpl> const& comm_addr) const
+{
+  simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_comm;
+  mc_model_checker->get_remote_simulation().read(temp_comm, comm_addr);
+  const simgrid::kernel::activity::CommImpl* comm = temp_comm.get_buffer();
+
+  auto src_proc = mc_model_checker->get_remote_simulation().resolve_actor(simgrid::mc::remote(comm->src_actor_.get()));
+  return src_proc;
+}
+
+smx_actor_t mc_api::get_dst_actor(mc::RemotePtr<kernel::activity::CommImpl> const& comm_addr) const
+{
+  simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_comm;
+  mc_model_checker->get_remote_simulation().read(temp_comm, comm_addr);
+  const simgrid::kernel::activity::CommImpl* comm = temp_comm.get_buffer();
+
+  auto dst_proc = mc_model_checker->get_remote_simulation().resolve_actor(simgrid::mc::remote(comm->dst_actor_.get()));
+  return dst_proc;
+}
+
+std::size_t mc_api::get_remote_heap_bytes() const
+{
+  RemoteSimulation& process = mc_model_checker->get_remote_simulation();
+  auto heap_bytes_used      = mmalloc_get_bytes_used_remote(process.get_heap()->heaplimit, process.get_malloc_info());
+  return heap_bytes_used;
+}
+
+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);
+}
+
+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
+{
+  for (auto& actor : mc_model_checker->get_remote_simulation().actors()) {
+    /* Only consider the actors that were marked as interleaving by the checker algorithm */
+    if (not state->actor_states_[actor.copy.get_buffer()->get_pid()].is_todo())
+      continue;
+
+    smx_simcall_t res = MC_state_choose_request_for_process(state, actor.copy.get_buffer());
+    if (res)
+      return res;
+  }
+  return nullptr;
+}
+
+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(simgrid::simix::Simcall kind) const
+{
+  return SIMIX_simcall_name(kind);
+}
+
+#if HAVE_SMPI
+int mc_api::get_smpi_request_tag(smx_simcall_t const& simcall, simgrid::simix::Simcall type) const
+{
+  simgrid::smpi::Request mpi_request;
+  void* simcall_data = nullptr;
+  if (type == Simcall::COMM_ISEND)
+    simcall_data = simcall_comm_isend__get__data(simcall);
+  else if (type == Simcall::COMM_IRECV)
+    simcall_data = simcall_comm_irecv__get__data(simcall);
+  mc_model_checker->get_remote_simulation().read(&mpi_request, remote(static_cast<smpi::Request*>(simcall_data)));
+  return mpi_request.tag();
+}
+#endif
+
+bool mc_api::snapshot_equal(const Snapshot* s1, const Snapshot* s2) const
+{
+  return simgrid::mc::snapshot_equal(s1, s2);
+}
+
+simgrid::mc::Snapshot* mc_api::take_snapshot(int num_state) const
+{
+  auto snapshot = new simgrid::mc::Snapshot(num_state);
+  return snapshot;
+}
+
+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..c6def81
--- /dev/null
@@ -0,0 +1,106 @@
+#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 APIs  
+  std::vector<simgrid::mc::ActorInformation>& get_actors() const;
+  bool actor_is_enabled(aid_t pid) const;
+  unsigned long get_maxpid() const;
+
+  // COMMUNICATION APIs
+  void copy_incomplete_comm_pattern(const simgrid::mc::State* state) const;
+  void copy_index_comm_pattern(const simgrid::mc::State* state) const;
+  kernel::activity::CommImpl* get_pattern_comm_addr(smx_simcall_t request) const;
+  std::string get_pattern_comm_rdv(void* addr) const;
+  unsigned long get_pattern_comm_src_proc(void* addr) const;
+  unsigned long get_pattern_comm_dst_proc(void* addr) const;
+  std::vector<char> get_pattern_comm_data(void* addr) const;
+  std::vector<char> get_pattern_comm_data(mc::RemotePtr<kernel::activity::CommImpl> const& comm_addr) const;
+  const char* get_actor_host_name(smx_actor_t actor) const;
+  bool check_send_request_detached(smx_simcall_t const& simcall) const;
+  smx_actor_t get_src_actor(mc::RemotePtr<kernel::activity::CommImpl> const& comm_addr) const;
+  smx_actor_t get_dst_actor(mc::RemotePtr<kernel::activity::CommImpl> const& comm_addr) const;
+
+  // REMOTE APIs
+  std::size_t get_remote_heap_bytes() const;
+
+  // MODEL CHECKER APIs
+  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;
+  void mc_dump_record_path() const;
+  smx_simcall_t mc_state_choose_request(simgrid::mc::State* state) const;
+
+  // SIMCALL APIs
+  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(simgrid::simix::Simcall kind) const;
+  #if HAVE_SMPI
+  int get_smpi_request_tag(smx_simcall_t const& simcall, simgrid::simix::Simcall type) const;
+  #endif
+
+  // SNAPSHOT APIs
+  bool snapshot_equal(const Snapshot* s1, const Snapshot* s2) const;
+  simgrid::mc::Snapshot* take_snapshot(int num_state) const;
+
+  // SESSION APIs
+  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 eba010b..ab35bd1 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_;
diff --git a/src/mc/mc_pattern.hpp b/src/mc/mc_pattern.hpp
new file mode 100644 (file)
index 0000000..6909e11
--- /dev/null
@@ -0,0 +1,94 @@
+/* Copyright (c) 2007-2020. The SimGrid Team. All rights reserved.          */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef SIMGRID_MC_PATTERN_H
+#define SIMGRID_MC_PATTERN_H
+
+#include "src/kernel/activity/CommImpl.hpp"
+
+namespace simgrid {
+namespace mc {
+
+enum class PatternCommunicationType {
+  none    = 0,
+  send    = 1,
+  receive = 2,
+};
+
+class PatternCommunication {
+public:
+  int num = 0;
+  simgrid::kernel::activity::CommImpl* comm_addr;
+  PatternCommunicationType type = PatternCommunicationType::send;
+  unsigned long src_proc        = 0;
+  unsigned long dst_proc        = 0;
+  const char* src_host          = nullptr;
+  const char* dst_host          = nullptr;
+  std::string rdv;
+  std::vector<char> data;
+  int tag   = 0;
+  int index = 0;
+
+  PatternCommunication() { std::memset(&comm_addr, 0, sizeof(comm_addr)); }
+
+  PatternCommunication dup() const
+  {
+    simgrid::mc::PatternCommunication res;
+    // num?
+    res.comm_addr = this->comm_addr;
+    res.type      = this->type;
+    // src_proc?
+    // dst_proc?
+    res.dst_proc = this->dst_proc;
+    res.dst_host = this->dst_host;
+    res.rdv      = this->rdv;
+    res.data     = this->data;
+    // tag?
+    res.index = this->index;
+    return res;
+  }
+};
+
+/* On every state, each actor has an entry of the following type.
+ * This represents both the actor and its transition because
+ *   an actor cannot have more than one enabled transition at a given time.
+ */
+class ActorState {
+  /* Possible exploration status of an actor transition in a state.
+   * Either the checker did not consider the transition, or it was considered and still to do, or considered and done.
+   */
+  enum class InterleavingType {
+    /** This actor transition is not considered by the checker (yet?) */
+    disabled = 0,
+    /** The checker algorithm decided that this actor transitions should be done at some point */
+    todo,
+    /** The checker algorithm decided that this should be done, but it was done in the meanwhile */
+    done,
+  };
+
+  /** Exploration control information */
+  InterleavingType state = InterleavingType::disabled;
+
+public:
+  /** Number of times that the process was considered to be executed */
+  // TODO, make this private
+  unsigned int times_considered = 0;
+
+  bool is_disabled() const { return this->state == InterleavingType::disabled; }
+  bool is_done() const { return this->state == InterleavingType::done; }
+  bool is_todo() const { return this->state == InterleavingType::todo; }
+  /** Mark that we should try executing this process at some point in the future of the checker algorithm */
+  void consider()
+  {
+    this->state            = InterleavingType::todo;
+    this->times_considered = 0;
+  }
+  void set_done() { this->state = InterleavingType::done; }
+};
+
+} // namespace mc
+} // namespace simgrid
+
+#endif
index de4158b..c078742 100644 (file)
@@ -4,14 +4,13 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include "src/mc/mc_state.hpp"
-#include "src/mc/mc_comm_pattern.hpp"
 #include "src/mc/mc_config.hpp"
-#include "src/mc/mc_request.hpp"
-#include "src/mc/mc_smx.hpp"
+#include "src/mc/mc_api.hpp"
 
 #include <boost/range/algorithm.hpp>
 
 using simgrid::mc::remote;
+using mcapi = simgrid::mc::mc_api;
 
 namespace simgrid {
 namespace mc {
@@ -19,14 +18,15 @@ namespace mc {
 State::State(unsigned long state_number) : num_(state_number)
 {
   this->internal_comm_.clear();
-
-  actor_states_.resize(MC_smx_get_maxpid());
+  auto maxpid = mcapi::get().get_maxpid();
+  actor_states_.resize(maxpid);
   /* Stateful model checking */
   if ((_sg_mc_checkpoint > 0 && (state_number % _sg_mc_checkpoint == 0)) || _sg_mc_termination) {
-    system_state_ = std::make_shared<simgrid::mc::Snapshot>(num_);
+    auto snapshot_ptr = mcapi::get().take_snapshot(num_);
+    system_state_ = std::shared_ptr<simgrid::mc::Snapshot>(snapshot_ptr);
     if (_sg_mc_comms_determinism || _sg_mc_send_determinism) {
-      MC_state_copy_incomplete_communications_pattern(this);
-      MC_state_copy_index_communications_pattern(this);
+      mcapi::get().copy_incomplete_comm_pattern(this);
+      mcapi::get().copy_index_comm_pattern(this);
     }
   }
 }
@@ -43,173 +43,3 @@ Transition State::get_transition() const
 
 }
 }
-
-/* Search an enabled transition for the given process.
- *
- * This can be seen as an iterator returning the next transition of the process.
- *
- * We only consider the processes that are both
- *  - marked "to be interleaved" in their ActorState (controlled by the checker algorithm).
- *  - which simcall can currently be executed (like a comm where the other partner is already known)
- * Once we returned the last enabled transition of a process, it is marked done.
- *
- * Things can get muddled with the WAITANY and TESTANY simcalls, that are rewritten on the fly to a bunch of WAIT
- * (resp TEST) transitions using the transition.argument field to remember what was the last returned sub-transition.
- */
-static inline smx_simcall_t MC_state_choose_request_for_process(simgrid::mc::State* state, smx_actor_t actor)
-{
-  using simgrid::simix::Simcall;
-
-  /* reset the outgoing transition */
-  simgrid::mc::ActorState* procstate   = &state->actor_states_[actor->get_pid()];
-  state->transition_.pid_              = -1;
-  state->transition_.argument_         = -1;
-  state->executed_req_.call_           = Simcall::NONE;
-
-  if (not simgrid::mc::actor_is_enabled(actor))
-    return nullptr; // Not executable in the application
-
-  smx_simcall_t req = nullptr;
-  switch (actor->simcall_.call_) {
-    case Simcall::COMM_WAITANY:
-      state->transition_.argument_ = -1;
-      while (procstate->times_considered < simcall_comm_waitany__get__count(&actor->simcall_)) {
-        if (simgrid::mc::request_is_enabled_by_idx(&actor->simcall_, procstate->times_considered)) {
-          state->transition_.argument_ = procstate->times_considered;
-          ++procstate->times_considered;
-          break;
-        }
-        ++procstate->times_considered;
-      }
-
-      if (procstate->times_considered >= simcall_comm_waitany__get__count(&actor->simcall_))
-        procstate->set_done();
-      if (state->transition_.argument_ != -1)
-        req = &actor->simcall_;
-      break;
-
-    case Simcall::COMM_TESTANY: {
-      unsigned start_count       = procstate->times_considered;
-      state->transition_.argument_ = -1;
-      while (procstate->times_considered < simcall_comm_testany__get__count(&actor->simcall_)) {
-        if (simgrid::mc::request_is_enabled_by_idx(&actor->simcall_, procstate->times_considered)) {
-          state->transition_.argument_ = procstate->times_considered;
-          ++procstate->times_considered;
-          break;
-        }
-        ++procstate->times_considered;
-      }
-
-      if (procstate->times_considered >= simcall_comm_testany__get__count(&actor->simcall_))
-        procstate->set_done();
-
-      if (state->transition_.argument_ != -1 || start_count == 0)
-        req = &actor->simcall_;
-
-      break;
-    }
-
-    case Simcall::COMM_WAIT: {
-      simgrid::mc::RemotePtr<simgrid::kernel::activity::CommImpl> remote_act =
-          remote(simcall_comm_wait__getraw__comm(&actor->simcall_));
-      simgrid::mc::Remote<simgrid::kernel::activity::CommImpl> temp_act;
-      mc_model_checker->get_remote_simulation().read(temp_act, remote_act);
-      const simgrid::kernel::activity::CommImpl* act = temp_act.get_buffer();
-      if (act->src_actor_.get() && act->dst_actor_.get())
-        state->transition_.argument_ = 0; // OK
-      else if (act->src_actor_.get() == nullptr && act->type_ == simgrid::kernel::activity::CommImpl::Type::READY &&
-               act->detached())
-        state->transition_.argument_ = 0; // OK
-      else
-        state->transition_.argument_ = -1; // timeout
-      procstate->set_done();
-      req = &actor->simcall_;
-      break;
-    }
-
-    case Simcall::MC_RANDOM: {
-      int min_value                = simcall_mc_random__get__min(&actor->simcall_);
-      state->transition_.argument_ = procstate->times_considered + min_value;
-      procstate->times_considered++;
-      if (state->transition_.argument_ == simcall_mc_random__get__max(&actor->simcall_))
-        procstate->set_done();
-      req = &actor->simcall_;
-      break;
-    }
-
-    default:
-      procstate->set_done();
-      state->transition_.argument_ = 0;
-      req                          = &actor->simcall_;
-      break;
-  }
-  if (not req)
-    return nullptr;
-
-  state->transition_.pid_ = actor->get_pid();
-  state->executed_req_    = *req;
-  // Fetch the data of the request and translate it:
-  state->internal_req_ = *req;
-
-  /* The waitany and testany request are transformed into a wait or test request over the corresponding communication
-   * action so it can be treated later by the dependence function. */
-  switch (req->call_) {
-    case Simcall::COMM_WAITANY: {
-      state->internal_req_.call_ = Simcall::COMM_WAIT;
-      simgrid::kernel::activity::CommImpl* remote_comm;
-      remote_comm = mc_model_checker->get_remote_simulation().read(
-          remote(simcall_comm_waitany__get__comms(req) + state->transition_.argument_));
-      mc_model_checker->get_remote_simulation().read(state->internal_comm_, remote(remote_comm));
-      simcall_comm_wait__set__comm(&state->internal_req_, state->internal_comm_.get_buffer());
-      simcall_comm_wait__set__timeout(&state->internal_req_, 0);
-      break;
-    }
-
-    case Simcall::COMM_TESTANY:
-      state->internal_req_.call_ = Simcall::COMM_TEST;
-
-      if (state->transition_.argument_ > 0) {
-        simgrid::kernel::activity::CommImpl* remote_comm = mc_model_checker->get_remote_simulation().read(
-            remote(simcall_comm_testany__get__comms(req) + state->transition_.argument_));
-        mc_model_checker->get_remote_simulation().read(state->internal_comm_, remote(remote_comm));
-      }
-
-      simcall_comm_test__set__comm(&state->internal_req_, state->internal_comm_.get_buffer());
-      simcall_comm_test__set__result(&state->internal_req_, state->transition_.argument_);
-      break;
-
-    case Simcall::COMM_WAIT:
-      mc_model_checker->get_remote_simulation().read_bytes(&state->internal_comm_, sizeof(state->internal_comm_),
-                                                           remote(simcall_comm_wait__getraw__comm(req)));
-      simcall_comm_wait__set__comm(&state->executed_req_, state->internal_comm_.get_buffer());
-      simcall_comm_wait__set__comm(&state->internal_req_, state->internal_comm_.get_buffer());
-      break;
-
-    case Simcall::COMM_TEST:
-      mc_model_checker->get_remote_simulation().read_bytes(&state->internal_comm_, sizeof(state->internal_comm_),
-                                                           remote(simcall_comm_test__getraw__comm(req)));
-      simcall_comm_test__set__comm(&state->executed_req_, state->internal_comm_.get_buffer());
-      simcall_comm_test__set__comm(&state->internal_req_, state->internal_comm_.get_buffer());
-      break;
-
-    default:
-      /* No translation needed */
-      break;
-  }
-
-  return req;
-}
-
-smx_simcall_t MC_state_choose_request(simgrid::mc::State* state)
-{
-  for (auto& actor : mc_model_checker->get_remote_simulation().actors()) {
-    /* Only consider the actors that were marked as interleaving by the checker algorithm */
-    if (not state->actor_states_[actor.copy.get_buffer()->get_pid()].is_todo())
-      continue;
-
-    smx_simcall_t res = MC_state_choose_request_for_process(state, actor.copy.get_buffer());
-    if (res)
-      return res;
-  }
-  return nullptr;
-}
index 54736a5..2f347e3 100644 (file)
@@ -6,90 +6,13 @@
 #ifndef SIMGRID_MC_STATE_HPP
 #define SIMGRID_MC_STATE_HPP
 
-#include "src/kernel/activity/CommImpl.hpp"
 #include "src/mc/Transition.hpp"
 #include "src/mc/sosp/Snapshot.hpp"
+#include "src/mc/mc_pattern.hpp"
 
 namespace simgrid {
 namespace mc {
 
-enum class PatternCommunicationType {
-  none    = 0,
-  send    = 1,
-  receive = 2,
-};
-
-class PatternCommunication {
-public:
-  int num = 0;
-  simgrid::kernel::activity::CommImpl* comm_addr;
-  PatternCommunicationType type = PatternCommunicationType::send;
-  unsigned long src_proc        = 0;
-  unsigned long dst_proc        = 0;
-  const char* src_host          = nullptr;
-  const char* dst_host          = nullptr;
-  std::string rdv;
-  std::vector<char> data;
-  int tag   = 0;
-  int index = 0;
-
-  PatternCommunication() { std::memset(&comm_addr, 0, sizeof(comm_addr)); }
-
-  PatternCommunication dup() const
-  {
-    simgrid::mc::PatternCommunication res;
-    // num?
-    res.comm_addr = this->comm_addr;
-    res.type      = this->type;
-    // src_proc?
-    // dst_proc?
-    res.dst_proc = this->dst_proc;
-    res.dst_host = this->dst_host;
-    res.rdv      = this->rdv;
-    res.data     = this->data;
-    // tag?
-    res.index = this->index;
-    return res;
-  }
-};
-
-/* On every state, each actor has an entry of the following type.
- * This represents both the actor and its transition because
- *   an actor cannot have more than one enabled transition at a given time.
- */
-class ActorState {
-  /* Possible exploration status of an actor transition in a state.
-   * Either the checker did not consider the transition, or it was considered and still to do, or considered and done.
-   */
-  enum class InterleavingType {
-    /** This actor transition is not considered by the checker (yet?) */
-    disabled = 0,
-    /** The checker algorithm decided that this actor transitions should be done at some point */
-    todo,
-    /** The checker algorithm decided that this should be done, but it was done in the meanwhile */
-    done,
-  };
-
-  /** Exploration control information */
-  InterleavingType state = InterleavingType::disabled;
-
-public:
-  /** Number of times that the process was considered to be executed */
-  // TODO, make this private
-  unsigned int times_considered = 0;
-
-  bool is_disabled() const { return this->state == InterleavingType::disabled; }
-  bool is_done() const { return this->state == InterleavingType::done; }
-  bool is_todo() const { return this->state == InterleavingType::todo; }
-  /** Mark that we should try executing this process at some point in the future of the checker algorithm */
-  void consider()
-  {
-    this->state            = InterleavingType::todo;
-    this->times_considered = 0;
-  }
-  void set_done() { this->state = InterleavingType::done; }
-};
-
 /* A node in the exploration graph (kind-of) */
 class XBT_PRIVATE State {
 public:
@@ -133,6 +56,4 @@ public:
 }
 }
 
-XBT_PRIVATE smx_simcall_t MC_state_choose_request(simgrid::mc::State* state);
-
 #endif
index 1062af7..27bf5f8 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
@@ -660,7 +660,10 @@ set(MC_SRC
   src/mc/Session.hpp
   src/mc/mc_comm_pattern.cpp
   src/mc/mc_comm_pattern.hpp
+  src/mc/mc_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