Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
start to make generic simcalls observable from the MC
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Mon, 12 Aug 2019 10:21:51 +0000 (12:21 +0200)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Thu, 15 Aug 2019 13:37:41 +0000 (15:37 +0200)
WIP, done in the easy parts for now.

Not finished in MC_state_get_request_for_process() yet. That's too bad
because this function is the core of the use of simcalls by the MC,
where the next simcall is picked.

Not done in the independence computing part either.

include/simgrid/simix.hpp
include/simgrid/simix/blocking_simcall.hpp
src/mc/mc_base.cpp
src/mc/mc_request.cpp
src/simix/libsmx.cpp
src/simix/popping_private.hpp

index f28dbb2..08bb97b 100644 (file)
 #include <string>
 #include <unordered_map>
 
-XBT_PUBLIC void simcall_run_kernel(std::function<void()> const& code);
-XBT_PUBLIC void simcall_run_blocking(std::function<void()> const& code);
+namespace simgrid {
+namespace kernel {
+namespace actor {
+
+class Transition {
+public:
+  virtual bool fireable()
+  {
+    return true;
+  } // whether this transition can currently be taken (if not, it could block the process)
+  virtual bool visible() { return true; } // whether the model-checker should pay any attention to this simcall
+  virtual std::string to_string() = 0;
+  virtual std::string dot_label() = 0;
+};
+} // namespace actor
+} // namespace kernel
+} // namespace simgrid
+
+XBT_PUBLIC void simcall_run_kernel(std::function<void()> const& code, simgrid::kernel::actor::Transition* t);
+XBT_PUBLIC void simcall_run_blocking(std::function<void()> const& code, simgrid::kernel::actor::Transition* t);
 
 namespace simgrid {
 namespace kernel {
@@ -42,7 +60,7 @@ namespace actor {
  * you may need to wait for that mutex to be unlocked by its current owner.
  * Potentially blocking simcall must be issued using simcall_blocking(), right below in this file.
  */
-template <class F> typename std::result_of<F()>::type simcall(F&& code)
+template <class F> typename std::result_of<F()>::type simcall(F&& code, Transition* t = nullptr)
 {
   // If we are in the maestro, we take the fast path and execute the
   // code directly without simcall mashalling/unmarshalling/dispatch:
@@ -54,7 +72,7 @@ template <class F> typename std::result_of<F()>::type simcall(F&& code)
   // conveniently handles the success/failure value for us.
   typedef typename std::result_of<F()>::type R;
   simgrid::xbt::Result<R> result;
-  simcall_run_kernel([&result, &code] { simgrid::xbt::fulfill_promise(result, std::forward<F>(code)); });
+  simcall_run_kernel([&result, &code] { simgrid::xbt::fulfill_promise(result, std::forward<F>(code)); }, t);
   return result.get();
 }
 
@@ -72,7 +90,7 @@ template <class F> typename std::result_of<F()>::type simcall(F&& code)
  *
  * If your code never calls actor->simcall_answer() itself, the actor will never return from its simcall.
  */
-template <class F> typename std::result_of<F()>::type simcall_blocking(F&& code)
+template <class F> typename std::result_of<F()>::type simcall_blocking(F&& code, Transition* t = nullptr)
 {
   // If we are in the maestro, we take the fast path and execute the
   // code directly without simcall mashalling/unmarshalling/dispatch:
@@ -84,7 +102,7 @@ template <class F> typename std::result_of<F()>::type simcall_blocking(F&& code)
   // conveniently handles the success/failure value for us.
   typedef typename std::result_of<F()>::type R;
   simgrid::xbt::Result<R> result;
-  simcall_run_blocking([&result, &code] { simgrid::xbt::fulfill_promise(result, std::forward<F>(code)); });
+  simcall_run_blocking([&result, &code] { simgrid::xbt::fulfill_promise(result, std::forward<F>(code)); }, t);
   return result.get();
 }
 } // namespace actor
index c8ba0f7..017b7f2 100644 (file)
@@ -18,8 +18,6 @@
 #include <simgrid/simix.h>
 #include <simgrid/simix.hpp>
 
-XBT_PUBLIC void simcall_run_blocking(std::function<void()> const& code);
-
 namespace simgrid {
 namespace simix {
 
@@ -54,19 +52,20 @@ template <class F> auto kernel_sync(F code) -> decltype(code().get())
   smx_actor_t self = SIMIX_process_self();
   simgrid::xbt::Result<T> result;
 
-  simcall_run_blocking([&result, self, &code]{
-    try {
-      auto future = code();
-      future.then_([&result, self](std::shared_ptr<simgrid::kernel::FutureState<T>>&& value) {
-        simgrid::xbt::set_promise(result, simgrid::kernel::Future<T>(value));
-        simgrid::simix::unblock(self);
-      });
-    }
-    catch (...) {
-      result.set_exception(std::current_exception());
-      simgrid::simix::unblock(self);
-    }
-  });
+  simcall_run_blocking(
+      [&result, self, &code] {
+        try {
+          auto future = code();
+          future.then_([&result, self](std::shared_ptr<simgrid::kernel::FutureState<T>>&& value) {
+            simgrid::xbt::set_promise(result, simgrid::kernel::Future<T>(value));
+            simgrid::simix::unblock(self);
+          });
+        } catch (...) {
+          result.set_exception(std::current_exception());
+          simgrid::simix::unblock(self);
+        }
+      },
+      nullptr);
   return result.get();
 }
 
@@ -89,20 +88,21 @@ public:
       throw std::future_error(std::future_errc::no_state);
     smx_actor_t self = SIMIX_process_self();
     simgrid::xbt::Result<T> result;
-    simcall_run_blocking([this, &result, self]{
-      try {
-        // When the kernel future is ready...
-        this->future_.then_([&result, self](std::shared_ptr<simgrid::kernel::FutureState<T>>&& value) {
-          // ... wake up the process with the result of the kernel future.
-          simgrid::xbt::set_promise(result, simgrid::kernel::Future<T>(value));
-          simgrid::simix::unblock(self);
-        });
-      }
-      catch (...) {
-        result.set_exception(std::current_exception());
-        simgrid::simix::unblock(self);
-      }
-    });
+    simcall_run_blocking(
+        [this, &result, self] {
+          try {
+            // When the kernel future is ready...
+            this->future_.then_([&result, self](std::shared_ptr<simgrid::kernel::FutureState<T>>&& value) {
+              // ... wake up the process with the result of the kernel future.
+              simgrid::xbt::set_promise(result, simgrid::kernel::Future<T>(value));
+              simgrid::simix::unblock(self);
+            });
+          } catch (...) {
+            result.set_exception(std::current_exception());
+            simgrid::simix::unblock(self);
+          }
+        },
+        nullptr);
     return result.get();
   }
   bool is_ready() const
@@ -119,20 +119,21 @@ public:
     // The future is not ready. We have to delegate to the SimGrid kernel:
     std::exception_ptr exception;
     smx_actor_t self = SIMIX_process_self();
-    simcall_run_blocking([this, &exception, self]{
-      try {
-        // When the kernel future is ready...
-        this->future_.then_([this, self](std::shared_ptr<simgrid::kernel::FutureState<T>>&& value) {
-          // ...store it the simix kernel and wake up.
-          this->future_ = std::move(simgrid::kernel::Future<T>(value));
-          simgrid::simix::unblock(self);
-        });
-      }
-      catch (...) {
-        exception = std::current_exception();
-        simgrid::simix::unblock(self);
-      }
-    });
+    simcall_run_blocking(
+        [this, &exception, self] {
+          try {
+            // When the kernel future is ready...
+            this->future_.then_([this, self](std::shared_ptr<simgrid::kernel::FutureState<T>>&& value) {
+              // ...store it the simix kernel and wake up.
+              this->future_ = std::move(simgrid::kernel::Future<T>(value));
+              simgrid::simix::unblock(self);
+            });
+          } catch (...) {
+            exception = std::current_exception();
+            simgrid::simix::unblock(self);
+          }
+        },
+        nullptr);
   }
 private:
   // We wrap an event-based kernel future:
index 413e9a7..2a6b270 100644 (file)
@@ -78,6 +78,9 @@ bool actor_is_enabled(smx_actor_t actor)
   // Now, we are in the client app, no need for remote memory reading.
   smx_simcall_t req = &actor->simcall;
 
+  if (req->transition != nullptr)
+    return req->transition->fireable();
+
   switch (req->call) {
     case SIMCALL_NONE:
       return false;
@@ -150,10 +153,10 @@ bool request_is_visible(smx_simcall_t req)
   xbt_assert(mc_model_checker == nullptr, "This should be called from the client side");
 #endif
 
-  return req->call == SIMCALL_COMM_ISEND || req->call == SIMCALL_COMM_IRECV || req->call == SIMCALL_COMM_WAIT ||
-         req->call == SIMCALL_COMM_WAITANY || req->call == SIMCALL_COMM_TEST || req->call == SIMCALL_COMM_TESTANY ||
-         req->call == SIMCALL_MC_RANDOM || req->call == SIMCALL_MUTEX_LOCK || req->call == SIMCALL_MUTEX_TRYLOCK ||
-         req->call == SIMCALL_MUTEX_UNLOCK;
+  return (req->transition != nullptr && req->transition->visible()) || req->call == SIMCALL_COMM_ISEND ||
+         req->call == SIMCALL_COMM_IRECV || req->call == SIMCALL_COMM_WAIT || req->call == SIMCALL_COMM_WAITANY ||
+         req->call == SIMCALL_COMM_TEST || req->call == SIMCALL_COMM_TESTANY || req->call == SIMCALL_MC_RANDOM ||
+         req->call == SIMCALL_MUTEX_LOCK || req->call == SIMCALL_MUTEX_TRYLOCK || req->call == SIMCALL_MUTEX_UNLOCK;
 }
 
 }
