X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/e2f13c6eb4d0c1b07e1b32a75016431dd75a68d2..237fd22b56db7d1c67360c37559ce3aab16a002d:/src/kernel/EngineImpl.cpp diff --git a/src/kernel/EngineImpl.cpp b/src/kernel/EngineImpl.cpp index 926bdb9288..5fcf59443b 100644 --- a/src/kernel/EngineImpl.cpp +++ b/src/kernel/EngineImpl.cpp @@ -13,6 +13,7 @@ #include "simgrid/sg_config.hpp" #include "src/include/surf/surf.hpp" //get_clock() and surf_solve() #include "src/kernel/resource/DiskImpl.hpp" +#include "src/kernel/resource/profile/Profile.hpp" #include "src/mc/mc_record.hpp" #include "src/mc/mc_replay.hpp" #include "src/simix/smx_private.hpp" @@ -20,21 +21,76 @@ #include "src/surf/network_interface.hpp" #include "src/surf/xml/platf.hpp" // FIXME: KILLME. There must be a better way than mimicking XML here +#include +#ifndef _WIN32 +#include +#endif /* _WIN32 */ + XBT_LOG_NEW_DEFAULT_CATEGORY(ker_engine, "Logging specific to Engine (kernel)"); namespace simgrid { namespace kernel { +EngineImpl* EngineImpl::instance_ = nullptr; /* That singleton is awful too. */ config::Flag cfg_breakpoint{"debug/breakpoint", "When non-negative, raise a SIGTRAP after given (simulated) time", -1.0}; -EngineImpl::~EngineImpl() +void EngineImpl::shutdown() { + static bool already_cleaned_up = false; + if (already_cleaned_up) + return; // to avoid double cleaning by java and C + already_cleaned_up = true; + if (not EngineImpl::instance_) { + simix_global->destroy_maestro(); + simix_global->destroy_context_factory(); + return; // Nothing more to shutdown + } + XBT_DEBUG("EngineImpl::shutdown() called. Simulation's over."); + + if (instance_->has_actors_to_run() && simgrid_get_clock() <= 0.0) { + XBT_CRITICAL(" "); + XBT_CRITICAL("The time is still 0, and you still have processes ready to run."); + XBT_CRITICAL("It seems that you forgot to run the simulation that you setup."); + xbt_die("Bailing out to avoid that stop-before-start madness. Please fix your code."); + } + +#if HAVE_SMPI + if (not instance_->actor_list_.empty()) { + if (smpi_process()->initialized()) { + xbt_die("Process exited without calling MPI_Finalize - Killing simulation"); + } else { + XBT_WARN("Process called exit when leaving - Skipping cleanups"); + return; + } + } +#endif + + /* Kill all actors (but maestro) */ + simix_global->get_maestro()->kill_all(); + instance_->run_all_actors(); + instance_->empty_trash(); + + /* Let's free maestro now */ + simix_global->destroy_maestro(); + + /* Finish context module and SURF */ + simix_global->destroy_context_factory(); while (not timer::kernel_timers().empty()) { delete timer::kernel_timers().top().second; timer::kernel_timers().pop(); } + tmgr_finalize(); + sg_platf_exit(); + + simgrid::s4u::Engine::shutdown(); + + simix_global = nullptr; +} + +EngineImpl::~EngineImpl() +{ /* Since hosts_ is a std::map, the hosts are destroyed in the lexicographic order, which ensures that the output is * reproducible. */ @@ -50,11 +106,40 @@ EngineImpl::~EngineImpl() if (kv.second) kv.second->destroy(); - /* Free the remaining data structures */ + for (auto const& kv : mailboxes_) + delete kv.second; + + /* Free the remaining data structures */ #if SIMGRID_HAVE_MC xbt_dynar_free(&actors_vector_); xbt_dynar_free(&dead_actors_vector_); #endif + /* clear models before freeing handle, network models can use external callback defined in the handle */ + models_prio_.clear(); +} + +void EngineImpl::load_platform(const std::string& platf) +{ + double start = xbt_os_time(); + if (boost::algorithm::ends_with(platf, ".so") or boost::algorithm::ends_with(platf, ".dylib")) { +#ifdef _WIN32 + xbt_die("loading platform through shared library isn't supported on windows"); +#else + void* handle = dlopen(platf.c_str(), RTLD_LAZY); + xbt_assert(handle, "Impossible to open platform file: %s", platf.c_str()); + platf_handle_ = std::unique_ptr>(handle, dlclose); + using load_fct_t = void (*)(const simgrid::s4u::Engine&); + auto callable = (load_fct_t)dlsym(platf_handle_.get(), "load_platform"); + const char* dlsym_error = dlerror(); + xbt_assert(not dlsym_error, "Error: %s", dlsym_error); + callable(*simgrid::s4u::Engine::get_instance()); +#endif /* _WIN32 */ + } else { + parse_platform_file(platf); + } + + double end = xbt_os_time(); + XBT_DEBUG("PARSE TIME: %g", (end - start)); } void EngineImpl::load_deployment(const std::string& file) const @@ -90,6 +175,11 @@ void EngineImpl::add_model(std::shared_ptr model, const std::ve models_prio_[model_name] = std::move(model); } +void EngineImpl::add_split_duplex_link(const std::string& name, std::unique_ptr link) +{ + split_duplex_links_[name] = std::move(link); +} + /** Wake up all actors waiting for a Surf action to finish */ void EngineImpl::wake_all_waiting_actors() const { @@ -119,7 +209,7 @@ void EngineImpl::wake_all_waiting_actors() const */ void EngineImpl::run_all_actors() { - simix_global->context_factory->run_all(); + simix_global->get_context_factory()->run_all(); actors_to_run_.swap(actors_that_ran_); actors_to_run_.clear(); @@ -140,11 +230,10 @@ actor::ActorImpl* EngineImpl::get_actor_by_pid(aid_t pid) /** Execute all the tasks that are queued, e.g. `.then()` callbacks of futures. */ bool EngineImpl::execute_tasks() { - xbt_assert(tasksTemp.empty()); - if (tasks.empty()) return false; + std::vector> tasksTemp; do { // We don't want the callbacks to modify the vector we are iterating over: tasks.swap(tasksTemp); @@ -235,6 +324,7 @@ void EngineImpl::run() { if (MC_record_replay_is_active()) { mc::replay(MC_record_path()); + empty_trash(); return; } @@ -338,7 +428,7 @@ void EngineImpl::run() if (actor_list_.size() == daemons_.size()) for (auto const& dmon : daemons_) { XBT_DEBUG("Kill %s", dmon->get_cname()); - simix_global->maestro_->kill(dmon); + simix_global->get_maestro()->kill(dmon); } } @@ -378,7 +468,7 @@ void EngineImpl::run() simgrid::s4u::Engine::on_deadlock(); for (auto const& kv : actor_list_) { XBT_DEBUG("Kill %s", kv.second->get_cname()); - simix_global->maestro_->kill(kv.second); + simix_global->get_maestro()->kill(kv.second); } } } while (time > -1.0 || has_actors_to_run());