1 /* Copyright (c) 2007-2015. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include <boost/range/algorithm.hpp>
9 #include "src/surf/surf_interface.hpp"
10 #include "smx_private.h"
11 #include "xbt/sysdep.h"
15 #include "src/mc/mc_replay.h"
16 #include "src/mc/Client.hpp"
17 #include "src/msg/msg_private.h"
19 #include "src/simix/SynchroSleep.hpp"
20 #include "src/simix/SynchroRaw.hpp"
21 #include "src/simix/SynchroIo.hpp"
24 #include "src/smpi/private.h"
27 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix, "Logging specific to SIMIX (process)");
29 unsigned long simix_process_maxpid = 0;
32 * \brief Returns the current agent.
34 * This functions returns the currently running SIMIX process.
36 * \return The SIMIX process
38 smx_process_t SIMIX_process_self(void)
40 smx_context_t self_context = SIMIX_context_self();
42 return self_context ? self_context->process() : NULL;
46 * \brief Returns whether a process has pending asynchronous communications.
47 * \return true if there are asynchronous communications in this process
49 int SIMIX_process_has_pending_comms(smx_process_t process) {
51 return xbt_fifo_size(process->comms) > 0;
55 * \brief Moves a process to the list of processes to destroy.
57 void SIMIX_process_cleanup(smx_process_t process)
59 XBT_DEBUG("Cleanup process %s (%p), waiting synchro %p",
60 process->name.c_str(), process, process->waiting_synchro);
62 SIMIX_process_on_exit_runall(process);
64 /* Unregister from the kill timer if any */
65 if (process->kill_timer != NULL)
66 SIMIX_timer_remove(process->kill_timer);
68 xbt_os_mutex_acquire(simix_global->mutex);
70 /* cancel non-blocking communications */
71 smx_synchro_t synchro;
72 while ((synchro = (smx_synchro_t) xbt_fifo_pop(process->comms))) {
73 simgrid::simix::Comm *comm = static_cast<simgrid::simix::Comm*>(synchro);
75 /* make sure no one will finish the comm after this process is destroyed,
76 * because src_proc or dst_proc would be an invalid pointer */
79 if (comm->src_proc == process) {
80 XBT_DEBUG("Found an unfinished send comm %p (detached = %d), state %d, src = %p, dst = %p",
81 comm, comm->detached, (int)comm->state, comm->src_proc, comm->dst_proc);
82 comm->src_proc = NULL;
84 /* I'm not supposed to destroy a detached comm from the sender side, */
86 XBT_DEBUG("Don't destroy it since it's a detached comm and I'm the sender");
91 else if (comm->dst_proc == process){
92 XBT_DEBUG("Found an unfinished recv comm %p, state %d, src = %p, dst = %p",
93 comm, (int)comm->state, comm->src_proc, comm->dst_proc);
94 comm->dst_proc = NULL;
96 if (comm->detached && comm->src_proc != NULL) {
97 /* the comm will be freed right now, remove it from the sender */
98 xbt_fifo_remove(comm->src_proc->comms, comm);
103 xbt_die("Communication synchro %p is in my list but I'm not the sender nor the receiver", synchro);
107 XBT_DEBUG("%p should not be run anymore",process);
108 xbt_swag_remove(process, simix_global->process_list);
110 xbt_swag_remove(process, sg_host_simix(process->host)->process_list);
111 xbt_swag_insert(process, simix_global->process_to_destroy);
112 process->context->iwannadie = 0;
114 xbt_os_mutex_release(simix_global->mutex);
120 * Should be called some time to time to free the memory allocated for processes
121 * that have finished (or killed).
123 void SIMIX_process_empty_trash(void)
125 smx_process_t process = NULL;
127 while ((process = (smx_process_t) xbt_swag_extract(simix_global->process_to_destroy))) {
128 XBT_DEBUG("Getting rid of %p",process);
130 delete process->context;
132 /* Free the exception allocated at creation time */
133 free(process->running_ctx);
134 xbt_dict_free(&process->properties);
136 xbt_fifo_free(process->comms);
138 xbt_dynar_free(&process->on_exit);
147 void create_maestro(std::function<void()> code)
149 smx_process_t maestro = NULL;
150 /* Create maestro process and intilialize it */
151 maestro = new simgrid::simix::Process();
152 maestro->pid = simix_process_maxpid++;
155 maestro->data = nullptr;
156 maestro->running_ctx = (xbt_running_ctx_t*) xbt_malloc0(sizeof(xbt_running_ctx_t));
157 XBT_RUNNING_CTX_INITIALIZE(maestro->running_ctx);
160 maestro->context = SIMIX_context_new(std::function<void()>(), NULL, maestro);
163 xbt_die("simix is not initialized, please call MSG_init first");
165 simix_global->context_factory->create_maestro(code, maestro);
168 maestro->simcall.issuer = maestro;
169 simix_global->maestro_process = maestro;
176 * \brief Creates and runs the maestro process
178 void SIMIX_maestro_create(void (*code)(void*), void* data)
180 simgrid::simix::create_maestro(std::bind(code, data));
184 * \brief Stops a process.
186 * Stops the process, execute all the registered on_exit functions,
187 * register it to the list of the process to restart if needed
188 * and stops its context.
190 void SIMIX_process_stop(smx_process_t arg) {
191 /* execute the on_exit functions */
192 SIMIX_process_on_exit_runall(arg);
193 /* Add the process to the list of process to restart, only if the host is down */
194 if (arg->auto_restart && arg->host->isOff()) {
195 SIMIX_host_add_auto_restart_process(arg->host, arg->name.c_str(),
196 arg->code, arg->data,
197 sg_host_get_name(arg->host),
198 SIMIX_timer_get_date(arg->kill_timer),
202 XBT_DEBUG("Process %s (%s) is dead",
203 arg->name.c_str(), sg_host_get_name(arg->host));
204 arg->context->stop();
208 * \brief Internal function to create a process.
210 * This function actually creates the process.
211 * It may be called when a SIMCALL_PROCESS_CREATE simcall occurs,
212 * or directly for SIMIX internal purposes. The sure thing is that it's called from maestro context.
214 * \return the process created
216 smx_process_t SIMIX_process_create(
218 std::function<void()> code,
220 const char *hostname,
222 xbt_dict_t properties,
224 smx_process_t parent_process)
226 smx_process_t process = NULL;
227 sg_host_t host = sg_host_by_name(hostname);
229 XBT_DEBUG("Start process %s on host '%s'", name, hostname);
232 XBT_WARN("Cannot launch process '%s' on failed host '%s'", name,
237 process = new simgrid::simix::Process();
239 xbt_assert(code && host != NULL, "Invalid parameters");
241 process->pid = simix_process_maxpid++;
242 process->name = simgrid::xbt::string(name);
243 process->host = host;
244 process->data = data;
245 process->comms = xbt_fifo_new();
246 process->simcall.issuer = process;
247 /* Initiliaze data segment to default value */
248 SIMIX_segment_index_set(process, -1);
250 if (parent_process != NULL) {
251 process->ppid = SIMIX_process_get_PID(parent_process);
252 /* SMPI process have their own data segment and
253 each other inherit from their father */
255 if(smpi_privatize_global_variables){
256 if( parent_process->pid != 0){
257 SIMIX_segment_index_set(process, parent_process->segment_index);
259 SIMIX_segment_index_set(process, process->pid - 1);
267 /* Process data for auto-restart */
268 process->auto_restart = auto_restart;
269 process->code = code;
271 XBT_VERB("Create context %s", process->name.c_str());
272 process->context = SIMIX_context_new(
274 simix_global->cleanup_process_function, process);
276 process->running_ctx = (xbt_running_ctx_t*) xbt_malloc0(sizeof(xbt_running_ctx_t));
277 XBT_RUNNING_CTX_INITIALIZE(process->running_ctx);
280 MC_ignore_heap(process->running_ctx, sizeof(*process->running_ctx));
284 process->properties = properties;
286 /* Add the process to it's host process list */
287 xbt_swag_insert(process, sg_host_simix(host)->process_list);
289 XBT_DEBUG("Start context '%s'", process->name.c_str());
291 /* Now insert it in the global process list and in the process to run list */
292 xbt_swag_insert(process, simix_global->process_list);
293 XBT_DEBUG("Inserting %s(%s) in the to_run list",
294 process->name.c_str(), sg_host_get_name(host));
295 xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
297 if (kill_time > SIMIX_get_clock() && simix_global->kill_process_function) {
298 XBT_DEBUG("Process %s(%s) will be kill at time %f",
299 process->name.c_str(), sg_host_get_name(process->host), kill_time);
300 process->kill_timer = SIMIX_timer_set(kill_time, [=]() {
301 simix_global->kill_process_function(process);
305 /* Tracing the process creation */
306 TRACE_msg_process_create(process->name.c_str(), process->pid, process->host);
311 smx_process_t SIMIX_process_attach(
314 const char* hostname,
315 xbt_dict_t properties,
316 smx_process_t parent_process)
318 // This is mostly a copy/paste from SIMIX_process_new(),
319 // it'd be nice to share some code between those two functions.
321 sg_host_t host = sg_host_by_name(hostname);
322 XBT_DEBUG("Attach process %s on host '%s'", name, hostname);
325 XBT_WARN("Cannot launch process '%s' on failed host '%s'",
330 smx_process_t process = new simgrid::simix::Process();
332 process->pid = simix_process_maxpid++;
333 process->name = std::string(name);
334 process->host = host;
335 process->data = data;
336 process->comms = xbt_fifo_new();
337 process->simcall.issuer = process;
339 /* Initiliaze data segment to default value */
340 SIMIX_segment_index_set(process, -1);
341 if (parent_process != NULL) {
342 process->ppid = SIMIX_process_get_PID(parent_process);
343 /* SMPI process have their own data segment and
344 each other inherit from their father */
346 if(smpi_privatize_global_variables){
347 if(parent_process->pid != 0){
348 SIMIX_segment_index_set(process, parent_process->segment_index);
350 SIMIX_segment_index_set(process, process->pid - 1);
356 /* Process data for auto-restart */
357 process->auto_restart = false;
358 process->code = nullptr;
360 XBT_VERB("Create context %s", process->name.c_str());
362 xbt_die("simix is not initialized, please call MSG_init first");
363 process->context = simix_global->context_factory->attach(
364 simix_global->cleanup_process_function, process);
366 process->running_ctx = (xbt_running_ctx_t*) xbt_malloc0(sizeof(xbt_running_ctx_t));
367 XBT_RUNNING_CTX_INITIALIZE(process->running_ctx);
370 MC_ignore_heap(process->running_ctx, sizeof(*process->running_ctx));
374 process->properties = properties;
376 /* Add the process to it's host process list */
377 xbt_swag_insert(process, sg_host_simix(host)->process_list);
379 /* Now insert it in the global process list and in the process to run list */
380 xbt_swag_insert(process, simix_global->process_list);
381 XBT_DEBUG("Inserting %s(%s) in the to_run list",
382 process->name.c_str(), sg_host_get_name(host));
383 xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
385 /* Tracing the process creation */
386 TRACE_msg_process_create(process->name.c_str(), process->pid, process->host);
388 auto context = dynamic_cast<simgrid::simix::AttachContext*>(process->context);
390 xbt_die("Not a suitable context");
392 context->attach_start();
396 void SIMIX_process_detach(void)
398 auto context = dynamic_cast<simgrid::simix::AttachContext*>(SIMIX_context_self());
400 xbt_die("Not a suitable context");
402 simix_global->cleanup_process_function(context->process());
404 // Let maestro ignore we are still alive:
405 // xbt_swag_remove(context->process(), simix_global->process_list);
407 // TODDO, Remove from proces list:
408 // xbt_swag_remove(process, sg_host_simix(host)->process_list);
410 context->attach_stop();
415 * \brief Executes the processes from simix_global->process_to_run.
417 * The processes of simix_global->process_to_run are run (in parallel if
418 * possible). On exit, simix_global->process_to_run is empty, and
419 * simix_global->process_that_ran contains the list of processes that just ran.
420 * The two lists are swapped so, be careful when using them before and after a
421 * call to this function.
423 void SIMIX_process_runall(void)
425 SIMIX_context_runall();
427 xbt_dynar_t tmp = simix_global->process_that_ran;
428 simix_global->process_that_ran = simix_global->process_to_run;
429 simix_global->process_to_run = tmp;
430 xbt_dynar_reset(simix_global->process_to_run);
433 void simcall_HANDLER_process_kill(smx_simcall_t simcall, smx_process_t process) {
434 SIMIX_process_kill(process, simcall->issuer);
437 * \brief Internal function to kill a SIMIX process.
439 * This function may be called when a SIMCALL_PROCESS_KILL simcall occurs,
440 * or directly for SIMIX internal purposes.
442 * \param process poor victim
443 * \param issuer the process which has sent the PROCESS_KILL. Important to not schedule twice the same process.
445 void SIMIX_process_kill(smx_process_t process, smx_process_t issuer) {
447 XBT_DEBUG("Killing process %s on %s",
448 process->name.c_str(), sg_host_get_name(process->host));
450 process->context->iwannadie = 1;
451 process->blocked = 0;
452 process->suspended = 0;
453 process->doexception = 0;
455 /* destroy the blocking synchro if any */
456 if (process->waiting_synchro) {
458 simgrid::simix::Exec *exec = dynamic_cast<simgrid::simix::Exec*>(process->waiting_synchro);
459 simgrid::simix::Comm *comm = dynamic_cast<simgrid::simix::Comm*>(process->waiting_synchro);
460 simgrid::simix::Sleep *sleep = dynamic_cast<simgrid::simix::Sleep*>(process->waiting_synchro);
461 simgrid::simix::Raw *raw = dynamic_cast<simgrid::simix::Raw*>(process->waiting_synchro);
462 simgrid::simix::Io *io = dynamic_cast<simgrid::simix::Io*>(process->waiting_synchro);
464 if (exec != nullptr) {
467 } else if (comm != nullptr) {
468 xbt_fifo_remove(process->comms, process->waiting_synchro);
471 // Remove first occurence of &process->simcall:
472 auto i = boost::range::find(
473 process->waiting_synchro->simcalls,
475 if (i != process->waiting_synchro->simcalls.end())
476 process->waiting_synchro->simcalls.remove(&process->simcall);
480 } else if (sleep != nullptr) {
481 SIMIX_process_sleep_destroy(process->waiting_synchro);
483 } else if (raw != nullptr) {
484 SIMIX_synchro_stop_waiting(process, &process->simcall);
485 delete process->waiting_synchro;
487 } else if (io != nullptr) {
488 SIMIX_io_destroy(process->waiting_synchro);
492 switch (process->waiting_synchro->type) {
493 case SIMIX_SYNC_JOIN:
494 SIMIX_process_sleep_destroy(process->waiting_synchro);
498 process->waiting_synchro = NULL;
500 if(!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != issuer) {
501 XBT_DEBUG("Inserting %s in the to_run list", process->name.c_str());
502 xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
507 /** @brief Ask another process to raise the given exception
509 * @param cat category of exception
510 * @param value value associated to the exception
511 * @param msg string information associated to the exception
513 void SIMIX_process_throw(smx_process_t process, xbt_errcat_t cat, int value, const char *msg) {
514 SMX_EXCEPTION(process, cat, value, msg);
516 if (process->suspended)
517 SIMIX_process_resume(process,SIMIX_process_self());
519 /* cancel the blocking synchro if any */
520 if (process->waiting_synchro) {
522 simgrid::simix::Exec *exec = dynamic_cast<simgrid::simix::Exec*>(process->waiting_synchro);
523 if (exec != nullptr) {
524 SIMIX_execution_cancel(process->waiting_synchro);
527 simgrid::simix::Comm *comm = dynamic_cast<simgrid::simix::Comm*>(process->waiting_synchro);
528 if (comm != nullptr) {
529 xbt_fifo_remove(process->comms, comm);
533 simgrid::simix::Sleep *sleep = dynamic_cast<simgrid::simix::Sleep*>(process->waiting_synchro);
534 if (sleep != nullptr) {
535 SIMIX_process_sleep_destroy(process->waiting_synchro);
536 if (!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != SIMIX_process_self()) {
537 XBT_DEBUG("Inserting %s in the to_run list", process->name.c_str());
538 xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
542 simgrid::simix::Raw *raw = dynamic_cast<simgrid::simix::Raw*>(process->waiting_synchro);
543 if (raw != nullptr) {
544 SIMIX_synchro_stop_waiting(process, &process->simcall);
547 simgrid::simix::Io *io = dynamic_cast<simgrid::simix::Io*>(process->waiting_synchro);
549 SIMIX_io_destroy(process->waiting_synchro);
552 process->waiting_synchro = NULL;
556 void simcall_HANDLER_process_killall(smx_simcall_t simcall, int reset_pid) {
557 SIMIX_process_killall(simcall->issuer, reset_pid);
560 * \brief Kills all running processes.
561 * \param issuer this one will not be killed
563 void SIMIX_process_killall(smx_process_t issuer, int reset_pid)
565 smx_process_t p = NULL;
567 while ((p = (smx_process_t) xbt_swag_extract(simix_global->process_list))) {
569 SIMIX_process_kill(p,issuer);
574 simix_process_maxpid = reset_pid;
576 SIMIX_context_runall();
578 SIMIX_process_empty_trash();
581 void simcall_HANDLER_process_set_host(smx_simcall_t simcall, smx_process_t process, sg_host_t dest)
583 process->new_host = dest;
585 void SIMIX_process_change_host(smx_process_t process,
588 xbt_assert((process != NULL), "Invalid parameters");
589 xbt_swag_remove(process, sg_host_simix(process->host)->process_list);
590 process->host = dest;
591 xbt_swag_insert(process, sg_host_simix(dest)->process_list);
595 void simcall_HANDLER_process_suspend(smx_simcall_t simcall, smx_process_t process)
597 smx_synchro_t sync_suspend = SIMIX_process_suspend(process, simcall->issuer);
599 if (process != simcall->issuer) {
600 SIMIX_simcall_answer(simcall);
602 sync_suspend->simcalls.push_back(simcall);
603 process->waiting_synchro = sync_suspend;
604 process->waiting_synchro->suspend();
606 /* If we are suspending ourselves, then just do not finish the simcall now */
609 smx_synchro_t SIMIX_process_suspend(smx_process_t process, smx_process_t issuer)
611 if (process->suspended) {
612 XBT_DEBUG("Process '%s' is already suspended", process->name.c_str());
616 process->suspended = 1;
618 /* If we are suspending another process that is waiting on a sync, suspend its synchronization. */
619 if (process != issuer) {
621 if (process->waiting_synchro)
622 process->waiting_synchro->suspend();
623 /* If the other process is not waiting, its suspension is delayed to when the process is rescheduled. */
627 /* FIXME: computation size is zero. Is it okay that bound is zero ? */
628 return SIMIX_execution_start(process, "suspend", 0.0, 1.0, 0.0, 0);
632 void simcall_HANDLER_process_resume(smx_simcall_t simcall, smx_process_t process){
633 SIMIX_process_resume(process, simcall->issuer);
636 void SIMIX_process_resume(smx_process_t process, smx_process_t issuer)
638 XBT_IN("process = %p, issuer = %p", process, issuer);
640 if(process->context->iwannadie) {
641 XBT_VERB("Ignoring request to suspend a process that is currently dying.");
645 if(!process->suspended) return;
646 process->suspended = 0;
648 /* If we are resuming another process, resume the synchronization it was waiting for
649 if any. Otherwise add it to the list of process to run in the next round. */
650 if (process != issuer) {
652 if (process->waiting_synchro) {
653 process->waiting_synchro->resume();
655 } else XBT_WARN("Strange. Process %p is trying to resume himself.", issuer);
660 int SIMIX_process_get_maxpid(void) {
661 return simix_process_maxpid;
664 int SIMIX_process_count(void)
666 return xbt_swag_size(simix_global->process_list);
669 int SIMIX_process_get_PID(smx_process_t self){
676 int SIMIX_process_get_PPID(smx_process_t self){
683 void* SIMIX_process_self_get_data()
685 smx_process_t self = SIMIX_process_self();
690 return SIMIX_process_get_data(self);
693 void SIMIX_process_self_set_data(void *data)
695 smx_process_t self = SIMIX_process_self();
697 SIMIX_process_set_data(self, data);
700 void* SIMIX_process_get_data(smx_process_t process)
702 return process->data;
705 void SIMIX_process_set_data(smx_process_t process, void *data)
707 process->data = data;
710 sg_host_t SIMIX_process_get_host(smx_process_t process)
712 return process->host;
715 /* needs to be public and without simcall because it is called
716 by exceptions and logging events */
717 const char* SIMIX_process_self_get_name(void) {
719 smx_process_t process = SIMIX_process_self();
720 if (process == NULL || process == simix_global->maestro_process)
723 return SIMIX_process_get_name(process);
726 const char* SIMIX_process_get_name(smx_process_t process)
728 return process->name.c_str();
731 smx_process_t SIMIX_process_get_by_name(const char* name)
734 xbt_swag_foreach(proc, simix_global->process_list) {
735 if (proc->name == name)
741 int SIMIX_process_is_suspended(smx_process_t process)
743 return process->suspended;
746 xbt_dict_t SIMIX_process_get_properties(smx_process_t process)
748 return process->properties;
751 void simcall_HANDLER_process_join(smx_simcall_t simcall, smx_process_t process, double timeout)
753 smx_synchro_t sync = SIMIX_process_join(simcall->issuer, process, timeout);
754 sync->simcalls.push_back(simcall);
755 simcall->issuer->waiting_synchro = sync;
758 static int SIMIX_process_join_finish(smx_process_exit_status_t status, smx_synchro_t synchro){
759 simgrid::simix::Sleep *sleep = static_cast<simgrid::simix::Sleep*>(synchro);
761 if (sleep->surf_sleep) {
762 sleep->surf_sleep->cancel();
764 while (!sleep->simcalls.empty()) {
765 smx_simcall_t simcall = sleep->simcalls.front();
766 sleep->simcalls.pop_front();
767 simcall_process_sleep__set__result(simcall, SIMIX_DONE);
768 simcall->issuer->waiting_synchro = NULL;
769 if (simcall->issuer->suspended) {
770 XBT_DEBUG("Wait! This process is suspended and can't wake up now.");
771 simcall->issuer->suspended = 0;
772 simcall_HANDLER_process_suspend(simcall, simcall->issuer);
774 SIMIX_simcall_answer(simcall);
777 sleep->surf_sleep->unref();
778 sleep->surf_sleep = NULL;
784 smx_synchro_t SIMIX_process_join(smx_process_t issuer, smx_process_t process, double timeout)
786 smx_synchro_t res = SIMIX_process_sleep(issuer, timeout);
787 SIMIX_process_on_exit(process, (int_f_pvoid_pvoid_t)SIMIX_process_join_finish, res);
791 void simcall_HANDLER_process_sleep(smx_simcall_t simcall, double duration)
793 if (MC_is_active() || MC_record_replay_is_active()) {
794 MC_process_clock_add(simcall->issuer, duration);
795 simcall_process_sleep__set__result(simcall, SIMIX_DONE);
796 SIMIX_simcall_answer(simcall);
799 smx_synchro_t sync = SIMIX_process_sleep(simcall->issuer, duration);
800 sync->simcalls.push_back(simcall);
801 simcall->issuer->waiting_synchro = sync;
804 smx_synchro_t SIMIX_process_sleep(smx_process_t process, double duration)
806 sg_host_t host = process->host;
808 /* check if the host is active */
810 THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_get_name(host));
812 simgrid::simix::Sleep *synchro = new simgrid::simix::Sleep();
813 synchro->host = host;
814 synchro->surf_sleep = surf_host_sleep(host, duration);
815 synchro->surf_sleep->setData(synchro);
816 XBT_DEBUG("Create sleep synchronization %p", synchro);
821 void SIMIX_process_sleep_destroy(smx_synchro_t synchro)
823 XBT_DEBUG("Destroy synchro %p", synchro);
824 simgrid::simix::Sleep *sleep = static_cast<simgrid::simix::Sleep*>(synchro);
826 if (sleep->surf_sleep) {
827 sleep->surf_sleep->unref();
828 sleep->surf_sleep = NULL;
833 * \brief Calling this function makes the process to yield.
835 * Only the current process can call this function, giving back the control to
838 * \param self the current process
840 void SIMIX_process_yield(smx_process_t self)
842 XBT_DEBUG("Yield process '%s'", self->name.c_str());
844 /* Go into sleep and return control to maestro */
845 self->context->suspend();
847 /* Ok, maestro returned control to us */
848 XBT_DEBUG("Control returned to me: '%s'", self->name.c_str());
850 if (self->new_host) {
851 SIMIX_process_change_host(self, self->new_host);
852 self->new_host = NULL;
855 if (self->context->iwannadie){
856 XBT_DEBUG("I wanna die!");
857 SIMIX_process_stop(self);
860 if (self->suspended) {
861 XBT_DEBUG("Hey! I'm suspended.");
862 xbt_assert(!self->doexception, "Gasp! This exception may be lost by subsequent calls.");
864 SIMIX_process_suspend(self, self);
867 if (self->doexception) {
868 XBT_DEBUG("Wait, maestro left me an exception");
869 self->doexception = 0;
873 if(SMPI_switch_data_segment && self->segment_index != -1){
874 SMPI_switch_data_segment(self->segment_index);
878 /* callback: context fetching */
879 xbt_running_ctx_t *SIMIX_process_get_running_context(void)
881 smx_process_t process = SIMIX_process_self();
883 return process->running_ctx;
888 /* callback: termination */
889 void SIMIX_process_exception_terminate(xbt_ex_t * e)
895 smx_context_t SIMIX_process_get_context(smx_process_t p) {
899 void SIMIX_process_set_context(smx_process_t p,smx_context_t c) {
904 * \brief Returns the list of processes to run.
906 xbt_dynar_t SIMIX_process_get_runnable(void)
908 return simix_global->process_to_run;
912 * \brief Returns the process from PID.
914 smx_process_t SIMIX_process_from_PID(int PID)
917 xbt_swag_foreach(proc, simix_global->process_list) {
918 if (proc->pid == (unsigned long) PID)
924 /** @brief returns a dynar containg all currently existing processes */
925 xbt_dynar_t SIMIX_processes_as_dynar(void) {
927 xbt_dynar_t res = xbt_dynar_new(sizeof(smx_process_t),NULL);
928 xbt_swag_foreach(proc, simix_global->process_list) {
929 xbt_dynar_push(res,&proc);
935 void SIMIX_process_on_exit_runall(smx_process_t process) {
936 s_smx_process_exit_fun_t exit_fun;
937 smx_process_exit_status_t exit_status = (process->context->iwannadie) ?
938 SMX_EXIT_FAILURE : SMX_EXIT_SUCCESS;
939 while (!xbt_dynar_is_empty(process->on_exit)) {
940 exit_fun = xbt_dynar_pop_as(process->on_exit,s_smx_process_exit_fun_t);
941 (exit_fun.fun)((void*)exit_status, exit_fun.arg);
945 void SIMIX_process_on_exit(smx_process_t process, int_f_pvoid_pvoid_t fun, void *data) {
946 xbt_assert(process, "current process not found: are you in maestro context ?");
948 if (!process->on_exit) {
949 process->on_exit = xbt_dynar_new(sizeof(s_smx_process_exit_fun_t), NULL);
952 s_smx_process_exit_fun_t exit_fun = {fun, data};
954 xbt_dynar_push_as(process->on_exit,s_smx_process_exit_fun_t,exit_fun);
958 * \brief Sets the auto-restart status of the process.
959 * If set to 1, the process will be automatically restarted when its host
962 void SIMIX_process_auto_restart_set(smx_process_t process, int auto_restart) {
963 process->auto_restart = auto_restart;
966 smx_process_t simcall_HANDLER_process_restart(smx_simcall_t simcall, smx_process_t process) {
967 return SIMIX_process_restart(process, simcall->issuer);
969 /** @brief Restart a process, starting it again from the beginning. */
970 smx_process_t SIMIX_process_restart(smx_process_t process, smx_process_t issuer) {
971 XBT_DEBUG("Restarting process %s on %s",
972 process->name.c_str(), sg_host_get_name(process->host));
974 //retrieve the arguments of the old process
975 //FIXME: Factorize this with SIMIX_host_add_auto_restart_process ?
976 simgrid::simix::ProcessArg arg;
977 arg.name = process->name;
978 arg.code = process->code;
979 arg.hostname = sg_host_get_name(process->host);
980 arg.kill_time = SIMIX_timer_get_date(process->kill_timer);
981 arg.data = process->data;
982 arg.properties = NULL;
983 arg.auto_restart = process->auto_restart;
985 //kill the old process
986 SIMIX_process_kill(process, issuer);
988 //start the new process
989 if (simix_global->create_process_function)
990 return simix_global->create_process_function(
991 arg.name.c_str(), std::move(arg.code), arg.data,
992 arg.hostname, arg.kill_time,
993 arg.properties, arg.auto_restart,
996 return simcall_process_create(
997 arg.name.c_str(), std::move(arg.code), arg.data,
998 arg.hostname, arg.kill_time,
999 arg.properties, arg.auto_restart);
1002 void SIMIX_segment_index_set(smx_process_t proc, int index){
1003 proc->segment_index = index;
1006 smx_process_t simcall_process_create(
1007 const char *name, std::function<void()> code, void *data,
1008 const char *hostname, double kill_time,
1009 xbt_dict_t properties, int auto_restart)
1011 if (name == nullptr)
1013 smx_process_t self = SIMIX_process_self();
1014 return simgrid::simix::kernel([&] {
1015 return SIMIX_process_create(name,
1016 std::move(code), data, hostname,
1017 kill_time, properties, auto_restart,