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
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
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 */
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]);
best_host = hosts[i];
}
}
+ xbt_free(hosts);
return best_host;
}
/* 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]);
for (cursor = 0; cursor < total_nhosts; cursor++)
sg_host_free_attribute(hosts[cursor]);
+ xbt_free(hosts);
/* exit */
SD_exit();
return 0;
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);
*/
#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_ */
e_xbt_log_priority_t priority,
const char* context, std::exception const& exception);
+XBT_PUBLIC(void) installExceptionHandler();
+
}
}
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;
}
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;
}
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:
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;
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;
}
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)
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)));
}
{
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) {
throw;
}
}
- xbt_dynar_free(&s_comms);
if (finished_index != -1) {
comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
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>");
}
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;
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);
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
*/
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);
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);
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;
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) {
}
/* 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)]);
}
}
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);
task->watch_points = 0;
/* dependencies */
- task->unsatisfied_dependencies = 0;
- task->is_not_ready = 0;
-
task->inputs->clear();
task->outputs->clear();
task->predecessors->clear();
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);
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:
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);
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");
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 */
}
}
}
}
- 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)
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));
*/
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() &&
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){
}
/* 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);
}
/**
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);
/* 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);
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);
}
/**
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;
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;
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 */
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);
/**
* \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);
}
/**
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);
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);
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() {
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:
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]];
/* 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>
}
}
-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);
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;
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;
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);
}
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);
}
}
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);
flag = 1;
smpi_empty_status(status);
}
- xbt_dynar_free(&comms);
return flag;
}
* \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
/* 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>
}
}
+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();
}
/** @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;