Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge s4u wait_any
authorGabriel Corona <gabriel.corona@loria.fr>
Fri, 22 Jul 2016 14:30:32 +0000 (16:30 +0200)
committerGabriel Corona <gabriel.corona@loria.fr>
Fri, 22 Jul 2016 14:30:32 +0000 (16:30 +0200)
25 files changed:
doc/doxygen/community_giveback.doc
doc/doxygen/options.doc
examples/simdag/scheduling/sd_scheduling.c
include/simgrid/simix.h
include/xbt/log.h
include/xbt/log.hpp
src/bindings/java/jmsg_rngstream.cpp
src/mc/mc_request.cpp
src/mc/mc_state.cpp
src/msg/msg_gos.cpp
src/simdag/sd_daxloader.cpp
src/simdag/sd_dotloader.cpp
src/simdag/sd_global.cpp
src/simdag/sd_task.cpp
src/simdag/simdag_private.h
src/simix/libsmx.cpp
src/simix/popping_accessors.h
src/simix/popping_bodies.cpp
src/simix/popping_generated.cpp
src/simix/simcalls.in
src/simix/smx_network.cpp
src/smpi/smpi_base.cpp
src/surf/surf_routing.cpp
src/xbt/exception.cpp
src/xbt/xbt_main.c

index 8eee215..cc428d0 100644 (file)
@@ -147,6 +147,11 @@ Some support for C++11-style time/duration is implemented (see `chrono.hpp`)
 but only available in some (S4U) APIs. It would be nice to add support for
 them in the rest of the C++ code.
 
+A related change would be to avoid using "-1" to mean "forever" at least in S4U
+and in the internal code. For compatibility, MSG should probably keep this
+semantic. We should probably always use separate functions
+(`wait` vs `wait_for`).
+
 @subsubsection contributing_todo_futures Futures
 
  - Some features are missing in the Maestro future implementation
index 45b5624..2f5f95f 100644 (file)
@@ -199,17 +199,6 @@ the \b maxmin/precision item (default value: 0.00001). Changing it
 may speedup the simulation by discarding very small actions, at the
 price of a reduced numerical precision.
 
-\subsection options_model_nthreads Parallel threads for model updates
-
-By default, Surf computes the analytical models sequentially to share their
-resources and update their actions. It is possible to run them in parallel,
-using the \b surf/nthreads item (default value: 1). If you use a
-negative or null value, the amount of available cores is automatically
-detected  and used instead.
-
-Depending on the workload of the models and their complexity, you may get a
-speedup or a slowdown because of the synchronization costs of threads.
-
 \subsection options_model_network Configuring the Network model
 
 \subsubsection options_model_network_gamma Maximal TCP window size
index 7269bc6..e4531aa 100644 (file)
@@ -92,24 +92,15 @@ static double finish_on_at(SD_task_t task, sg_host_t host)
     xbt_dynar_foreach(parents, i, parent) {
       /* normal case */
       if (SD_task_get_kind(parent) == SD_TASK_COMM_E2E) {
-        xbt_dynar_t grand_parents = SD_task_get_parents(parent);
-        SD_task_t grand_parent;
-
-        xbt_assert(xbt_dynar_length(grand_parents) <2, "Error: transfer %s has 2 parents", SD_task_get_name(parent));
-
-        xbt_dynar_get_cpy(grand_parents, 0, &grand_parent);
-
-        sg_host_t * grand_parent_host_list = SD_task_get_workstation_list(grand_parent);
+        sg_host_t * parent_host= SD_task_get_workstation_list(parent);
         /* Estimate the redistribution time from this parent */
         if (SD_task_get_amount(parent) <= 1e-6){
           redist_time= 0;
         } else {
-          redist_time = SD_route_get_latency(grand_parent_host_list[0], host) +
-                        SD_task_get_amount(parent) / SD_route_get_bandwidth(grand_parent_host_list[0], host);
+          redist_time = SD_route_get_latency(parent_host[0], host) +
+                        SD_task_get_amount(parent) / SD_route_get_bandwidth(parent_host[0], host);
         }
-        data_available = SD_task_get_finish_time(grand_parent) + redist_time;
-
-        xbt_dynar_free_container(&grand_parents);
+        data_available = SD_task_get_start_time(parent) + redist_time;
       }
 
       /* no transfer, control dependency */
@@ -134,7 +125,7 @@ static double finish_on_at(SD_task_t task, sg_host_t host)
 
 static sg_host_t SD_task_get_best_host(SD_task_t task)
 {
-  const sg_host_t *hosts = sg_host_list();
+  sg_host_t *hosts = sg_host_list();
   int nhosts = sg_host_count();
   sg_host_t best_host = hosts[0];
   double min_EFT = finish_on_at(task, hosts[0]);
@@ -148,6 +139,7 @@ static sg_host_t SD_task_get_best_host(SD_task_t task)
       best_host = hosts[i];
     }
   }
+  xbt_free(hosts);
   return best_host;
 }
 
@@ -175,7 +167,7 @@ int main(int argc, char **argv)
 
   /*  Allocating the host attribute */
   int total_nhosts = sg_host_count();
-  const sg_host_t *hosts = sg_host_list();
+  sg_host_t *hosts = sg_host_list();
 
   for (cursor = 0; cursor < total_nhosts; cursor++)
     sg_host_allocate_attribute(hosts[cursor]);
@@ -259,6 +251,7 @@ int main(int argc, char **argv)
   for (cursor = 0; cursor < total_nhosts; cursor++)
     sg_host_free_attribute(hosts[cursor]);
 
+  xbt_free(hosts);
   /* exit */
   SD_exit();
   return 0;
index dd789b2..6b7f31b 100644 (file)
@@ -362,7 +362,7 @@ XBT_PUBLIC(void) simcall_comm_cancel(smx_synchro_t comm);
 XBT_PUBLIC(unsigned int) simcall_comm_waitany(xbt_dynar_t comms, double timeout);
 XBT_PUBLIC(void) simcall_comm_wait(smx_synchro_t comm, double timeout);
 XBT_PUBLIC(int) simcall_comm_test(smx_synchro_t comm);
