1 //* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include "xbt/sysdep.h"
10 #include "msg/mailbox.h"
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
13 "Logging specific to SIMIX (process)");
16 * \brief Move a process to the list of process to destroy. *
18 void SIMIX_process_cleanup(void *arg)
20 xbt_swag_remove(arg, simix_global->process_to_run);
21 xbt_swag_remove(arg, simix_global->process_list);
22 xbt_swag_remove(arg, ((smx_process_t) arg)->smx_host->process_list);
23 xbt_swag_insert(arg, simix_global->process_to_destroy);
29 * Should be called some time to time to free the memory allocated for processes
30 * that have finished (or killed).
32 void SIMIX_process_empty_trash(void)
34 smx_process_t process = NULL;
36 while ((process = xbt_swag_extract(simix_global->process_to_destroy))) {
37 SIMIX_context_free(process->context);
39 /* Free the exception allocated at creation time */
40 if (process->exception)
41 free(process->exception);
42 if (process->properties)
43 xbt_dict_free(&process->properties);
52 * \brief Creates and runs the maestro process
54 void SIMIX_create_maestro_process()
56 smx_process_t process = NULL;
57 process = xbt_new0(s_smx_process_t, 1);
60 process->name = (char *) "";
62 process->exception = xbt_new(ex_ctx_t, 1);
63 XBT_CTX_INITIALIZE(process->exception);
65 /* Create a dummy context for maestro */
66 process->context = SIMIX_context_new(NULL, 0, NULL, NULL, NULL);
68 /* Set it as the maestro process */
69 simix_global->maestro_process = process;
70 simix_global->current_process = process;
76 * \brief Creates and runs a new #smx_process_t.
78 * A constructor for #m_process_t taking four arguments and returning the corresponding object. The structure (and the corresponding thread) is created, and put in the list of ready process.
80 * \param name a name for the object. It is for user-level information and can be NULL.
81 * \param data a pointer to any data one may want to attach to the new object. It is for user-level information and can be NULL. It can be retrieved with the function \ref MSG_process_get_data.
82 * \param host the location where the new agent is executed.
83 * \param argc first argument passed to \a code
84 * \param argv second argument passed to \a code
85 * \param clean_process_function The cleanup function of user process. It will be called when the process finish. This function have to call the SIMIX_process_cleanup.
87 * \return The new corresponding object.
89 smx_process_t SIMIX_process_create(const char *name,
90 xbt_main_func_t code, void *data,
91 const char *hostname, int argc,
92 char **argv, xbt_dict_t properties)
94 smx_process_t process = NULL;
95 smx_host_t host = SIMIX_host_get_by_name(hostname);
97 DEBUG2("Start process %s on host %s", name, hostname);
99 if (!SIMIX_host_get_state(host)) {
100 WARN2("Cannot launch process '%s' on failed host '%s'", name, hostname);
103 process = xbt_new0(s_smx_process_t, 1);
105 xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
108 process->name = xbt_strdup(name);
109 process->smx_host = host;
110 process->mutex = NULL;
111 process->cond = NULL;
112 process->iwannadie = 0;
113 process->data = data;
115 VERB1("Create context %s", process->name);
116 process->context = SIMIX_context_new(code, argc, argv,
117 simix_global->cleanup_process_function,
120 process->exception = xbt_new(ex_ctx_t, 1);
121 XBT_CTX_INITIALIZE(process->exception);
124 process->properties = properties;
126 /* Add the process to it's host process list */
127 xbt_swag_insert(process, host->process_list);
129 DEBUG1("Start context '%s'", process->name);
131 /* Now insert it in the global process list and in the process to run list */
132 xbt_swag_insert(process, simix_global->process_list);
133 DEBUG2("Inserting %s(%s) in the to_run list", process->name, host->name);
134 xbt_swag_insert(process, simix_global->process_to_run);
139 /** \brief Kill a SIMIX process
141 * This function simply kills a \a process... scarry isn't it ? :).
142 * \param process poor victim
145 void SIMIX_process_kill(smx_process_t process)
147 DEBUG2("Killing process %s on %s", process->name, process->smx_host->name);
149 process->iwannadie = 1;
151 /* If I'm killing myself then stop otherwise schedule the process to kill
152 * Two different behaviors, if I'm killing my self, remove from mutex and condition and stop. Otherwise, first we must schedule the process, wait its ending and after remove it from mutex and condition */
153 if (process == SIMIX_process_self()) {
154 /* Cleanup if we were waiting for something */
156 xbt_swag_remove(process, process->mutex->sleeping);
159 xbt_swag_remove(process, process->cond->sleeping);
160 if (process->waiting_action) {
161 SIMIX_unregister_action_to_condition(process->waiting_action, process->cond);
162 SIMIX_action_destroy(process->waiting_action);
166 xbt_swag_remove(process, process->sem->sleeping);
168 if (process->waiting_action) {
169 SIMIX_unregister_action_to_semaphore(process->waiting_action, process->sem);
170 SIMIX_action_destroy(process->waiting_action);
174 SIMIX_context_stop(process->context);
177 DEBUG4("%s(%p) here! killing %s(%p)",
178 simix_global->current_process->name,simix_global->current_process,
179 process->name,process);
181 /* Cleanup if it were waiting for something */
182 if (process->mutex) {
183 xbt_swag_remove(process, process->mutex->sleeping);
184 process->mutex = NULL;
188 xbt_swag_remove(process, process->cond->sleeping);
190 if (process->waiting_action) {
191 SIMIX_unregister_action_to_condition(process->waiting_action, process->cond);
192 SIMIX_action_destroy(process->waiting_action);
194 process->cond = NULL;
198 xbt_swag_remove(process, process->sem->sleeping);
200 if (process->waiting_action) {
201 SIMIX_unregister_action_to_semaphore(process->waiting_action, process->sem);
202 SIMIX_action_destroy(process->waiting_action);
207 /* make sure that the process gets awake soon enough, now that we've set its iwannadie to 1 */
208 process->blocked = 0;
209 process->suspended = 0;
210 xbt_swag_insert(process, simix_global->process_to_run);
215 * \brief Return the user data of a #smx_process_t.
217 * This functions checks whether \a process is a valid pointer or not and return the user data associated to \a process if it is possible.
218 * \param process SIMIX process
219 * \return A void pointer to the user data
221 XBT_INLINE void *SIMIX_process_get_data(smx_process_t process)
223 xbt_assert0((process != NULL), "Invalid parameters");
224 return (process->data);
228 * \brief Set the user data of a #m_process_t.
230 * This functions checks whether \a process is a valid pointer or not and set the user data associated to \a process if it is possible.
231 * \param process SIMIX process
232 * \param data User data
234 XBT_INLINE void SIMIX_process_set_data(smx_process_t process, void *data)
236 xbt_assert0((process != NULL), "Invalid parameters");
238 process->data = data;
243 * \brief Return the location on which an agent is running.
245 * This functions checks whether \a process is a valid pointer or not and return the m_host_t corresponding to the location on which \a process is running.
246 * \param process SIMIX process
249 XBT_INLINE smx_host_t SIMIX_process_get_host(smx_process_t process)
251 xbt_assert0((process != NULL), "Invalid parameters");
252 return (process->smx_host);
256 * \brief Return the name of an agent.
258 * This functions checks whether \a process is a valid pointer or not and return its name.
259 * \param process SIMIX process
260 * \return The process name
262 XBT_INLINE const char *SIMIX_process_get_name(smx_process_t process)
264 xbt_assert0((process != NULL), "Invalid parameters");
265 return (process->name);
269 * \brief Changes the name of an agent.
271 * This functions checks whether \a process is a valid pointer or not and return its name.
272 * \param process SIMIX process
273 * \param name The new process name
275 XBT_INLINE void SIMIX_process_set_name(smx_process_t process, char *name)
277 xbt_assert0((process != NULL), "Invalid parameters");
278 process->name = name;
281 /** \ingroup m_process_management
282 * \brief Return the properties
284 * This functions returns the properties associated with this process
286 XBT_INLINE xbt_dict_t SIMIX_process_get_properties(smx_process_t process)
288 return process->properties;
292 * \brief Return the current agent.
294 * This functions returns the currently running #smx_process_t.
295 * \return The SIMIX process
297 XBT_INLINE smx_process_t SIMIX_process_self(void)
299 return simix_global ? simix_global->current_process : NULL;
303 * \brief Suspend the process.
305 * This functions suspend the process by suspending the action on
306 * which it was waiting for the completion.
308 * \param process SIMIX process
310 void SIMIX_process_suspend(smx_process_t process)
312 xbt_assert0(process, "Invalid parameters");
314 if (process != SIMIX_process_self()) {
316 if (process->mutex) {
317 /* process blocked on a mutex or sem, only set suspend=1 */
318 process->suspended = 1;
319 } else if (process->cond) {
320 /* process blocked cond, suspend all actions */
322 /* temporaries variables */
327 process->suspended = 1;
329 xbt_fifo_foreach(c->actions, i, act, smx_action_t) {
330 SIMIX_action_suspend(act);
332 } else if (process->sem) {
337 process->suspended = 1;
339 xbt_fifo_foreach(s->actions, i, act, smx_action_t) {
340 SIMIX_action_suspend(act);
343 process->suspended = 1;
346 /* process executing, I can create an action and suspend it */
349 char name[] = "dummy";
350 process->suspended = 1;
352 cond = SIMIX_cond_init();
353 dummy = SIMIX_action_execute(SIMIX_process_get_host(process), name, 0);
354 SIMIX_process_self()->waiting_action = dummy;
355 SIMIX_action_suspend(dummy);
356 SIMIX_register_action_to_condition(dummy, cond);
357 __SIMIX_cond_wait(cond);
358 SIMIX_process_self()->waiting_action = NULL;
359 SIMIX_unregister_action_to_condition(dummy, cond);
360 SIMIX_action_destroy(dummy);
361 SIMIX_cond_destroy(cond);
367 * \brief Resume a suspended process.
369 * This functions resume a suspended process by resuming the task on which it was waiting for the completion.
370 * \param process SIMIX process
372 void SIMIX_process_resume(smx_process_t process)
374 xbt_assert0((process != NULL), "Invalid parameters");
377 if (process == SIMIX_process_self())
380 if (process->mutex) {
381 DEBUG0("Resume process blocked on a mutex or semaphore");
382 process->suspended = 0; /* It'll wake up by itself when mutex releases */
384 } else if (process->cond) {
385 /* temporaries variables */
389 DEBUG0("Resume process blocked on a conditional");
390 process->suspended = 0;
392 xbt_fifo_foreach(c->actions, i, act, smx_action_t) {
393 SIMIX_action_resume(act);
395 SIMIX_cond_signal(c);
397 } else if (process->sem) {
398 /* temporaries variables */
402 DEBUG0("Resume process blocked on a semaphore");
403 process->suspended = 0;
405 xbt_fifo_foreach(s->actions, i, act, smx_action_t) {
406 SIMIX_action_resume(act);
410 process->suspended = 0;
411 xbt_swag_insert(process, simix_global->process_to_run);
416 * \brief Migrates an agent to another location.
418 * This function changes the value of the host on which \a process is running.
420 void SIMIX_process_change_host(smx_process_t process, char *source,
423 xbt_assert0((process != NULL), "Invalid parameters");
424 smx_host_t h1 = SIMIX_host_get_by_name(source);
425 smx_host_t h2 = SIMIX_host_get_by_name(dest);
426 process->smx_host = h2;
427 xbt_swag_remove(process, h1->process_list);
428 xbt_swag_insert(process, h2->process_list);
432 * \brief Returns true if the process is suspended .
434 * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
435 * \param process SIMIX process
436 * \return 1, if the process is suspended, else 0.
438 XBT_INLINE int SIMIX_process_is_suspended(smx_process_t process)
440 xbt_assert0((process != NULL), "Invalid parameters");
442 return (process->suspended);
446 * \brief Returns the amount of SIMIX processes in the system
448 * Maestro internal process is not counted, only user code processes are
450 XBT_INLINE int SIMIX_process_count()
452 return xbt_swag_size(simix_global->process_list);
456 * Calling this function makes the process process to yield. The process
457 * that scheduled it returns from __SIMIX_process_schedule as if nothing
460 * Only the processes can call this function, giving back the control
463 void SIMIX_process_yield(void)
465 DEBUG1("Yield process '%s'", simix_global->current_process->name);
466 xbt_assert0((simix_global->current_process !=
467 simix_global->maestro_process),
468 "You are not supposed to run this function in maestro context!");
471 /* Go into sleep and return control to maestro */
472 SIMIX_context_suspend(simix_global->current_process->context);
473 /* Ok, maestro returned control to us */
475 if (simix_global->current_process->iwannadie)
476 SIMIX_context_stop(simix_global->current_process->context);
479 void SIMIX_process_schedule(smx_process_t new_process)
481 xbt_assert0(simix_global->current_process == simix_global->maestro_process,
482 "This function can only be called from maestro context");
483 DEBUG1("Scheduling context: '%s'", new_process->name);
485 /* update the current process */
486 simix_global->current_process = new_process;
488 /* schedule the context */
489 SIMIX_context_resume(new_process->context);
490 DEBUG1("Resumed from scheduling context: '%s'", new_process->name);
492 /* restore the current process to the previously saved process */
493 simix_global->current_process = simix_global->maestro_process;
496 /* callback: context fetching */
497 ex_ctx_t *SIMIX_process_get_exception(void)
499 return simix_global->current_process->exception;
502 /* callback: termination */
503 void SIMIX_process_exception_terminate(xbt_ex_t * e)