Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of framagit.org:simgrid/simgrid
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Wed, 10 May 2023 21:22:28 +0000 (23:22 +0200)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Wed, 10 May 2023 21:22:28 +0000 (23:22 +0200)
21 files changed:
ChangeLog
examples/cpp/CMakeLists.txt
examples/cpp/synchro-mutex/s4u-mc-synchro-mutex-stateful.tesh [new file with mode: 0644]
include/simgrid/s4u/Link.hpp
src/kernel/lmm/System.cpp
src/kernel/lmm/System.hpp
src/kernel/resource/Resource.hpp
src/mc/explo/DFSExplorer.cpp
src/mc/explo/DFSExplorer.hpp
src/mc/explo/Exploration.cpp
src/mc/explo/Exploration.hpp
src/mc/explo/LivenessChecker.cpp
src/mc/explo/LivenessChecker.hpp
src/mc/explo/UdporChecker.cpp
src/mc/explo/UdporChecker.hpp
src/mc/mc_record.cpp
src/mc/mc_record.hpp
src/plugins/link_energy.cpp
src/plugins/link_energy_wifi.cpp
src/plugins/link_load.cpp
src/s4u/s4u_Link.cpp

index 345aacc..d68448e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -19,6 +19,7 @@ S4U:
    are fullfiled. If it cannot be started right away, it will start as soon as it becomes
    possible.
  - Allow to set a concurrency limit on disks and hosts, as it was already the case for links.
+ - Rename Link::get_usage() to Link::get_load() for consistency with Host::
 
 New plugin: Operation
  - Operations are designed to represent workflows, i.e, graphs of repeatable Activities.
index c0eca33..9c06ea0 100644 (file)
@@ -47,6 +47,14 @@ if(SIMGRID_HAVE_STATEFUL_MC)
     add_dependencies(tests-mc s4u-mc-bugged1-liveness-cleaner-off)
   endif()
 
+  ADD_TESH(s4u-mc-synchro-mutex-stateful
+     --setenv bindir=${CMAKE_CURRENT_BINARY_DIR}/synchro-mutex
+     --setenv libdir=${CMAKE_BINARY_DIR}/lib
+     --setenv platfdir=${CMAKE_HOME_DIRECTORY}/examples/platforms
+     --setenv srcdir=${CMAKE_CURRENT_SOURCE_DIR}/synchro-mutex
+     --cd ${CMAKE_CURRENT_SOURCE_DIR}/synchro-mutex
+      ${CMAKE_HOME_DIRECTORY}/examples/cpp/synchro-mutex/s4u-mc-synchro-mutex-stateful.tesh)
+
   # Model-checking liveness
   if(HAVE_UCONTEXT_CONTEXTS AND SIMGRID_PROCESSOR_x86_64)
     # liveness model-checking works only on 64bits (for now ...)
diff --git a/examples/cpp/synchro-mutex/s4u-mc-synchro-mutex-stateful.tesh b/examples/cpp/synchro-mutex/s4u-mc-synchro-mutex-stateful.tesh
new file mode 100644 (file)
index 0000000..3d1e75d
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/env tesh
+
+p This file tests the cfg=model-check/checkpoint option for DFS explorer
+
+$ $VALGRIND_NO_TRACE_CHILDREN ${bindir:=.}/../../../bin/simgrid-mc --cfg=model-check/checkpoint:5 --cfg=model-check/sleep-set:true -- ${bindir:=.}/s4u-synchro-mutex --cfg=actors:2 --log=s4u_test.thres:critical
+> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check/checkpoint' to '5'
+> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check/sleep-set' to 'true'
+> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'actors' to '2'
+> [0.000000] [mc_dfs/INFO] Start a DFS exploration. Reduction is: dpor.
+> [0.000000] [mc_dfs/INFO] DFS exploration ended. 130 unique states visited; 27 backtracks (209 transition replays, 52 states visited overall)
+
+p The stats without checkpoints is:               130 unique states visited; 27 backtracks (308 transition replays, 151 states visited overall)
+p But it runs much faster (0.6 sec vs. 1.6 sec), damn slow checkpointing code.
index 2195c69..ca87ddc 100644 (file)
@@ -130,7 +130,14 @@ public:
   void set_host_wifi_rate(const s4u::Host* host, int level) const;
 
   /** @brief Returns the current load (in bytes per second) */
