]> AND Public Git Repository - simgrid.git/blobdiff - src/mc/remote/AppSide.cpp
Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add first batch of tests for History class
[simgrid.git] / src / mc / remote / AppSide.cpp
index fe481ca3d865f0cd1eeacf4e11cf9a4021c363e8..9db7806dc8939649594facdc1a5949a39294e252 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2022. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2015-2023. 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. */
@@ -15,9 +15,9 @@
 #if HAVE_SMPI
 #include "src/smpi/include/private.hpp"
 #endif
-#include "xbt/coverage.h"
+#include "src/sthread/sthread.h"
+#include "src/xbt/coverage.h"
 #include "xbt/str.h"
-#include "xbt/xbt_modinter.h" /* mmalloc_preinit to get the default mmalloc arena address */
 #include <simgrid/modelchecker.h>
 
 #include <cerrno>
@@ -25,6 +25,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <memory>
+#include <numeric>
 #include <sys/ptrace.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -153,25 +154,74 @@ void AppSide::handle_finalize(const s_mc_message_int_t* msg) const
 void AppSide::handle_actors_status() const
 {
   auto const& actor_list = kernel::EngineImpl::get_instance()->get_actor_list();
-  int count              = actor_list.size();
-  XBT_DEBUG("Serialize the actors to answer ACTORS_STATUS from the checker. %d actors to go.", count);
+  const int num_actors   = actor_list.size();
+  XBT_DEBUG("Serialize the actors to answer ACTORS_STATUS from the checker. %d actors to go.", num_actors);
+
+  std::vector<s_mc_message_actors_status_one_t> status(num_actors);
+  int i                 = 0;
+  int total_transitions = 0;
 
-  struct s_mc_message_actors_status_answer_t answer {
-    MessageType::ACTORS_STATUS_REPLY, count
-  };
-  std::vector<s_mc_message_actors_status_one_t> status(count);
-  int i = 0;
   for (auto const& [aid, actor] : actor_list) {
     status[i].aid            = aid;
     status[i].enabled        = mc::actor_is_enabled(actor);
     status[i].max_considered = actor->simcall_.observer_->get_max_consider();
+    status[i].n_transitions  = mc::actor_is_enabled(actor) ? status[i].max_considered : 0;
+    total_transitions += status[i].n_transitions;
     i++;
   }
+
+  struct s_mc_message_actors_status_answer_t answer {
+    MessageType::ACTORS_STATUS_REPLY, num_actors, total_transitions
+  };
+
   xbt_assert(channel_.send(answer) == 0, "Could not send ACTORS_STATUS_REPLY msg");
   if (answer.count > 0) {
     size_t size = status.size() * sizeof(s_mc_message_actors_status_one_t);
     xbt_assert(channel_.send(status.data(), size) == 0, "Could not send ACTORS_STATUS_REPLY data");
   }
+
+  // Serialize each transition to describe what each actor is doing
+  if (total_transitions > 0) {
+    std::vector<s_mc_message_simcall_probe_one_t> probes(total_transitions);
+    auto probes_iter = probes.begin();
+
+    for (const auto& actor_status : status) {
+      if (not actor_status.enabled)
+        continue;
+
+      const auto& actor        = actor_list.at(actor_status.aid);
+      const int max_considered = actor_status.max_considered;
+
+      for (int times_considered = 0; times_considered < max_considered; times_considered++, probes_iter++) {
+        std::stringstream stream;
+        s_mc_message_simcall_probe_one_t& probe = *probes_iter;
+
+        if (actor->simcall_.observer_ != nullptr) {
+          actor->simcall_.observer_->prepare(times_considered);
+          actor->simcall_.observer_->serialize(stream);
+        } else {
+          stream << (short)mc::Transition::Type::UNKNOWN;
+        }
+
+        std::string str = stream.str();
+        xbt_assert(str.size() + 1 <= probe.buffer.size(),
+                   "The serialized transition is too large for the buffer. Please fix the code.");
+        strncpy(probe.buffer.data(), str.c_str(), probe.buffer.size() - 1);
+        probe.buffer.back() = '\0';
+      }
+      // NOTE: We do NOT need to reset `times_considered` for each actor's
+      // simcall observer here to the "original" value (i.e. the value BEFORE
+      // multiple prepare() calls were made for serialization purposes) since
+      // each SIMCALL_EXECUTE provides a `times_considered` to be used to prepare
+      // the transition before execution.
+    }
+    XBT_DEBUG("Deliver ACTOR_TRANSITION_PROBE payload");
+
+    for (const auto& probe : probes) {
+      size_t size = sizeof(s_mc_message_simcall_probe_one_t);
+      xbt_assert(channel_.send(&probe, size) == 0, "Could not send ACTOR_TRANSITION_PROBE payload (%zu bytes)", size);
+    }
+  }
 }
 
 #define assert_msg_size(_name_, _type_)                                                                                \
@@ -187,6 +237,8 @@ void AppSide::handle_messages() const
     ssize_t received_size = channel_.receive(message_buffer.data(), message_buffer.size());
 
     xbt_assert(received_size >= 0, "Could not receive commands from the model-checker");
+    xbt_assert(static_cast<size_t>(received_size) >= sizeof(s_mc_message_t), "Cannot handle short message (size=%zd)",
+               received_size);
 
     const s_mc_message_t* message = (s_mc_message_t*)message_buffer.data();
     switch (message->type) {
@@ -227,7 +279,9 @@ void AppSide::main_loop() const
   MC_ignore_heap(simgrid::mc::processes_time.data(),
                  simgrid::mc::processes_time.size() * sizeof(simgrid::mc::processes_time[0]));
 
+  sthread_disable();
   coverage_checkpoint();
+  sthread_enable();
   while (true) {
     simgrid::mc::execute_actors();
     xbt_assert(channel_.send(MessageType::WAITING) == 0, "Could not send WAITING message to model-checker");