Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Activity refactoring
[simgrid.git] / src / kernel / EngineImpl.cpp
index e2f5158..24116e2 100644 (file)
@@ -248,7 +248,7 @@ void EngineImpl::context_mod_init() const
 {
   xbt_assert(not instance_->has_context_factory());
 
-#if HAVE_SMPI && (defined(__APPLE__) || defined(__NetBSD__))
+#if HAVE_SMPI && defined(__NetBSD__)
   smpi_init_options_internal(false);
   std::string priv = config::get_value<std::string>("smpi/privatization");
   if (context_factory_name == "thread" && (priv == "dlopen" || priv == "yes" || priv == "default" || priv == "1")) {
@@ -329,7 +329,8 @@ void EngineImpl::shutdown()
   instance_->empty_trash();
 
   /* Let's free maestro now */
-  instance_->destroy_maestro();
+  delete instance_->maestro_;
+  instance_->maestro_ = nullptr;
 
   /* Finish context module and SURF */
   instance_->destroy_context_factory();
@@ -415,16 +416,35 @@ void EngineImpl::wake_all_waiting_actors() const
     XBT_DEBUG("Handling the failed actions (if any)");
     while (auto* action = model->extract_failed_action()) {
       XBT_DEBUG("   Handling Action %p", action);
-      if (action->get_activity() != nullptr)
+      if (action->get_activity() != nullptr) {
+        // If nobody told the interface that the activity has failed, that's because no actor waits on it (maestro
+        // started it). SimDAG I see you!
+        if (action->get_activity()->get_actor() == maestro_)
+          action->get_activity()->get_iface()->complete(s4u::Activity::State::FAILED);
+
         activity::ActivityImplPtr(action->get_activity())->post();
+      }
     }
     XBT_DEBUG("Handling the terminated actions (if any)");
     while (auto* action = model->extract_done_action()) {
       XBT_DEBUG("   Handling Action %p", action);
       if (action->get_activity() == nullptr)
         XBT_DEBUG("probably vcpu's action %p, skip", action);
-      else
+      else {
+        // If nobody told the interface that the activity is finished, that's because no actor waits on it (maestro
+        // started it). SimDAG I see you!
+        // TODO: do the same for other activity kinds once comms are cleaned up
+        auto* exec = dynamic_cast<activity::ExecImpl*>(action->get_activity());
+        if (exec != nullptr && exec->get_actor() == maestro_) {
+          exec->set_finish_time(action->get_finish_time());
+          exec->get_iface()->complete(s4u::Activity::State::FINISHED);
+        }
+        auto* io = dynamic_cast<activity::IoImpl*>(action->get_activity());
+        if (io != nullptr && io->get_actor() == maestro_)
+          io->get_iface()->complete(s4u::Activity::State::FINISHED);
+
         activity::ActivityImplPtr(action->get_activity())->post();
+      }
     }
   }
 }
@@ -672,7 +692,7 @@ double EngineImpl::solve(double max_date) const
   return time_delta;
 }
 
-void EngineImpl::run()
+void EngineImpl::run(double max_date)
 {
   if (MC_record_replay_is_active()) {
     mc::replay(MC_record_path());
@@ -680,7 +700,8 @@ void EngineImpl::run()
     return;
   }
 
-  double time = 0;
+  double elapsed_time = -1;
+  std::set<s4u::Activity*>* vetoed_activities = s4u::Activity::get_vetoed_activities();
 
   do {
     XBT_DEBUG("New Schedule Round; size(queue)=%zu", actors_to_run_.size());
@@ -784,13 +805,19 @@ void EngineImpl::run()
         }
     }
 
-    time = timer::Timer::next();
-    if (time > -1.0 || not actor_list_.empty()) {
-      XBT_DEBUG("Calling solve");
-      time = solve(time);
-      XBT_DEBUG("Moving time ahead : %g", time);
+    // Compute the max_date of the next solve.
+    // It's either when a timer occurs, or when user-specified deadline is reached, or -1 if none is given
+    double next_time = timer::Timer::next();
+    if (next_time < 0 && max_date > -1) {
+      next_time = max_date;
+    } else if (next_time > -1 && max_date > -1) { // either both <0, or both >0
+      next_time = std::min(next_time, max_date);
     }
 
+    XBT_DEBUG("Calling solve(%g) %g", next_time, NOW);
+    elapsed_time = solve(next_time);
+    XBT_DEBUG("Moving time ahead. NOW=%g; elapsed: %g", NOW, elapsed_time);
+
     /* Notify all the hosts that have failed */
     /* FIXME: iterate through the list of failed host and mark each of them */
     /* as failed. On each host, signal all the running actors with host_fail */
@@ -807,9 +834,10 @@ void EngineImpl::run()
     /* Clean actors to destroy */
     empty_trash();
 
-    XBT_DEBUG("### time %f, #actors %zu, #to_run %zu", time, actor_list_.size(), actors_to_run_.size());
+    XBT_DEBUG("### elapsed time %f, #actors %zu, #to_run %zu, #vetoed %d", elapsed_time, actor_list_.size(),
+              actors_to_run_.size(), (vetoed_activities == nullptr ? -1 : static_cast<int>(vetoed_activities->size())));
 
-    if (time < 0. && actors_to_run_.empty() && not actor_list_.empty()) {
+    if (elapsed_time < 0. && actors_to_run_.empty() && not actor_list_.empty()) {
       if (actor_list_.size() <= daemons_.size()) {
         XBT_CRITICAL("Oops! Daemon actors cannot do any blocking activity (communications, synchronization, etc) "
                      "once the simulation is over. Please fix your on_exit() functions.");
@@ -823,9 +851,11 @@ void EngineImpl::run()
         maestro_->kill(kv.second);
       }
     }
-  } while (time > -1.0 || has_actors_to_run());
 
-  if (not actor_list_.empty())
+  } while ((vetoed_activities == nullptr || vetoed_activities->empty()) &&
+           ((elapsed_time > -1.0 && not double_equals(max_date, NOW, 0.00001)) || has_actors_to_run()));
+
+  if (not actor_list_.empty() && max_date < 0 && not(vetoed_activities == nullptr || vetoed_activities->empty()))
     THROW_IMPOSSIBLE;
 
   simgrid::s4u::Engine::on_simulation_end();
@@ -840,5 +870,5 @@ double EngineImpl::get_clock()
 
 void SIMIX_run() // XBT_ATTRIB_DEPRECATED_v332
 {
-  simgrid::kernel::EngineImpl::get_instance()->run();
+  simgrid::kernel::EngineImpl::get_instance()->run(-1);
 }