-  double get_usage() const;
+  double get_load() const;
+
+#ifndef DOXYGEN
+  XBT_ATTRIB_DEPRECATED_v337("Please use get_load() instead") double get_usage() const
+  {
+    return get_load();
+  }
+#endif
 
   /** @brief Check if the Link is used (at least one flow uses the link) */
   bool is_used() const;
index 75eb88a..cebcb96 100644 (file)
@@ -747,7 +747,7 @@ void System::remove_all_modified_cnst_set()
  * If the resource is not shared (ie in FATPIPE mode), then the load is the max (not the sum)
  * of all resource usages located on this resource.
  */
-double Constraint::get_usage() const
+double Constraint::get_load() const
 {
   double result              = 0.0;
   if (sharing_policy_ != SharingPolicy::FATPIPE) {
index bfbe7d2..25fa550 100644 (file)
@@ -220,8 +220,8 @@ public:
   /** @brief Check how a constraint is shared  */
   SharingPolicy get_sharing_policy() const { return sharing_policy_; }
 
-  /** @brief Get the usage of the constraint after the last lmm solve */
-  double get_usage() const;
+  /** @brief Get the load of the constraint after the last lmm solve */
+  double get_load() const;
 
   /** @brief Sets the concurrency limit for this constraint */
   void set_concurrency_limit(int limit)
index 6c864e3..9e2f284 100644 (file)
@@ -115,7 +115,7 @@ public:
   /** @brief returns the current load due to activities (in flops per second, byte per second or similar)
    *
    * The load due to external usages modeled by profile files is ignored.*/
-  virtual double get_load() const { return constraint_->get_usage(); }
+  virtual double get_load() const { return constraint_->get_load(); }
 
   bool is_used() const override { return model_->get_maxmin_system()->constraint_used(constraint_); }
 };
index 0130455..a8faec6 100644 (file)
@@ -69,21 +69,14 @@ void DFSExplorer::check_non_termination(const State* current_state)
 RecordTrace DFSExplorer::get_record_trace() // override
 {
   RecordTrace res;
-  for (auto const& transition : stack_.back()->get_recipe())
-    res.push_back(transition);
-  res.push_back(stack_.back()->get_transition_out().get());
-  return res;
-}
 
-std::vector<std::string> DFSExplorer::get_textual_trace() // override
-{
-  std::vector<std::string> trace;
-  for (auto const& transition : stack_.back()->get_recipe()) {
-    trace.push_back(xbt::string_printf("%ld: %s", transition->aid_, transition->to_string().c_str()));
-  }
   if (const auto trans = stack_.back()->get_transition_out(); trans != nullptr)
-    trace.push_back(xbt::string_printf("%ld: %s", trans->aid_, trans->to_string().c_str()));
-  return trace;
+    res.push_back(trans.get());
+  for (const auto* state = stack_.back().get(); state != nullptr; state = state->get_parent_state().get())
+    if (state->get_transition_in() != nullptr)
+      res.push_front(state->get_transition_in().get());
+
+  return res;
 }
 
 void DFSExplorer::restore_stack(std::shared_ptr<State> state)
@@ -343,20 +336,48 @@ void DFSExplorer::backtrack()
   }
 #endif
 
+  // Search how to restore the backtracking point
+  State* init_state = nullptr;
+  std::deque<Transition*> replay_recipe;
+  for (auto* s = backtracking_point.get(); s != nullptr; s = s->get_parent_state().get()) {
+#if SIMGRID_HAVE_STATEFUL_MC
+    if (s->get_system_state() != nullptr) { // Found a state that I can restore
+      init_state = s;
+      break;
+    }
+#endif
+    if (s->get_transition_in() != nullptr) // The root has no transition_in
+      replay_recipe.push_front(s->get_transition_in().get());
+  }
+
+  // Restore the init_state, if any
+  if (init_state != nullptr) {
+#if SIMGRID_HAVE_STATEFUL_MC
+    const auto* system_state = init_state->get_system_state();
+    system_state->restore(*get_remote_app().get_remote_process_memory());
+    on_restore_system_state_signal(init_state, get_remote_app());
+#endif
+  } else { // Restore the initial state if no intermediate state was found
+    get_remote_app().restore_initial_state();
+    on_restore_initial_state_signal(get_remote_app());
+  }
+
   /* if no snapshot, we need to restore the initial state and replay the transitions */
-  get_remote_app().restore_initial_state();
-  on_restore_initial_state_signal(get_remote_app());
   /* Traverse the stack from the state at position start and re-execute the transitions */
