+ /* If we are suspending ourselves, then just do not finish the simcall now */
+}
+
+smx_action_t SIMIX_process_suspend(smx_process_t process, smx_process_t issuer)
+{
+ xbt_assert((process != NULL), "Invalid parameters");
+
+ if (process->suspended) {
+ XBT_DEBUG("Process '%s' is already suspended", process->name);
+ return NULL;
+ }
+
+ process->suspended = 1;
+
+ /* If we are suspending another process, and it is waiting on an action,
+ suspend its action. */
+ if (process != issuer) {
+
+ if (process->waiting_action) {
+
+ switch (process->waiting_action->type) {
+
+ case SIMIX_ACTION_EXECUTE:
+ case SIMIX_ACTION_PARALLEL_EXECUTE:
+ SIMIX_host_execution_suspend(process->waiting_action);
+ break;
+
+ case SIMIX_ACTION_COMMUNICATE:
+ SIMIX_comm_suspend(process->waiting_action);
+ break;
+
+ case SIMIX_ACTION_SLEEP:
+ SIMIX_process_sleep_suspend(process->waiting_action);
+ break;
+
+ case SIMIX_ACTION_SYNCHRO:
+ /* Suspension is delayed to when the process is rescheduled. */
+ break;
+
+ default:
+ xbt_die("Internal error in SIMIX_process_suspend: unexpected action type %d",
+ (int)process->waiting_action->type);
+ }
+ return NULL;
+ } else {
+ /* Suspension is delayed to when the process is rescheduled. */
+ return NULL;
+ }
+ } else {
+ /* FIXME: computation size is zero. Is it okay that bound is zero ? */
+ return SIMIX_host_execute("suspend", process->smx_host, 0.0, 1.0, 0.0, 0);
+ }
+}
+
+void SIMIX_pre_process_resume(smx_simcall_t simcall, smx_process_t process){
+ SIMIX_process_resume(process, simcall->issuer);
+}
+
+void SIMIX_process_resume(smx_process_t process, smx_process_t issuer)
+{
+ XBT_IN("process = %p, issuer = %p", process, issuer);
+
+ if(process->context->iwannadie) {
+ XBT_VERB("Ignoring request to suspend a process that is currently dying.");
+ return;
+ }
+
+ if(!process->suspended) return;
+ process->suspended = 0;
+
+ /* If we are resuming another process, resume the action it was waiting for
+ if any. Otherwise add it to the list of process to run in the next round. */
+ if (process != issuer) {
+
+ if (process->waiting_action) {
+
+ switch (process->waiting_action->type) {
+
+ case SIMIX_ACTION_EXECUTE:
+ case SIMIX_ACTION_PARALLEL_EXECUTE:
+ SIMIX_host_execution_resume(process->waiting_action);
+ break;
+
+ case SIMIX_ACTION_COMMUNICATE:
+ SIMIX_comm_resume(process->waiting_action);
+ break;
+
+ case SIMIX_ACTION_SLEEP:
+ SIMIX_process_sleep_resume(process->waiting_action);
+ break;
+
+ case SIMIX_ACTION_SYNCHRO:
+ /* I cannot resume it now. This is delayed to when the process is rescheduled at
+ * the end of the synchro. */
+ break;
+
+ default:
+ xbt_die("Internal error in SIMIX_process_resume: unexpected action type %d",
+ (int)process->waiting_action->type);
+ }
+ }
+ } else XBT_WARN("Strange. Process %p is trying to resume himself.", issuer);
+
+ XBT_OUT();
+}
+
+int SIMIX_process_get_maxpid(void) {
+ return simix_process_maxpid;
+}
+
+int SIMIX_pre_process_count(smx_simcall_t simcall){
+ return SIMIX_process_count();
+}
+int SIMIX_process_count(void)
+{
+ return xbt_swag_size(simix_global->process_list);
+}
+
+int SIMIX_pre_process_get_PID(smx_simcall_t simcall, smx_process_t self){
+ return SIMIX_process_get_PID(self);
+}
+
+int SIMIX_process_get_PID(smx_process_t self){
+ if (self == NULL)
+ return 0;
+ else
+ return self->pid;
+}
+
+int SIMIX_pre_process_get_PPID(smx_simcall_t simcall, smx_process_t self){
+ return SIMIX_process_get_PPID(self);
+}
+
+int SIMIX_process_get_PPID(smx_process_t self){
+ if (self == NULL)
+ return 0;
+ else
+ return self->ppid;
+}
+
+void* SIMIX_pre_process_self_get_data(smx_simcall_t simcall, smx_process_t self){
+ return SIMIX_process_self_get_data(self);
+}
+
+void* SIMIX_process_self_get_data(smx_process_t self)
+{
+ xbt_assert(self == SIMIX_process_self(), "This is not the current process");
+
+ if (!self) {
+ return NULL;
+ }
+ return SIMIX_process_get_data(self);
+}
+
+void SIMIX_pre_process_set_data(smx_simcall_t simcall, smx_process_t process,
+ void *data){
+ SIMIX_process_set_data(process, data);
+}
+void SIMIX_process_self_set_data(smx_process_t self, void *data)
+{
+ xbt_assert(self == SIMIX_process_self(), "This is not the current process");
+
+ SIMIX_process_set_data(self, data);
+}
+
+void* SIMIX_pre_process_get_data(smx_simcall_t simcall, smx_process_t process){
+ return SIMIX_process_get_data(process);
+}
+void* SIMIX_process_get_data(smx_process_t process)
+{
+ return process->data;
+}
+
+void SIMIX_process_set_data(smx_process_t process, void *data)
+{
+ process->data = data;
+}
+
+smx_host_t SIMIX_pre_process_get_host(smx_simcall_t simcall, smx_process_t process){
+ return SIMIX_process_get_host(process);
+}
+smx_host_t SIMIX_process_get_host(smx_process_t process)
+{
+ return process->smx_host;
+}
+
+/* needs to be public and without simcall because it is called
+ by exceptions and logging events */
+const char* SIMIX_process_self_get_name(void) {
+
+ smx_process_t process = SIMIX_process_self();
+ if (process == NULL || process == simix_global->maestro_process)
+ return "";
+
+ return SIMIX_process_get_name(process);
+}
+
+const char* SIMIX_pre_process_get_name(smx_simcall_t simcall, smx_process_t process) {
+ return SIMIX_process_get_name(process);
+}
+const char* SIMIX_process_get_name(smx_process_t process)
+{
+ return process->name;
+}
+
+smx_process_t SIMIX_process_get_by_name(const char* name)
+{
+ smx_process_t proc;
+
+ xbt_swag_foreach(proc, simix_global->process_list)
+ {
+ if(!strcmp(name, proc->name))
+ return proc;
+ }
+ return NULL;
+}
+
+int SIMIX_pre_process_is_suspended(smx_simcall_t simcall, smx_process_t process){
+ return SIMIX_process_is_suspended(process);
+}
+int SIMIX_process_is_suspended(smx_process_t process)
+{
+ return process->suspended;
+}
+
+xbt_dict_t SIMIX_pre_process_get_properties(smx_simcall_t simcall, smx_process_t process){
+ return SIMIX_process_get_properties(process);
+}
+xbt_dict_t SIMIX_process_get_properties(smx_process_t process)
+{
+ return process->properties;
+}
+
+void SIMIX_pre_process_join(smx_simcall_t simcall, smx_process_t process, double timeout)
+{
+ smx_action_t action = SIMIX_process_join(simcall->issuer, process, timeout);
+ xbt_fifo_push(action->simcalls, simcall);
+ simcall->issuer->waiting_action = action;
+}
+
+static int SIMIX_process_join_finish(smx_process_exit_status_t status, smx_action_t action){
+ if (action->sleep.surf_sleep) {
+ surf_action_cancel(action->sleep.surf_sleep);
+
+ smx_simcall_t simcall;
+ while ((simcall = xbt_fifo_shift(action->simcalls))) {
+ simcall_process_sleep__set__result(simcall, SIMIX_DONE);
+ simcall->issuer->waiting_action = NULL;
+ if (simcall->issuer->suspended) {
+ XBT_DEBUG("Wait! This process is suspended and can't wake up now.");
+ simcall->issuer->suspended = 0;
+ SIMIX_pre_process_suspend(simcall, simcall->issuer);
+ } else {
+ SIMIX_simcall_answer(simcall);
+ }
+ }
+ surf_action_unref(action->sleep.surf_sleep);
+ action->sleep.surf_sleep = NULL;
+ }
+ xbt_mallocator_release(simix_global->action_mallocator, action);
+ return 0;
+}
+
+smx_action_t SIMIX_process_join(smx_process_t issuer, smx_process_t process, double timeout)
+{
+ smx_action_t res = SIMIX_process_sleep(issuer, timeout);
+ res->type = SIMIX_ACTION_JOIN;
+ SIMIX_process_on_exit(process, (int_f_pvoid_pvoid_t)SIMIX_process_join_finish, res);
+ return res;
+}
+
+void SIMIX_pre_process_sleep(smx_simcall_t simcall, double duration)
+{
+ if (MC_is_active()) {
+ MC_process_clock_add(simcall->issuer, duration);
+ simcall_process_sleep__set__result(simcall, SIMIX_DONE);
+ SIMIX_simcall_answer(simcall);
+ return;
+ }
+ smx_action_t action = SIMIX_process_sleep(simcall->issuer, duration);
+ xbt_fifo_push(action->simcalls, simcall);
+ simcall->issuer->waiting_action = action;
+}
+
+smx_action_t SIMIX_process_sleep(smx_process_t process, double duration)
+{
+ smx_action_t action;
+ smx_host_t host = process->smx_host;
+
+ /* check if the host is active */
+ if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) {
+ THROWF(host_error, 0, "Host %s failed, you cannot call this function",
+ sg_host_name(host));
+ }
+
+ action = xbt_mallocator_get(simix_global->action_mallocator);
+ action->type = SIMIX_ACTION_SLEEP;
+ action->name = NULL;
+#ifdef HAVE_TRACING
+ action->category = NULL;
+#endif
+
+ action->sleep.host = host;
+ action->sleep.surf_sleep =
+ surf_workstation_sleep(host, duration);
+
+ surf_action_set_data(action->sleep.surf_sleep, action);
+ XBT_DEBUG("Create sleep action %p", action);
+
+ return action;
+}
+
+void SIMIX_post_process_sleep(smx_action_t action)
+{
+ smx_simcall_t simcall;
+ e_smx_state_t state;
+ xbt_assert(action->type == SIMIX_ACTION_SLEEP || action->type == SIMIX_ACTION_JOIN);
+
+ while ((simcall = xbt_fifo_shift(action->simcalls))) {
+
+ switch(surf_action_get_state(action->sleep.surf_sleep)){
+ case SURF_ACTION_FAILED:
+ simcall->issuer->context->iwannadie = 1;
+ //SMX_EXCEPTION(simcall->issuer, host_error, 0, "Host failed");
+ state = SIMIX_SRC_HOST_FAILURE;
+ break;
+
+ case SURF_ACTION_DONE:
+ state = SIMIX_DONE;
+ break;
+
+ default:
+ THROW_IMPOSSIBLE;
+ break;
+ }
+ if (surf_resource_get_state(surf_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) {
+ simcall->issuer->context->iwannadie = 1;
+ }
+ simcall_process_sleep__set__result(simcall, state);
+ simcall->issuer->waiting_action = NULL;
+ if (simcall->issuer->suspended) {
+ XBT_DEBUG("Wait! This process is suspended and can't wake up now.");
+ simcall->issuer->suspended = 0;
+ SIMIX_pre_process_suspend(simcall, simcall->issuer);
+ } else {
+ SIMIX_simcall_answer(simcall);
+ }
+ }
+
+ SIMIX_process_sleep_destroy(action);
+}
+
+void SIMIX_process_sleep_destroy(smx_action_t action)
+{
+ XBT_DEBUG("Destroy action %p", action);
+ xbt_assert(action->type == SIMIX_ACTION_SLEEP || action->type == SIMIX_ACTION_JOIN);
+
+ if (action->sleep.surf_sleep) {
+ surf_action_unref(action->sleep.surf_sleep);
+ action->sleep.surf_sleep = NULL;
+ }
+ if (action->type == SIMIX_ACTION_SLEEP)
+ xbt_mallocator_release(simix_global->action_mallocator, action);
+}
+
+void SIMIX_process_sleep_suspend(smx_action_t action)
+{
+ xbt_assert(action->type == SIMIX_ACTION_SLEEP);
+ surf_action_suspend(action->sleep.surf_sleep);
+}
+
+void SIMIX_process_sleep_resume(smx_action_t action)
+{
+ XBT_DEBUG("Action state is %d on process_sleep_resume.", action->state);
+ xbt_assert(action->type == SIMIX_ACTION_SLEEP);
+ surf_action_resume(action->sleep.surf_sleep);