-XBT_PUBLIC(int) simcall_comm_testany(xbt_dynar_t comms);
+XBT_PUBLIC(int) simcall_comm_testany(smx_synchro_t* comms, size_t count);
 
 /************************** Tracing handling **********************************/
 XBT_PUBLIC(void) simcall_set_category(smx_synchro_t synchro, const char *category);
index 4c24f32..837829f 100644 (file)
@@ -659,5 +659,7 @@ extern xbt_log_layout_t xbt_log_default_layout;
  */
 #define XBT_HERE(...) XBT_LOG(xbt_log_priority_trace, "-- was here" __VA_ARGS__)
 
+XBT_PUBLIC(void) xbt_set_terminate();
+
 SG_END_DECL()
 #endif                          /* ! _XBT_LOG_H_ */
index 875b3ad..6dbf711 100644 (file)
@@ -20,5 +20,7 @@ XBT_PUBLIC(void) logException(
   e_xbt_log_priority_t priority,
   const char* context, std::exception const& exception);
 
+XBT_PUBLIC(void) installExceptionHandler();
+
 }
 }
index 2dda4ca..a7e82b7 100644 (file)
@@ -110,7 +110,13 @@ JNIEXPORT jboolean JNICALL Java_org_simgrid_msg_RngStream_setSeed(JNIEnv *env, j
   if (!rngstream)
     return JNI_FALSE;
 
-  int result = RngStream_SetSeed(rngstream, (unsigned long*)buffer);
+  // The C API expects unsigned long which are wider than int on LP64.
+  // We need to convert:
+  unsigned long seed[6];
+  for (int i = 0; i != 6; ++i)
+    seed[i] = buffer[i];
+
+  int result = RngStream_SetSeed(rngstream, seed);
 
   return result == -1 ? JNI_FALSE : JNI_TRUE;
 }
index cf8a8bf..1feb6e8 100644 (file)
@@ -375,8 +375,7 @@ std::string simgrid::mc::request_to_string(smx_simcall_t req, int value, simgrid
       type = "TestAny";
       args =
           bprintf("(%d of %zu)", value + 1,
-                  read_length(mc_model_checker->process(),
-                    simcall_comm_testany__get__comms(req)));
+                    simcall_comm_testany__get__count(req));
     }
     break;
 
@@ -451,12 +450,9 @@ bool request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
     }
     break;
 
-  case SIMCALL_COMM_TESTANY: {
-    read_element(
-      mc_model_checker->process(), &remote_act,
-      remote(simcall_comm_testany__get__comms(req)),
-      idx, sizeof(remote_act));
-    }
+  case SIMCALL_COMM_TESTANY:
+    remote_act = mc_model_checker->process().read(remote(
+      simcall_comm_testany__get__comms(req) + idx));
     break;
 
   default:
@@ -601,12 +597,12 @@ std::string request_get_dot_output(smx_simcall_t req, int value)
         label = simgrid::xbt::string_printf("[(%lu)%s] TestAny TRUE [%d of %lu]",
                     issuer->pid,
                     MC_smx_process_get_host_name(issuer), value + 1,
-                    xbt_dynar_length(simcall_comm_testany__get__comms(req)));
+                    simcall_comm_testany__get__count(req));
       else
         label = simgrid::xbt::string_printf("[(%lu)] TestAny TRUE [%d of %lu]",
                     issuer->pid,
                     value + 1,
-                    xbt_dynar_length(simcall_comm_testany__get__comms(req)));
+                    simcall_comm_testany__get__count(req));
     }
     break;
 
index a919c30..59a9de0 100644 (file)
@@ -106,8 +106,7 @@ static inline smx_simcall_t MC_state_get_request_for_process(
         unsigned start_count = procstate->interleave_count;
         state->transition.argument = -1;
         while (procstate->interleave_count <
-                read_length(mc_model_checker->process(),
-                  remote(simcall_comm_testany__get__comms(&process->simcall))))
+                simcall_comm_testany__get__count(&process->simcall))
           if (simgrid::mc::request_is_enabled_by_idx(&process->simcall,
               procstate->interleave_count++)) {
             state->transition.argument = procstate->interleave_count - 1;
@@ -115,8 +114,7 @@ static inline smx_simcall_t MC_state_get_request_for_process(
           }
 
         if (procstate->interleave_count >=
-            read_length(mc_model_checker->process(),
-              remote(simcall_comm_testany__get__comms(&process->simcall))))
+            simcall_comm_testany__get__count(&process->simcall))
           procstate->setDone();
 
         if (state->transition.argument != -1 || start_count == 0)
@@ -191,10 +189,8 @@ static inline smx_simcall_t MC_state_get_request_for_process(
     state->internal_req.issuer = req->issuer;
 
     if (state->transition.argument > 0) {
-      smx_synchro_t remote_comm;
-      read_element(mc_model_checker->process(),
-        &remote_comm, remote(simcall_comm_testany__get__comms(req)),
-        state->transition.argument, sizeof(remote_comm));
+      smx_synchro_t remote_comm = mc_model_checker->process().read(
+        remote(simcall_comm_testany__get__comms(req) + state->transition.argument));
       mc_model_checker->process().read(state->internal_comm, remote(
         static_cast<simgrid::simix::Comm*>(remote_comm)));
     }
index 0ec8312..1d5ebf1 100644 (file)
@@ -504,17 +504,18 @@ int MSG_comm_testany(xbt_dynar_t comms)
 {
   int finished_index = -1;
 
-  /* create the equivalent dynar with SIMIX objects */
-  xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_synchro_t), nullptr);
+  /* Create the equivalent array with SIMIX objects: */
+  std::vector<simgrid::simix::Synchro*> s_comms;
+  s_comms.reserve(xbt_dynar_length(comms));
   msg_comm_t comm;
   unsigned int cursor;
   xbt_dynar_foreach(comms, cursor, comm) {
-    xbt_dynar_push(s_comms, &comm->s_comm);
+    s_comms.push_back(comm->s_comm);
   }
 
   msg_error_t status = MSG_OK;
   try {
-    finished_index = simcall_comm_testany(s_comms);
+    finished_index = simcall_comm_testany(s_comms.data(), s_comms.size());
   }
   catch (xbt_ex& e) {
     switch (e.category) {
@@ -530,7 +531,6 @@ int MSG_comm_testany(xbt_dynar_t comms)
         throw;
     }
   }