-  for (auto& state : backtracking_point->get_recipe()) {
-    state->replay(get_remote_app());
-    on_transition_replay_signal(state, get_remote_app());
+  for (auto& transition : replay_recipe) {
+    transition->replay(get_remote_app());
+    on_transition_replay_signal(transition, get_remote_app());
     visited_states_count_++;
   }
   this->restore_stack(backtracking_point);
 }
 
 DFSExplorer::DFSExplorer(const std::vector<char*>& args, bool with_dpor, bool need_memory_info)
-    : Exploration(args, need_memory_info || _sg_mc_termination)
+    : Exploration(args, need_memory_info || _sg_mc_termination
+#if SIMGRID_HAVE_STATEFUL_MC
+                            || _sg_mc_checkpoint > 0
+#endif
+      )
 {
   if (with_dpor)
     reduction_mode_ = ReductionMode::dpor;
index 6510cfe..27194a8 100644 (file)
@@ -46,7 +46,6 @@ public:
   explicit DFSExplorer(const std::vector<char*>& args, bool with_dpor, bool need_memory_info = false);
   void run() override;
   RecordTrace get_record_trace() override;
-  std::vector<std::string> get_textual_trace() override;
   void log_state() override;
 
   /** Called once when the exploration starts */
index 7a77588..8bf0110 100644 (file)
@@ -8,6 +8,7 @@
 #include "src/mc/mc_environ.h"
 #include "src/mc/mc_exit.hpp"
 #include "src/mc/mc_private.hpp"
+#include "xbt/string.hpp"
 
 #if SIMGRID_HAVE_STATEFUL_MC
 #include "src/mc/sosp/RemoteProcessMemory.hpp"
@@ -81,6 +82,15 @@ static const char* signal_name(int status)
       return strsignal(WTERMSIG(status));
   }
 }
+
+std::vector<std::string> Exploration::get_textual_trace()
+{
+  std::vector<std::string> trace;
+  for (auto const& transition : get_record_trace())
+    trace.push_back(xbt::string_printf("%ld: %s", transition->aid_, transition->to_string().c_str()));
+  return trace;
+}
+
 XBT_ATTRIB_NORETURN void Exploration::report_crash(int status)
 {
   XBT_INFO("**************************");
index a164bf0..824adcd 100644 (file)
@@ -55,13 +55,11 @@ public:
    * to get and display information about the current state of the
    * model-checking algorithm: */
 
-  /** Show the current trace/stack
-   *
-   *  Could this be handled in the Session/ModelChecker instead? */
+  /** Retrieve the current stack to build an execution trace */
   virtual RecordTrace get_record_trace() = 0;
 
   /** Generate a textual execution trace of the simulated application */
-  virtual std::vector<std::string> get_textual_trace() = 0;
+  std::vector<std::string> get_textual_trace();
 
   /** Log additional information about the state of the model-checker */
   virtual void log_state();
index e254683..3d60ef9 100644 (file)
@@ -258,7 +258,8 @@ RecordTrace LivenessChecker::get_record_trace() // override
 {
   RecordTrace res;
   for (std::shared_ptr<Pair> const& pair : exploration_stack_)
-    res.push_back(pair->app_state_->get_transition_out().get());
+    if (pair->app_state_->get_transition_out() != nullptr)
+      res.push_back(pair->app_state_->get_transition_out().get());
   return res;
 }
 
@@ -285,16 +286,6 @@ void LivenessChecker::show_acceptance_cycle(std::size_t depth)
   XBT_INFO("Counter-example depth: %zu", depth);
 }
 
-std::vector<std::string> LivenessChecker::get_textual_trace() // override
-{
-  std::vector<std::string> trace;
-  for (std::shared_ptr<Pair> const& pair : exploration_stack_)
-    if (pair->app_state_->get_transition_out() != nullptr)
-      trace.push_back(pair->app_state_->get_transition_out()->to_string());
-
-  return trace;
-}
-
 std::shared_ptr<Pair> LivenessChecker::create_pair(const Pair* current_pair, xbt_automaton_state_t state,
                                                    std::shared_ptr<const std::vector<int>> propositions)
 {
index 532f639..baed48e 100644 (file)
@@ -56,7 +56,6 @@ public:
 
   void run() override;
   RecordTrace get_record_trace() override;
-  std::vector<std::string> get_textual_trace() override;
   void log_state() override;
 
 private:
index 6d913b2..e367890 100644 (file)
@@ -325,16 +325,6 @@ RecordTrace UdporChecker::get_record_trace()
   return res;
 }
 