index b46fc55..900a115 100644 (file)
@@ -176,6 +176,9 @@ std::string simgrid::mc::request_to_string(smx_simcall_t req, int value, simgrid
 {
   xbt_assert(mc_model_checker != nullptr, "Must be called from MCer");
 
+  if (req->transition != nullptr)
+    return req->transition->to_string();
+
   bool use_remote_comm = true;
   switch(request_type) {
   case simgrid::mc::RequestType::simix:
@@ -417,9 +420,15 @@ static inline const char* get_color(int id)
 
 std::string request_get_dot_output(smx_simcall_t req, int value)
 {
+  const smx_actor_t issuer = MC_smx_simcall_get_issuer(req);
+  const char* color        = get_color(issuer->get_pid() - 1);
+
+  if (req->transition != nullptr)
+    return simgrid::xbt::string_printf("label = \"%s\", color = %s, fontcolor = %s",
+                                       req->transition->dot_label().c_str(), color, color);
+
   std::string label;
 
-  const smx_actor_t issuer = MC_smx_simcall_get_issuer(req);
 
   switch (req->call) {
   case SIMCALL_COMM_ISEND:
@@ -531,7 +540,6 @@ std::string request_get_dot_output(smx_simcall_t req, int value)
     THROW_UNIMPLEMENTED;
   }
 
-  const char* color = get_color(issuer->get_pid() - 1);
   return  simgrid::xbt::string_printf(
         "label = \"%s\", color = %s, fontcolor = %s", label.c_str(),
         color, color);
index 4a0aa0e..c8470a4 100644 (file)
@@ -307,13 +307,15 @@ e_smx_state_t simcall_io_wait(const smx_activity_t& io)
   return (e_smx_state_t)simcall_BODY_io_wait(static_cast<simgrid::kernel::activity::IoImpl*>(io.get()));
 }
 
-void simcall_run_kernel(std::function<void()> const& code)
+void simcall_run_kernel(std::function<void()> const& code, simgrid::kernel::actor::Transition* t)
 {
+  SIMIX_process_self()->simcall.transition = t;
   simcall_BODY_run_kernel(&code);
 }
 
-void simcall_run_blocking(std::function<void()> const& code)
+void simcall_run_blocking(std::function<void()> const& code, simgrid::kernel::actor::Transition* t = nullptr)
 {
+  SIMIX_process_self()->simcall.transition = t;
   simcall_BODY_run_blocking(&code);
 }
 
index 83f7e2d..f0c6cce 100644 (file)
@@ -46,6 +46,7 @@ struct s_smx_simcall {
   e_smx_simcall_t call;
   smx_actor_t issuer;
   smx_timer_t timeout_cb; // Callback to timeouts
+  simgrid::kernel::actor::Transition* transition = nullptr;
   int mc_value;
   u_smx_scalar args[11];
   u_smx_scalar result;