* under the terms of the license (GNU LGPL) which comes with this package. */
#include <functional>
+#include <memory>
#include <signal.h> /* Signal handling */
#include <stdlib.h>
#include "src/internal_config.h"
+#include <xbt/functional.hpp>
+
+#include <simgrid/s4u/host.hpp>
+
#include "src/surf/surf_interface.hpp"
#include "src/surf/storage_interface.hpp"
#include "src/surf/xml/platf.hpp"
#include "src/mc/mc_replay.h"
#include "simgrid/sg_config.h"
-#include "src/simix/SynchroExec.hpp"
-#include "src/simix/SynchroComm.hpp"
-#include "src/simix/SynchroSleep.hpp"
-#include "src/simix/SynchroIo.hpp"
-#include "src/simix/SynchroRaw.hpp"
+#include "src/kernel/activity/SynchroExec.hpp"
+#include "src/kernel/activity/SynchroComm.hpp"
+#include "src/kernel/activity/SynchroSleep.hpp"
+#include "src/kernel/activity/SynchroIo.hpp"
+#include "src/kernel/activity/SynchroRaw.hpp"
#if HAVE_MC
#include "src/mc/mc_private.h"
XBT_LOG_NEW_CATEGORY(simix, "All SIMIX categories");
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_kernel, simix, "Logging specific to SIMIX (kernel)");
-smx_global_t simix_global = nullptr;
+std::unique_ptr<simgrid::simix::Global> simix_global;
static xbt_heap_t simix_timers = nullptr;
/** @brief Timer datatype */
typedef struct s_smx_timer {
double date = 0.0;
- std::function<void()> callback;
+ simgrid::xbt::Task<void()> callback;
s_smx_timer() {}
- s_smx_timer(double date, std::function<void()> callback)
+ s_smx_timer(double date, simgrid::xbt::Task<void()> callback)
: date(date), callback(std::move(callback)) {}
} s_smx_timer_t;
#endif
if (!simix_global) {
- simix_global = xbt_new0(s_smx_global_t, 1);
+ simix_global = std::unique_ptr<simgrid::simix::Global>(new simgrid::simix::Global());
simgrid::simix::Process proc;
simix_global->process_to_run = xbt_dynar_new(sizeof(smx_process_t), nullptr);
simix_global->process_that_ran = xbt_dynar_new(sizeof(smx_process_t), nullptr);
simix_global->process_list = xbt_swag_new(xbt_swag_offset(proc, process_hookup));
simix_global->process_to_destroy = xbt_swag_new(xbt_swag_offset(proc, destroy_hookup));
-
simix_global->maestro_process = nullptr;
- simix_global->registered_functions = xbt_dict_new_homogeneous(nullptr);
-
simix_global->create_process_function = &SIMIX_process_create;
simix_global->kill_process_function = &kill_process;
simix_global->cleanup_process_function = &SIMIX_process_cleanup;
void SIMIX_clean(void)
{
if (smx_cleaned) return; // to avoid double cleaning by java and C
+
+#if HAVE_SMPI
+ if (SIMIX_process_count()>0){
+ 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
+
smx_cleaned = 1;
XBT_DEBUG("SIMIX_clean called. Simulation's over.");
if (!xbt_dynar_is_empty(simix_global->process_to_run) && SIMIX_get_clock() == 0.0) {
xbt_swag_free(simix_global->process_list);
simix_global->process_list = nullptr;
simix_global->process_to_destroy = nullptr;
- xbt_dict_free(&(simix_global->registered_functions));
xbt_os_mutex_destroy(simix_global->mutex);
simix_global->mutex = nullptr;
surf_exit();
- xbt_free(simix_global);
simix_global = nullptr;
-
return;
}
}
}
+/** Wake up all processes waiting for a Surf action to finish */
+static void SIMIX_wake_processes()
+{
+ unsigned int iter;
+ surf_model_t model;
+ surf_action_t action;
+
+ xbt_dynar_foreach(all_existing_models, iter, model) {
+ XBT_DEBUG("Handling the processes whose action failed (if any)");
+ while ((action = surf_model_extract_failed_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
+ SIMIX_simcall_exit((smx_synchro_t) action->getData());
+ }
+ XBT_DEBUG("Handling the processes whose action terminated normally (if any)");
+ while ((action = surf_model_extract_done_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
+ if (action->getData() == nullptr)
+ XBT_DEBUG("probably vcpu's action %p, skip", action);
+ else
+ SIMIX_simcall_exit((smx_synchro_t) action->getData());
+ }
+ }
+}
+
+/** Handle any pending timer */
+static bool SIMIX_execute_timers()
+{
+ bool result = false;
+ while (xbt_heap_size(simix_timers) > 0 && SIMIX_get_clock() >= SIMIX_timer_next()) {
+ result = true;
+ //FIXME: make the timers being real callbacks
+ // (i.e. provide dispatchers that read and expand the args)
+ smx_timer_t timer = (smx_timer_t) xbt_heap_pop(simix_timers);
+ try {
+ timer->callback();
+ }
+ catch(...) {
+ xbt_die("Exception throwed ouf of timer callback");
+ }
+ delete timer;
+ }
+ return result;
+}
+
+/** Execute all the tasks that are queued
+ *
+ * e.g. `.then()` callbacks of futures.
+ **/
+static bool SIMIX_execute_tasks()
+{
+ xbt_assert(simix_global->tasksTemp.empty());
+
+ if (simix_global->tasks.empty())
+ return false;
+
+ using std::swap;
+ do {
+ // We don't want the callbacks to modify the vector we are iterating over:
+ swap(simix_global->tasks, simix_global->tasksTemp);
+
+ // Execute all the queued tasks:
+ for (auto& task : simix_global->tasksTemp)
+ task();
+
+ simix_global->tasksTemp.clear();
+ } while (!simix_global->tasks.empty());
+
+ return true;
+}
+
/**
* \ingroup SIMIX_API
* \brief Run the main simulation loop.
double time = 0;
smx_process_t process;
- surf_action_t action;
- smx_timer_t timer;
- surf_model_t model;
- unsigned int iter;
do {
XBT_DEBUG("New Schedule Round; size(queue)=%lu",
xbt_dynar_length(simix_global->process_to_run));
+
+ SIMIX_execute_tasks();
+
while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
XBT_DEBUG("New Sub-Schedule Round; size(queue)=%lu",
xbt_dynar_length(simix_global->process_to_run));
* That would thus be a pure waste of time.
*/
+ unsigned int iter;
xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
if (process->simcall.call != SIMCALL_NONE) {
SIMIX_simcall_handle(&process->simcall, 0);
}
}
- /* Wake up all processes waiting for a Surf action to finish */
- xbt_dynar_foreach(all_existing_models, iter, model) {
- XBT_DEBUG("Handling process whose action failed");
- while ((action = surf_model_extract_failed_action_set(model))) {
- XBT_DEBUG(" Handling Action %p",action);
- SIMIX_simcall_exit((smx_synchro_t) action->getData());
- }
- XBT_DEBUG("Handling process whose action terminated normally");
- while ((action = surf_model_extract_done_action_set(model))) {
- XBT_DEBUG(" Handling Action %p",action);
- if (action->getData() == nullptr)
- XBT_DEBUG("probably vcpu's action %p, skip", action);
- else
- SIMIX_simcall_exit((smx_synchro_t) action->getData());
- }
- }
+
+ SIMIX_execute_tasks();
+ do {
+ SIMIX_wake_processes();
+ } while (SIMIX_execute_tasks());
+
}
time = SIMIX_timer_next();
time = surf_solve(time);
XBT_DEBUG("Moving time ahead : %g", 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 processes with host_fail */
- /* Handle any pending timer */
- while (xbt_heap_size(simix_timers) > 0 && SIMIX_get_clock() >= SIMIX_timer_next()) {
- //FIXME: make the timers being real callbacks
- // (i.e. provide dispatchers that read and expand the args)
- timer = (smx_timer_t) xbt_heap_pop(simix_timers);
- if (timer->callback) {
- try {
- timer->callback();
- }
- catch(...) {
- xbt_die("Exception throwed ouf of timer callback");
- }
- }
- delete timer;
- }
-
- /* Wake up all processes waiting for a Surf action to finish */
- xbt_dynar_foreach(all_existing_models, iter, model) {
- XBT_DEBUG("Handling process whose action failed");
- while ((action = surf_model_extract_failed_action_set(model))) {
- XBT_DEBUG(" Handling Action %p",action);
- SIMIX_simcall_exit((smx_synchro_t) action->getData());
- }
- XBT_DEBUG("Handling process whose action terminated normally");
- while ((action = surf_model_extract_done_action_set(model))) {
- XBT_DEBUG(" Handling Action %p",action);
- if (action->getData() == nullptr)
- XBT_DEBUG("probably vcpu's action %p, skip", action);
- else
- SIMIX_simcall_exit((smx_synchro_t) action->getData());
- }
- }
+ // Execute timers and tasks until there isn't anything to be done:
+ bool again = false;
+ do {
+ again = SIMIX_execute_timers();
+ if (SIMIX_execute_tasks())
+ again = true;
+ SIMIX_wake_processes();
+ } while (again);
/* Autorestart all process */
char *hostname = nullptr;
+ unsigned int iter;
xbt_dynar_foreach(host_that_restart,iter,hostname) {
XBT_INFO("Restart processes on host: %s",hostname);
SIMIX_host_autorestart(sg_host_by_name(hostname));
/* Clean processes to destroy */
SIMIX_process_empty_trash();
-
XBT_DEBUG("### time %f, empty %d", time, xbt_dynar_is_empty(simix_global->process_to_run));
} while (time != -1.0 || !xbt_dynar_is_empty(simix_global->process_to_run));
* \param arg Parameters of the function
*
*/
-smx_timer_t SIMIX_timer_set(double date, void (*function)(void*), void *arg)
+smx_timer_t SIMIX_timer_set(double date, void (*callback)(void*), void *arg)
{
- smx_timer_t timer = new s_smx_timer_t(date, std::bind(function, arg));
+ smx_timer_t timer = new s_smx_timer_t(date, [=](){ callback(arg); });
xbt_heap_push(simix_timers, timer, date);
return timer;
}
-smx_timer_t SIMIX_timer_set(double date, std::function<void()> callback)
+smx_timer_t SIMIX_timer_set(double date, simgrid::xbt::Task<void()> callback)
{
smx_timer_t timer = new s_smx_timer_t(date, std::move(callback));
xbt_heap_push(simix_timers, timer, date);