-std::vector<std::string> UdporChecker::get_textual_trace()
-{
-  std::vector<std::string> trace;
-  for (auto const& state : state_stack) {
-    const auto t = state->get_transition_out();
-    trace.push_back(xbt::string_printf("%ld: %s", t->aid_, t->to_string().c_str()));
-  }
-  return trace;
-}
-
 } // namespace simgrid::mc::udpor
 
 namespace simgrid::mc {
index 6706d2b..0e23ab0 100644 (file)
@@ -38,7 +38,6 @@ public:
 
   void run() override;
   RecordTrace get_record_trace() override;
-  std::vector<std::string> get_textual_trace() override;
   std::unique_ptr<State> get_current_state() { return std::make_unique<State>(get_remote_app()); }
 
 private:
index f639107..63d9fc0 100644 (file)
@@ -51,7 +51,7 @@ void RecordTrace::replay() const
   const auto& actor_list = engine->get_actor_list();
   if (actor_list.empty()) {
     XBT_INFO("The replay of the trace is complete. The application is terminating.");
-  } else if (std::none_of(begin(actor_list), end(actor_list),
+  } else if (std::none_of(std::begin(actor_list), std::end(actor_list),
                           [](const auto& kv) { return mc::actor_is_enabled(kv.second); })) {
     XBT_INFO("The replay of the trace is complete. DEADLOCK detected.");
     engine->display_all_actor_status();
index 2958780..b0739db 100644 (file)
 #include "src/mc/mc_forward.hpp"
 #include "xbt/base.h"
 
+#include <deque>
 #include <string>
-#include <vector>
 
 namespace simgrid::mc {
 
 class RecordTrace {
-  std::vector<Transition*> transitions_;
+  std::deque<Transition*> transitions_;
 
 public:
   RecordTrace() = default;
@@ -35,7 +35,10 @@ public:
   /** Make a string representation that can later be used to create a new trace */
   std::string to_string() const;
 
+  void push_front(Transition* t) { transitions_.push_front(t); }
   void push_back(Transition* t) { transitions_.push_back(t); }
+  std::deque<Transition*>::const_iterator begin() const { return transitions_.begin(); }
+  std::deque<Transition*>::const_iterator end() const { return transitions_.end(); }
 
   /** Replay all transitions of a trace */
   void replay() const;
index 29b3700..4cf3a5e 100644 (file)
@@ -128,7 +128,7 @@ double LinkEnergy::get_power() const
 
   double power_slope = busy_ - idle_;
 
-  double normalized_link_usage = link_->get_usage() / link_->get_bandwidth();
+  double normalized_link_usage = link_->get_load() / link_->get_bandwidth();
   double dynamic_power         = power_slope * normalized_link_usage;
 
   return idle_ + dynamic_power;
index 481f1f2..0eb9cf0 100644 (file)
@@ -187,7 +187,7 @@ void LinkEnergyWifi::update()
    *  - if idle i.e. get_usage = 0, update P_{stat}
    * P_{tot} = P_{dyn}+P_{stat}
    */
-  if (link_->get_usage() != 0.0) {
+  if (link_->get_load() != 0.0) {
     eDyn_ += /*duration * */ durUsage * ((host_count * pRx_) + pTx_);
     eStat_ += (duration - durUsage) * pIdle_ * (host_count + 1);
     XBT_DEBUG("eDyn +=  %f * ((%f * %f) + %f) | eDyn = %f (durusage =%f)", durUsage, host_count, pRx_, pTx_, eDyn_,
index 1afdd6e..8614765 100644 (file)
@@ -111,7 +111,7 @@ void LinkLoad::update()
              " Please track your link with sg_link_load_track before trying to access any of its load metrics.",
              link_->get_cname());
 
-  double current_instantaneous_bytes_per_second = link_->get_usage();
+  double current_instantaneous_bytes_per_second = link_->get_load();
   double now                                    = simgrid::s4u::Engine::get_clock();
 
   // Update minimum/maximum observed values if needed
index 8d41270..4280066 100644 (file)
@@ -130,9 +130,9 @@ Link* Link::set_concurrency_limit(int limit)
   return this;
 }
 
-double Link::get_usage() const
+double Link::get_load() const
 {
-  return this->pimpl_->get_constraint()->get_usage();
+  return this->pimpl_->get_constraint()->get_load();
 }
 
 void Link::turn_on()