-  xbt_dynar_free(&s_comms);
 
   if (finished_index != -1) {
     comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
index d8e0a91..df81674 100644 (file)
@@ -356,18 +356,18 @@ void ETag_dax__adag()
   XBT_DEBUG("See </adag>");
 }
 
-void ETag_dax__job(void)
+void ETag_dax__job()
 {
   current_job = nullptr;
   XBT_DEBUG("See </job>");
 }
 
-void ETag_dax__parent(void)
+void ETag_dax__parent()
 {
   XBT_DEBUG("See </parent>");
 }
 
-void ETag_dax__uses(void)
+void ETag_dax__uses()
 {
   XBT_DEBUG("See </uses>");
 }
index 5a35d52..e9ebab0 100644 (file)
@@ -60,7 +60,9 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
   xbt_assert(in_file != nullptr, "Failed to open file: %s", filename);
 
   unsigned int i;
-  SD_task_t root, end, task;
+  SD_task_t root;
+  SD_task_t end;
+  SD_task_t task;
   xbt_dict_t computers;
   xbt_dynar_t computer = nullptr;
   xbt_dict_cursor_t dict_cursor;
@@ -78,9 +80,9 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
   Agnode_t *node = nullptr;
   for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) {
     char *name = agnameof(node);
-    double amount = atof(agget(node, (char *) "size"));
-
-    if (!(task = (SD_task_t)xbt_dict_get_or_null(jobs, name))) {
+    double amount = atof(agget(node, (char*)"size"));
+    task = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, name));
+    if (task == nullptr) {
       if (seq_or_par == sequential){
         XBT_DEBUG("See <job id=%s amount =%.0f>", name, amount);
         task = SD_task_create_comp_seq(name, nullptr , amount);
@@ -159,17 +161,17 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
     xbt_dynar_sort(edges, edge_compare);
 
     xbt_dynar_foreach(edges, i, edge) {
-      SD_task_t src, dst;
       char *src_name=agnameof(agtail(edge)), *dst_name=agnameof(aghead(edge));
       double size = atof(agget(edge, (char *) "size"));
 
-      src = (SD_task_t)xbt_dict_get_or_null(jobs, src_name);
-      dst = (SD_task_t)xbt_dict_get_or_null(jobs, dst_name);
+      SD_task_t src = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, src_name));
+      SD_task_t dst = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, dst_name));
 
       if (size > 0) {
         char *name = bprintf("%s->%s", src_name, dst_name);
         XBT_DEBUG("See <transfer id=%s amount = %.0f>", name, size);
-        if (!(task = (SD_task_t)xbt_dict_get_or_null(jobs, name))) {
+        task = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, name));
+        if (task == nullptr) {
           if (seq_or_par == sequential)
             task = SD_task_create_comm_e2e(name, nullptr , size);
           else
index 93d7cb6..7579f31 100644 (file)
@@ -31,8 +31,6 @@ SD_global_t sd_global = nullptr;
  */
 void SD_init(int *argc, char **argv)
 {
-  TRACE_global_init(argc, argv);
-
   xbt_assert(sd_global == nullptr, "SD_init() already called");
 
   sd_global = xbt_new(s_SD_global_t, 1);
@@ -41,7 +39,7 @@ void SD_init(int *argc, char **argv)
   sd_global->task_mallocator=xbt_mallocator_new(65536, SD_task_new_f, SD_task_free_f, SD_task_recycle_f);
 
   sd_global->initial_tasks = new std::set<SD_task_t>();
-  sd_global->executable_tasks = new std::set<SD_task_t>();
+  sd_global->runnable_tasks = new std::set<SD_task_t>();
   sd_global->completed_tasks = new std::set<SD_task_t>();
   sd_global->return_set = xbt_dynar_new(sizeof(SD_task_t), nullptr);
 
@@ -117,28 +115,26 @@ void SD_create_environment(const char *platform_file)
 
 xbt_dynar_t SD_simulate(double how_long) {
   /* we stop the simulation when total_time >= how_long */
-  double total_time = 0.0;
-  SD_task_t task, dst;
+  SD_task_t task;
+  SD_task_t dst;
   surf_action_t action;
   unsigned int iter;
 
   XBT_VERB("Run simulation for %f seconds", how_long);
-  sd_global->watch_point_reached = 0;
+  sd_global->watch_point_reached = false;
 
   xbt_dynar_reset(sd_global->return_set);
 
   /* explore the runnable tasks */
-  std::set<SD_task_t>::iterator it=sd_global->executable_tasks->begin();
-  while(it != sd_global->executable_tasks->end()){
-    task = *it;
-    it++;
+  while(!sd_global->runnable_tasks->empty()){
+    task = *(sd_global->runnable_tasks->begin());
     XBT_VERB("Executing task '%s'", SD_task_get_name(task));
     SD_task_run(task);
-    xbt_dynar_push(sd_global->return_set, &task);
   }
 
   /* main loop */
   double elapsed_time = 0.0;
+  double total_time = 0.0;
   while (elapsed_time >= 0.0 && (how_long < 0.0 || 0.00001 < (how_long -total_time)) &&
          !sd_global->watch_point_reached) {
     surf_model_t model = nullptr;
@@ -154,13 +150,8 @@ xbt_dynar_t SD_simulate(double how_long) {
     xbt_dynar_foreach(all_existing_models, iter, model) {
       while ((action = surf_model_extract_done_action_set(model))) {
         task = static_cast<SD_task_t>(action->getData());
-        task->start_time = task->surf_action->getStartTime();
-
-        task->finish_time = surf_get_clock();
         XBT_VERB("Task '%s' done", SD_task_get_name(task));
         SD_task_set_state(task, SD_DONE);
-        task->surf_action->unref();
-        task->surf_action = nullptr;
 
         /* the state has changed. Add it only if it's the first change */
         if (xbt_dynar_member(sd_global->return_set, &task) == 0) {
@@ -168,80 +159,65 @@ xbt_dynar_t SD_simulate(double how_long) {
         }
 
         /* remove the dependencies after this task */
-        for (std::set<SD_task_t>::iterator it=task->successors->begin(); it!=task->successors->end(); ++it){
-          dst=*it;
-          dst->unsatisfied_dependencies--;
-          if (dst->is_not_ready > 0)
-            dst->is_not_ready--;
-          XBT_DEBUG("Released a dependency on %s: %d remain(s). Became schedulable if %d=0",
-             SD_task_get_name(dst), dst->unsatisfied_dependencies, dst->is_not_ready);
-          if (dst->unsatisfied_dependencies == 0) {
-            if (SD_task_get_state(dst) == SD_SCHEDULED)
-              SD_task_set_state(dst, SD_RUNNABLE);
-            else
-              SD_task_set_state(dst, SD_SCHEDULABLE);
-          }
+        for (std::set<SD_task_t>::iterator succ = task->successors->begin(); succ != task->successors->end(); ++succ){
+          (*succ)->predecessors->erase(task);
+          (*succ)->inputs->erase(task);
+          XBT_DEBUG("Release dependency on %s: %zu remain(s). Becomes schedulable if %zu=0", SD_task_get_name((*succ)),
+              (*succ)->predecessors->size()+(*succ)->inputs->size(), (*succ)->predecessors->size());
 
-          if (SD_task_get_state(dst) == SD_NOT_SCHEDULED && dst->is_not_ready == 0) {
-            SD_task_set_state(dst, SD_SCHEDULABLE);
-          }
-          if (SD_task_get_state(dst) == SD_RUNNABLE && !sd_global->watch_point_reached) {
-            XBT_VERB("Executing task '%s'", SD_task_get_name(dst));
-            SD_task_run(dst);
-            xbt_dynar_push(sd_global->return_set, &dst);
+          if (SD_task_get_state((*succ)) == SD_NOT_SCHEDULED && (*succ)->predecessors->empty())
+            SD_task_set_state((*succ), SD_SCHEDULABLE);
+
+          if (SD_task_get_state((*succ)) == SD_SCHEDULED && (*succ)->predecessors->empty() && (*succ)->inputs->empty())
+            SD_task_set_state((*succ), SD_RUNNABLE);
+
+          if (SD_task_get_state((*succ)) == SD_RUNNABLE && !sd_global->watch_point_reached) {
+            XBT_VERB("Executing task '%s'", SD_task_get_name((*succ)));
+            SD_task_run((*succ));
           }
         }
+        task->successors->clear();
 
         for (std::set<SD_task_t>::iterator it=task->outputs->begin(); it!=task->outputs->end(); ++it){
           dst=*it;
-          dst->unsatisfied_dependencies = 0;
-          dst->is_not_ready = 0;
+          dst->start_time = task->finish_time;
+          dst->predecessors->erase(task);
           if (SD_task_get_state(dst) == SD_SCHEDULED)
              SD_task_set_state(dst, SD_RUNNABLE);
           else
              SD_task_set_state(dst, SD_SCHEDULABLE);
-          SD_task_t comm_dst = *(dst->successors->begin());
-          if (SD_task_get_state(comm_dst) == SD_NOT_SCHEDULED && comm_dst->is_not_ready > 0) {
-            comm_dst->is_not_ready--;
-
-            XBT_DEBUG("%s is a transfer, %s may be ready now if %d=0",
-                SD_task_get_name(dst), SD_task_get_name(comm_dst), comm_dst->is_not_ready);
 
-            if (comm_dst->is_not_ready == 0) {
-              SD_task_set_state(comm_dst, SD_SCHEDULABLE);
-            }
+          SD_task_t comm_dst = *(dst->successors->begin());
+          if (SD_task_get_state(comm_dst) == SD_NOT_SCHEDULED && comm_dst->predecessors->empty()){
+            XBT_DEBUG("%s is a transfer, %s may be ready now if %zu=0",
+                SD_task_get_name(dst), SD_task_get_name(comm_dst), comm_dst->predecessors->size());
+            SD_task_set_state(comm_dst, SD_SCHEDULABLE);
           }
           if (SD_task_get_state(dst) == SD_RUNNABLE && !sd_global->watch_point_reached) {
             XBT_VERB("Executing task '%s'", SD_task_get_name(dst));
             SD_task_run(dst);
-            xbt_dynar_push(sd_global->return_set, &dst);
           }
         }
+        task->outputs->clear();
       }
 
       /* let's see which tasks have just failed */
       while ((action = surf_model_extract_failed_action_set(model))) {
         task = static_cast<SD_task_t>(action->getData());
-        task->start_time = task->surf_action->getStartTime();
-        task->finish_time = surf_get_clock();
         XBT_VERB("Task '%s' failed", SD_task_get_name(task));
         SD_task_set_state(task, SD_FAILED);
-        action->unref();
-        task->surf_action = nullptr;
-
         xbt_dynar_push(sd_global->return_set, &task);
       }
     }
   }
 
-  if (!sd_global->watch_point_reached && how_long<0 && !sd_global->initial_tasks->empty()) {
+  if (!sd_global->watch_point_reached && how_long < 0 && !sd_global->initial_tasks->empty()) {
     XBT_WARN("Simulation is finished but %zu tasks are still not done", sd_global->initial_tasks->size());
     static const char* state_names[] =
       { "SD_NOT_SCHEDULED", "SD_SCHEDULABLE", "SD_SCHEDULED", "SD_RUNNABLE", "SD_RUNNING", "SD_DONE","SD_FAILED" };
-    for (std::set<SD_task_t>::iterator it=sd_global->initial_tasks->begin();
-         it!=sd_global->initial_tasks->end(); ++it){
-      task = *it;
-      XBT_WARN("%s is in %s state", SD_task_get_name(task), state_names[SD_task_get_state(task)]);
+    for (std::set<SD_task_t>::iterator t = sd_global->initial_tasks->begin(); t != sd_global->initial_tasks->end();
+         ++t){
+      XBT_WARN("%s is in %s state", SD_task_get_name(*t), state_names[SD_task_get_state(*t)]);
     }
   }
 
@@ -275,7 +251,7 @@ void SD_exit()
 
   xbt_mallocator_free(sd_global->task_mallocator);
   delete sd_global->initial_tasks;
-  delete sd_global->executable_tasks;
+  delete sd_global->runnable_tasks;
   delete sd_global->completed_tasks;
   xbt_dynar_free_container(&(sd_global->return_set));
   xbt_free(sd_global);
index 9b677f8..33d2b5d 100644 (file)
@@ -52,9 +52,6 @@ void SD_task_recycle_f(void *t)
   task->watch_points = 0;
 
   /* dependencies */
-  task->unsatisfied_dependencies = 0;
-  task->is_not_ready = 0;
-
   task->inputs->clear();
   task->outputs->clear();
   task->predecessors->clear();
@@ -288,7 +285,7 @@ void SD_task_set_data(SD_task_t task, void *data)
 void SD_task_set_rate(SD_task_t task, double rate)
 {
   xbt_assert(task->kind == SD_TASK_COMM_E2E, "The rate can be modified for end-to-end communications only.");
-  if(task->start_time<0) {
+  if(task->state < SD_RUNNING) {
     task->rate = rate;
   } else {
     XBT_WARN("Task %p has started. Changing rate is ineffective.", task);
@@ -313,6 +310,7 @@ e_SD_task_state_t SD_task_get_state(SD_task_t task)
 void SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state)
 {
   std::set<SD_task_t>::iterator idx;
+  XBT_DEBUG("Set state of '%s' to %d", task->name, new_state);
   switch (new_state) {
   case SD_NOT_SCHEDULED:
   case SD_SCHEDULABLE:
@@ -324,22 +322,25 @@ void SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state)
   case SD_SCHEDULED:
     if (SD_task_get_state(task) == SD_RUNNABLE){
       sd_global->initial_tasks->insert(task);
-      sd_global->executable_tasks->erase(task);
+      sd_global->runnable_tasks->erase(task);
     }
     break;
   case SD_RUNNABLE:
     idx = sd_global->initial_tasks->find(task);
     if (idx != sd_global->initial_tasks->end()) {
-      sd_global->executable_tasks->insert(*idx);
+      sd_global->runnable_tasks->insert(*idx);
       sd_global->initial_tasks->erase(idx);
     }
     break;
   case SD_RUNNING:
-    sd_global->executable_tasks->erase(task);
+    sd_global->runnable_tasks->erase(task);
     break;
   case SD_DONE:
     sd_global->completed_tasks->insert(task);
+    task->start_time = task->surf_action->getStartTime();
     task->finish_time = task->surf_action->getFinishTime();
+    task->surf_action->unref();
+    task->surf_action = nullptr;
     task->remains = 0;
 #if HAVE_JEDULE
     jedule_log_sd_event(task);
@@ -347,6 +348,10 @@ void SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state)
     break;
   case SD_FAILED:
     sd_global->completed_tasks->insert(task);
+    task->start_time = task->surf_action->getStartTime();
+    task->finish_time = surf_get_clock();
+    task->surf_action->unref();
+    task->surf_action = nullptr;
     break;
   default:
     xbt_die( "Invalid state");
@@ -356,7 +361,7 @@ void SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state)
 
   if (task->watch_points & new_state) {
     XBT_VERB("Watch point reached with task '%s'!", SD_task_get_name(task));
-    sd_global->watch_point_reached = 1;
+    sd_global->watch_point_reached = true;
     SD_task_unwatch(task, new_state);   /* remove the watch point */
   }
 }
@@ -531,13 +536,10 @@ void SD_task_dump(SD_task_t task)
     }
   }
 
-  if (task->category)
-    XBT_INFO("  - tracing category: %s", task->category);
-
   XBT_INFO("  - amount: %.0f", SD_task_get_amount(task));
   if (task->kind == SD_TASK_COMP_PAR_AMDAHL)
     XBT_INFO("  - alpha: %.2f", task->alpha);
-  XBT_INFO("  - Dependencies to satisfy: %d", task->unsatisfied_dependencies);
+  XBT_INFO("  - Dependencies to satisfy: %zu", task->inputs->size()+ task->predecessors->size());
   if ((task->inputs->size()+ task->predecessors->size()) > 0) {
     XBT_INFO("  - pre-dependencies:");
     for (std::set<SD_task_t>::iterator it=task->predecessors->begin(); it!=task->predecessors->end(); ++it)
@@ -636,9 +638,6 @@ void SD_task_dependency_add(const char *name, void *data, SD_task_t src, SD_task
     dst->predecessors->insert(src);
   }
 
-  dst->unsatisfied_dependencies++;
-  dst->is_not_ready++;
-
   /* if the task was runnable, the task goes back to SD_SCHEDULED because of the new dependency*/
   if (SD_task_get_state(dst) == SD_RUNNABLE) {
     XBT_DEBUG("SD_task_dependency_add: %s was runnable and becomes scheduled!", SD_task_get_name(dst));
@@ -680,7 +679,6 @@ int SD_task_dependency_exists(SD_task_t src, SD_task_t dst)
  */
 void SD_task_dependency_remove(SD_task_t src, SD_task_t dst)
 {
-
   XBT_DEBUG("SD_task_dependency_remove: src = %s, dst = %s", SD_task_get_name(src), SD_task_get_name(dst));
 
   if (src->successors->find(dst) == src->successors->end() &&
@@ -688,12 +686,6 @@ void SD_task_dependency_remove(SD_task_t src, SD_task_t dst)
     THROWF(arg_error, 0, "No dependency found between task '%s' and '%s': task '%s' is not a successor of task '%s'",
            SD_task_get_name(src), SD_task_get_name(dst), SD_task_get_name(dst), SD_task_get_name(src));
 
-  if (dst->predecessors->find(src) != dst->predecessors->end() ||
-      dst->inputs->find(src) != dst->inputs->end()){
-    dst->unsatisfied_dependencies--;
-    dst->is_not_ready--;
-  }
-
   e_SD_task_kind_t src_kind = SD_task_get_kind(src);
   e_SD_task_kind_t dst_kind = SD_task_get_kind(dst);
   if (src_kind == SD_TASK_COMM_E2E || src_kind == SD_TASK_COMM_PAR_MXN_1D_BLOCK){
@@ -713,15 +705,8 @@ void SD_task_dependency_remove(SD_task_t src, SD_task_t dst)
   }
 
   /* if the task was scheduled and dependencies are satisfied, we can make it runnable */
-  if (dst->unsatisfied_dependencies == 0) {
-    if (SD_task_get_state(dst) == SD_SCHEDULED)
-      SD_task_set_state(dst, SD_RUNNABLE);
-    else
-      SD_task_set_state(dst, SD_SCHEDULABLE);
-  }
-
-  if (dst->is_not_ready == 0)
-    SD_task_set_state(dst, SD_SCHEDULABLE);
+  if (dst->predecessors->empty() && dst->inputs->empty() && SD_task_get_state(dst) == SD_SCHEDULED)
+    SD_task_set_state(dst, SD_RUNNABLE);
 }
 
 /**
@@ -802,7 +787,7 @@ static inline void SD_task_do_schedule(SD_task_t task)
   if (SD_task_get_state(task) > SD_SCHEDULABLE)
     THROWF(arg_error, 0, "Task '%s' has already been scheduled", SD_task_get_name(task));
 
-  if (task->unsatisfied_dependencies == 0)
+  if (task->predecessors->empty() && task->inputs->empty())
     SD_task_set_state(task, SD_RUNNABLE);
   else
     SD_task_set_state(task, SD_SCHEDULED);
@@ -884,7 +869,7 @@ void SD_task_unschedule(SD_task_t task)
     /* the task should become SD_FAILED */
     task->surf_action->cancel();
   else {
-    if (task->unsatisfied_dependencies == 0)
+    if (task->predecessors->empty() && task->inputs->empty())
       SD_task_set_state(task, SD_SCHEDULABLE);
     else
       SD_task_set_state(task, SD_NOT_SCHEDULED);
@@ -923,11 +908,9 @@ void SD_task_run(SD_task_t task)
 
   XBT_DEBUG("surf_action = %p", task->surf_action);
 
-  if (task->category)
-    TRACE_surf_action(task->surf_action, task->category);
-
   __SD_task_destroy_scheduling_data(task);      /* now the scheduling data are not useful anymore */
   SD_task_set_state(task, SD_RUNNING);
+  xbt_dynar_push(sd_global->return_set, &task);
 }
 
 /**
index 331a2c3..906205e 100644 (file)
@@ -23,7 +23,7 @@ typedef struct SD_global {
   bool watch_point_reached;      /* has a task just reached a watch point? */
 
   std::set<SD_task_t> *initial_tasks;
-  std::set<SD_task_t> *executable_tasks;
+  std::set<SD_task_t> *runnable_tasks;
   std::set<SD_task_t> *completed_tasks;
 
   xbt_dynar_t return_set;
@@ -49,9 +49,6 @@ typedef struct SD_task {
   int marked;                   /* used to check if the task DAG has some cycle*/
 
   /* dependencies */
-  int unsatisfied_dependencies;
-  unsigned int is_not_ready;
-
   std::set<SD_task_t> *inputs;
   std::set<SD_task_t> *outputs;
   std::set<SD_task_t> *predecessors;
@@ -63,9 +60,6 @@ typedef struct SD_task {
   double *flops_amount;
   double *bytes_amount;
   double rate;
-
-  long long int counter;        /* task unique identifier for instrumentation */
-  char *category;               /* sd task category for instrumentation */
 } s_SD_task_t;
 
 /* SimDag private functions */
@@ -75,7 +69,7 @@ XBT_PRIVATE bool acyclic_graph_detail(xbt_dynar_t dag);
 XBT_PRIVATE void uniq_transfer_task_name(SD_task_t task);
 
 /* Task mallocator functions */
-XBT_PRIVATE void* SD_task_new_f(void);
+XBT_PRIVATE void* SD_task_new_f();
 XBT_PRIVATE void SD_task_recycle_f(void *t);
 XBT_PRIVATE void SD_task_free_f(void *t);
 
index 2742d6d..8cf08c4 100644 (file)
@@ -773,11 +773,11 @@ unsigned int simcall_comm_waitany(xbt_dynar_t comms, double timeout)
 /**
  * \ingroup simix_comm_management
  */
-int simcall_comm_testany(xbt_dynar_t comms)
+int simcall_comm_testany(smx_synchro_t* comms, size_t count)
 {
-  if (xbt_dynar_is_empty(comms))
+  if (count == 0)
     return -1;
-  return simcall_BODY_comm_testany(comms);
+  return simcall_BODY_comm_testany(comms, count);
 }
 
 /**
index e74bb3b..dede08b 100644 (file)
@@ -696,11 +696,17 @@ static inline void simcall_comm_test__set__result(smx_simcall_t simcall, int res
     simgrid::simix::marshal<int>(simcall->result, result);
 }
 
-static inline xbt_dynar_t simcall_comm_testany__get__comms(smx_simcall_t simcall) {
-  return simgrid::simix::unmarshal<xbt_dynar_t>(simcall->args[0]);
+static inline smx_synchro_t* simcall_comm_testany__get__comms(smx_simcall_t simcall) {
+  return simgrid::simix::unmarshal<smx_synchro_t*>(simcall->args[0]);
 }
-static inline void simcall_comm_testany__set__comms(smx_simcall_t simcall, xbt_dynar_t arg) {
-    simgrid::simix::marshal<xbt_dynar_t>(simcall->args[0], arg);
+static inline void simcall_comm_testany__set__comms(smx_simcall_t simcall, smx_synchro_t* arg) {
+    simgrid::simix::marshal<smx_synchro_t*>(simcall->args[0], arg);
+}
+static inline size_t simcall_comm_testany__get__count(smx_simcall_t simcall) {
+  return simgrid::simix::unmarshal<size_t>(simcall->args[1]);
+}
+static inline void simcall_comm_testany__set__count(smx_simcall_t simcall, size_t arg) {
+    simgrid::simix::marshal<size_t>(simcall->args[1], arg);
 }
 static inline int simcall_comm_testany__get__result(smx_simcall_t simcall){
     return simgrid::simix::unmarshal<int>(simcall->result);
@@ -1188,7 +1194,7 @@ XBT_PRIVATE smx_synchro_t simcall_HANDLER_comm_irecv(smx_simcall_t simcall, smx_
 XBT_PRIVATE void simcall_HANDLER_comm_waitany(smx_simcall_t simcall, xbt_dynar_t comms, double timeout);
 XBT_PRIVATE void simcall_HANDLER_comm_wait(smx_simcall_t simcall, smx_synchro_t comm, double timeout);
 XBT_PRIVATE void simcall_HANDLER_comm_test(smx_simcall_t simcall, smx_synchro_t comm);
-XBT_PRIVATE void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t comms);
+XBT_PRIVATE void simcall_HANDLER_comm_testany(smx_simcall_t simcall, smx_synchro_t* comms, size_t count);
 XBT_PRIVATE smx_mutex_t simcall_HANDLER_mutex_init(smx_simcall_t simcall);
 XBT_PRIVATE void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex);
 XBT_PRIVATE int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex);
index e1cbb57..1910808 100644 (file)
@@ -239,10 +239,10 @@ inline static int simcall_BODY_comm_test(smx_synchro_t comm) {
     return simcall<int, smx_synchro_t>(SIMCALL_COMM_TEST, comm);
   }
   
-inline static int simcall_BODY_comm_testany(xbt_dynar_t comms) {
+inline static int simcall_BODY_comm_testany(smx_synchro_t* comms, size_t count) {
     /* Go to that function to follow the code flow through the simcall barrier */
-    if (0) simcall_HANDLER_comm_testany(&SIMIX_process_self()->simcall, comms);
-    return simcall<int, xbt_dynar_t>(SIMCALL_COMM_TESTANY, comms);
+    if (0) simcall_HANDLER_comm_testany(&SIMIX_process_self()->simcall, comms, count);
+    return simcall<int, smx_synchro_t*, size_t>(SIMCALL_COMM_TESTANY, comms, count);
   }
   
 inline static smx_mutex_t simcall_BODY_mutex_init() {
index 226dc13..3e13053 100644 (file)
@@ -266,7 +266,7 @@ case SIMCALL_COMM_TEST:
       break;
 
 case SIMCALL_COMM_TESTANY:
-      simcall_HANDLER_comm_testany(simcall, simgrid::simix::unmarshal<xbt_dynar_t>(simcall->args[0]));
+      simcall_HANDLER_comm_testany(simcall, simgrid::simix::unmarshal<smx_synchro_t*>(simcall->args[0]), simgrid::simix::unmarshal<size_t>(simcall->args[1]));
       break;
 
 case SIMCALL_MUTEX_INIT:
index 185f440..476dd57 100644 (file)
@@ -75,7 +75,7 @@ smx_synchro_t comm_irecv(smx_process_t receiver, smx_mailbox_t mbox, void* dst_b
 int           comm_waitany(xbt_dynar_t comms, double timeout) [[block]];
 void          comm_wait(smx_synchro_t comm, double timeout) [[block]];
 int           comm_test(smx_synchro_t comm) [[block]];
-int           comm_testany(xbt_dynar_t comms) [[block]];
+int           comm_testany(smx_synchro_t* comms, size_t count) [[block]];
 
 smx_mutex_t mutex_init();
 void        mutex_lock(smx_mutex_t mutex) [[block]];
index dd86baa..25783eb 100644 (file)
@@ -3,6 +3,8 @@
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
+#include <algorithm>
+
 #include <boost/range/algorithm.hpp>
 
 #include <xbt/ex.hpp>
@@ -443,10 +445,9 @@ void simcall_HANDLER_comm_test(smx_simcall_t simcall, smx_synchro_t synchro)
   }
 }
 
-void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
+void simcall_HANDLER_comm_testany(
+  smx_simcall_t simcall, simgrid::simix::Synchro* comms[], size_t count)
 {
-  unsigned int cursor;
-  smx_synchro_t synchro;
   // The default result is -1 -- this means, "nothing is ready".
   // It can be changed below, but only if something matches.
   simcall_comm_testany__set__result(simcall, -1);
@@ -456,7 +457,7 @@ void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
     if(idx == -1){
       SIMIX_simcall_answer(simcall);
     }else{
-      synchro = xbt_dynar_get_as(synchros, idx, smx_synchro_t);
+      simgrid::simix::Synchro* synchro = comms[idx];
       simcall_comm_testany__set__result(simcall, idx);
       synchro->simcalls.push_back(simcall);
       synchro->state = SIMIX_DONE;
@@ -465,9 +466,10 @@ void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
     return;
   }
 
-  xbt_dynar_foreach(simcall_comm_testany__get__comms(simcall), cursor,synchro) {
+  for (std::size_t i = 0; i != count; ++i) {
+    simgrid::simix::Synchro* synchro = comms[i];
     if (synchro->state != SIMIX_WAITING && synchro->state != SIMIX_RUNNING) {
-      simcall_comm_testany__set__result(simcall, cursor);
+      simcall_comm_testany__set__result(simcall, i);
       synchro->simcalls.push_back(simcall);
       SIMIX_comm_finish(synchro);
       return;
@@ -685,7 +687,14 @@ void SIMIX_comm_finish(smx_synchro_t synchro)
           e.value = xbt_dynar_search(simcall_comm_waitany__get__comms(simcall), &synchro);
         }
         else if (simcall->call == SIMCALL_COMM_TESTANY) {
-          e.value = xbt_dynar_search(simcall_comm_testany__get__comms(simcall), &synchro);
+          e.value = -1;
+          auto comms = simcall_comm_testany__get__comms(simcall);
+          auto count = simcall_comm_testany__get__count(simcall);
+          auto element = std::find(comms, comms + count, synchro);
+          if (element == comms + count)
+            e.value = -1;
+          else
+            e.value = element - comms;
         }
         simcall->issuer->exception = std::make_exception_ptr(e);
       }
index 3a98771..d60b2bf 100644 (file)
@@ -773,16 +773,18 @@ int smpi_mpi_test(MPI_Request * request, MPI_Status * status) {
 
 int smpi_mpi_testany(int count, MPI_Request requests[], int *index, MPI_Status * status)
 {
-  xbt_dynar_t comms;
+  std::vector<simgrid::simix::Synchro*> comms;
+  comms.reserve(count);
+
   int i;
   int flag = 0;
 
   *index = MPI_UNDEFINED;
-  comms = xbt_dynar_new(sizeof(smx_synchro_t), nullptr);
+
   std::vector<int> map; /** Maps all matching comms back to their location in requests **/
   for(i = 0; i < count; i++) {
     if ((requests[i] != MPI_REQUEST_NULL) && requests[i]->action && !(requests[i]->flags & PREPARED)) {
-       xbt_dynar_push(comms, &requests[i]->action);
+       comms.push_back(requests[i]->action);
        map.push_back(i);
     }
   }
@@ -792,7 +794,7 @@ int smpi_mpi_testany(int count, MPI_Request requests[], int *index, MPI_Status *
     if(smpi_test_sleep > 0) 
       simcall_process_sleep(nsleeps*smpi_test_sleep);
 
-    i = simcall_comm_testany(comms); // The i-th element in comms matches!
+    i = simcall_comm_testany(comms.data(), comms.size()); // The i-th element in comms matches!
     if (i != -1) { // -1 is not MPI_UNDEFINED but a SIMIX return code. (nothing matches)
       *index = map[i]; 
       finish_wait(&requests[*index], status);
@@ -809,7 +811,6 @@ int smpi_mpi_testany(int count, MPI_Request requests[], int *index, MPI_Status *
       flag = 1;
       smpi_empty_status(status);
   }
-  xbt_dynar_free(&comms);
 
   return flag;
 }
index 313b39d..e79fbb0 100644 (file)
@@ -90,7 +90,7 @@ namespace routing {
  * \param route where to store the list of links.
  *              If *route=nullptr, create a short lived dynar. Else, fill the provided dynar
  * \param latency where to store the latency experienced on the path (or nullptr if not interested)
- *                It is the caller responsability to initialize latency to 0 (we add to provided route)
+ *                It is the caller responsibility to initialize latency to 0 (we add to provided route)
  * \pre route!=nullptr
  *
  * walk through the routing components tree and find a route between hosts
index 6e9cf0c..230e330 100644 (file)
@@ -4,9 +4,15 @@
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
+#include <cstdlib>
+
+#include <atomic>
 #include <exception>
+#include <string>
 #include <typeinfo>
+#include <vector>
 #include <memory>
+#include <mutex>
 
 #include <xbt/backtrace.hpp>
 #include <xbt/exception.hpp>
@@ -68,5 +74,66 @@ void logException(
   }
 }
 
+static void showBacktrace(std::vector<xbt_backtrace_location_t>& bt)
+{
+  std::vector<std::string> res = resolveBacktrace(&bt[0], bt.size());
+  XBT_LOG(xbt_log_priority_critical, "Current backtrace:");
+  for (std::string const& s : res)
+    XBT_LOG(xbt_log_priority_critical, "  -> %s", s.c_str());
 }
+
+static std::terminate_handler previous_terminate_handler = nullptr;
+
+static void handler()
+{
+  // Avoid doing crazy things if we get an uncaught exception inside
+  // an uncaught exception
+  static std::atomic_flag lock = ATOMIC_FLAG_INIT;
+  if (lock.test_and_set()) {
+    XBT_ERROR("Multiple uncaught exceptions");
+    std::abort();
+  }
+
+  // Get the current backtrace and exception
+  auto e = std::current_exception();
+  auto bt = backtrace();
+  try {
+    std::rethrow_exception(e);
+  }
+
+  // We manage C++ exception ourselves
+  catch (std::exception& e) {
+    logException(xbt_log_priority_critical, "Uncaught exception", e);
+    showBacktrace(bt);
+    std::abort();
+  }
+
+  // We don't know how to manage other exceptions
+  catch (...) {
+    // If there was another handler let's delegate to it
+    if (previous_terminate_handler)
+      previous_terminate_handler();
+    else {
+      XBT_ERROR("Unknown uncaught exception");
+      showBacktrace(bt);
+      std::abort();
+    }
+  }
+
+}
+
+void installExceptionHandler()
+{
+  static std::once_flag handler_flag;
+  std::call_once(handler_flag, [] {
+    previous_terminate_handler = std::set_terminate(handler);
+  });
+}
+
+}
+}
+
+void xbt_set_terminate()
+{
+  simgrid::xbt::installExceptionHandler();
 }
index 3451b60..13ec9e3 100644 (file)
@@ -137,6 +137,8 @@ static void xbt_postexit(void)
 /** @brief Initialize the xbt mechanisms. */
 void xbt_init(int *argc, char **argv)
 {
+  xbt_set_terminate();
+
   if (xbt_initialized++) {
     XBT_DEBUG("XBT was initialized %d times.", xbt_initialized);
     return;