3 /* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved. */
5 /* This program is free software; you can redistribute it and/or modify it
6 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "xbt/sysdep.h"
12 #include "msg/mailbox.h"
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
15 "Logging specific to SIMIX (process)");
18 * \brief Move a process to the list of process to destroy. *
20 void SIMIX_process_cleanup(void *arg)
22 xbt_swag_remove(arg, simix_global->process_to_run);
23 xbt_swag_remove(arg, simix_global->process_list);
24 xbt_swag_remove(arg, ((smx_process_t) arg)->smx_host->process_list);
25 xbt_swag_insert(arg, simix_global->process_to_destroy);
31 * Should be called some time to time to free the memory allocated for processes
32 * that have finished (or killed).
34 void SIMIX_process_empty_trash(void)
36 smx_process_t process = NULL;
38 while ((process = xbt_swag_extract(simix_global->process_to_destroy))) {
39 SIMIX_context_free(process->context);
41 /* Free the exception allocated at creation time */
42 if (process->exception)
43 free(process->exception);
44 if (process->properties)
45 xbt_dict_free(&process->properties);
54 * \brief Creates and runs the maestro process
56 void SIMIX_create_maestro_process()
58 smx_process_t process = NULL;
59 process = xbt_new0(s_smx_process_t, 1);
62 process->name = (char *) "";
64 process->exception = xbt_new(ex_ctx_t, 1);
65 XBT_CTX_INITIALIZE(process->exception);
67 /* Create a dummy context for maestro */
68 process->context = SIMIX_context_new(NULL, 0, NULL, NULL, NULL);
70 /* Set it as the maestro process */
71 simix_global->maestro_process = process;
72 simix_global->current_process = process;
78 * \brief Creates and runs a new #smx_process_t.
80 * 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.
82 * \param name a name for the object. It is for user-level information and can be NULL.
83 * \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.
84 * \param host the location where the new agent is executed.
85 * \param argc first argument passed to \a code
86 * \param argv second argument passed to \a code
87 * \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.
89 * \return The new corresponding object.
91 smx_process_t SIMIX_process_create(const char *name,
92 xbt_main_func_t code, void *data,
93 const char *hostname, int argc,
94 char **argv, xbt_dict_t properties)
96 smx_process_t process = NULL;
97 smx_host_t host = SIMIX_host_get_by_name(hostname);
99 DEBUG2("Start process %s on host %s", name, hostname);
101 if (!SIMIX_host_get_state(host)) {
102 WARN2("Cannot launch process '%s' on failed host '%s'", name, hostname);
105 process = xbt_new0(s_smx_process_t, 1);
107 xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
110 process->name = xbt_strdup(name);
111 process->smx_host = host;
112 process->mutex = NULL;
113 process->cond = NULL;
114 process->iwannadie = 0;
115 process->data = data;
117 VERB1("Create context %s", process->name);
118 process->context = SIMIX_context_new(code, argc, argv,
119 simix_global->cleanup_process_function,
122 process->exception = xbt_new(ex_ctx_t, 1);
123 XBT_CTX_INITIALIZE(process->exception);
126 process->properties = properties;
128 /* Add the process to it's host process list */
129 xbt_swag_insert(process, host->process_list);
131 DEBUG1("Start context '%s'", process->name);
133 /* Now insert it in the global process list and in the process to run list */
134 xbt_swag_insert(process, simix_global->process_list);
135 DEBUG2("Inserting %s(%s) in the to_run list", process->name, host->name);
136 xbt_swag_insert(process, simix_global->process_to_run);
141 /** \brief Kill a SIMIX process
143 * This function simply kills a \a process... scarry isn't it ? :).
144 * \param process poor victim
147 void SIMIX_process_kill(smx_process_t process)
149 DEBUG2("Killing process %s on %s", process->name, process->smx_host->name);
151 process->iwannadie = 1;
153 /* If I'm killing myself then stop otherwise schedule the process to kill
154 * 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 */
155 if (process == SIMIX_process_self()) {
156 /* Cleanup if we were waiting for something */
158 xbt_swag_remove(process, process->mutex->sleeping);
161 xbt_swag_remove(process, process->cond->sleeping);
162 if (process->waiting_action) {
163 SIMIX_unregister_action_to_condition(process->waiting_action, process->cond);
164 SIMIX_action_destroy(process->waiting_action);
168 xbt_swag_remove(process, process->sem->sleeping);
170 if (process->waiting_action) {
171 SIMIX_unregister_action_to_semaphore(process->waiting_action, process->sem);
172 SIMIX_action_destroy(process->waiting_action);
176 SIMIX_context_stop(process->context);
179 DEBUG4("%s(%p) here! killing %s(%p)",
180 simix_global->current_process->name,simix_global->current_process,
181 process->name,process);
183 /* Cleanup if it were waiting for something */
184 if (process->mutex) {
185 xbt_swag_remove(process, process->mutex->sleeping);
186 process->mutex = NULL;
190 xbt_swag_remove(process, process->cond->sleeping);
192 if (process->waiting_action) {
193 SIMIX_unregister_action_to_condition(process->waiting_action, process->cond);
194 SIMIX_action_destroy(process->waiting_action);
196 process->cond = NULL;
200 xbt_swag_remove(process, process->sem->sleeping);
202 if (process->waiting_action) {
203 SIMIX_unregister_action_to_semaphore(process->waiting_action, process->sem);
204 SIMIX_action_destroy(process->waiting_action);
209 /* make sure that the process gets awake soon enough, now that we've set its iwannadie to 1 */
210 process->blocked = 0;
211 process->suspended = 0;
212 xbt_swag_insert(process, simix_global->process_to_run);
217 * \brief Return the user data of a #smx_process_t.
219 * 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.
220 * \param process SIMIX process
221 * \return A void pointer to the user data
223 XBT_INLINE void *SIMIX_process_get_data(smx_process_t process)
225 xbt_assert0((process != NULL), "Invalid parameters");
226 return (process->data);
230 * \brief Set the user data of a #m_process_t.
232 * 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.
233 * \param process SIMIX process
234 * \param data User data
236 XBT_INLINE void SIMIX_process_set_data(smx_process_t process, void *data)
238 xbt_assert0((process != NULL), "Invalid parameters");
240 process->data = data;
245 * \brief Return the location on which an agent is running.
247 * 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.
248 * \param process SIMIX process
251 XBT_INLINE smx_host_t SIMIX_process_get_host(smx_process_t process)
253 xbt_assert0((process != NULL), "Invalid parameters");
254 return (process->smx_host);
258 * \brief Return the name of an agent.
260 * This functions checks whether \a process is a valid pointer or not and return its name.
261 * \param process SIMIX process
262 * \return The process name
264 XBT_INLINE const char *SIMIX_process_get_name(smx_process_t process)
266 xbt_assert0((process != NULL), "Invalid parameters");
267 return (process->name);
271 * \brief Changes the name of an agent.
273 * This functions checks whether \a process is a valid pointer or not and return its name.
274 * \param process SIMIX process
275 * \param name The new process name
277 XBT_INLINE void SIMIX_process_set_name(smx_process_t process, char *name)
279 xbt_assert0((process != NULL), "Invalid parameters");
280 process->name = name;
283 /** \ingroup m_process_management
284 * \brief Return the properties
286 * This functions returns the properties associated with this process
288 XBT_INLINE xbt_dict_t SIMIX_process_get_properties(smx_process_t process)
290 return process->properties;
294 * \brief Return the current agent.
296 * This functions returns the currently running #smx_process_t.
297 * \return The SIMIX process
299 XBT_INLINE smx_process_t SIMIX_process_self(void)
301 return simix_global ? simix_global->current_process : NULL;
305 * \brief Suspend the process.
307 * This functions suspend the process by suspending the action on
308 * which it was waiting for the completion.
310 * \param process SIMIX process
312 void SIMIX_process_suspend(smx_process_t process)
314 xbt_assert0(process, "Invalid parameters");
316 if (process != SIMIX_process_self()) {
318 if (process->mutex) {
319 /* process blocked on a mutex, only set suspend=1 */
320 process->suspended = 1;
321 } else if (process->cond) {
322 /* process blocked cond, suspend all actions */
324 /* temporaries variables */
329 process->suspended = 1;
331 xbt_fifo_foreach(c->actions, i, act, smx_action_t) {
332 surf_workstation_model->suspend(act->surf_action);
335 process->suspended = 1;
338 /* process executing, I can create an action and suspend it */
341 char name[] = "dummy";
342 process->suspended = 1;
344 cond = SIMIX_cond_init();
345 dummy = SIMIX_action_execute(SIMIX_process_get_host(process), name, 0);
346 SIMIX_process_self()->waiting_action = dummy;
347 surf_workstation_model->suspend(dummy->surf_action);
348 SIMIX_register_action_to_condition(dummy, cond);
349 __SIMIX_cond_wait(cond);
350 SIMIX_process_self()->waiting_action = NULL;
351 SIMIX_unregister_action_to_condition(dummy, cond);
352 SIMIX_action_destroy(dummy);
353 SIMIX_cond_destroy(cond);
359 * \brief Resume a suspended process.
361 * This functions resume a suspended process by resuming the task on which it was waiting for the completion.
362 * \param process SIMIX process
364 void SIMIX_process_resume(smx_process_t process)
366 xbt_assert0((process != NULL), "Invalid parameters");
369 if (process == SIMIX_process_self())
372 if (process->mutex) {
373 DEBUG0("Resume process blocked on a mutex");
374 process->suspended = 0; /* It'll wake up by itself when mutex releases */
376 } else if (process->cond) {
377 /* temporaries variables */
381 DEBUG0("Resume process blocked on a conditional");
382 process->suspended = 0;
384 xbt_fifo_foreach(c->actions, i, act, smx_action_t) {
385 surf_workstation_model->resume(act->surf_action);
387 SIMIX_cond_signal(c);
390 process->suspended = 0;
391 xbt_swag_insert(process, simix_global->process_to_run);
396 * \brief Migrates an agent to another location.
398 * This function changes the value of the host on which \a process is running.
400 void SIMIX_process_change_host(smx_process_t process, char *source,
403 xbt_assert0((process != NULL), "Invalid parameters");
404 smx_host_t h1 = SIMIX_host_get_by_name(source);
405 smx_host_t h2 = SIMIX_host_get_by_name(dest);
406 process->smx_host = h2;
407 xbt_swag_remove(process, h1->process_list);
408 xbt_swag_insert(process, h2->process_list);
412 * \brief Returns true if the process is suspended .
414 * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
415 * \param process SIMIX process
416 * \return 1, if the process is suspended, else 0.
418 XBT_INLINE int SIMIX_process_is_suspended(smx_process_t process)
420 xbt_assert0((process != NULL), "Invalid parameters");
422 return (process->suspended);
426 * \brief Returns the amount of SIMIX processes in the system
428 * Maestro internal process is not counted, only user code processes are
430 XBT_INLINE int SIMIX_process_count()
432 return xbt_swag_size(simix_global->process_list);
436 * Calling this function makes the process process to yield. The process
437 * that scheduled it returns from __SIMIX_process_schedule as if nothing
440 * Only the processes can call this function, giving back the control
443 void SIMIX_process_yield(void)
445 DEBUG1("Yield process '%s'", simix_global->current_process->name);
446 xbt_assert0((simix_global->current_process !=
447 simix_global->maestro_process),
448 "You are not supposed to run this function in maestro context!");
451 /* Go into sleep and return control to maestro */
452 SIMIX_context_suspend(simix_global->current_process->context);
453 /* Ok, maestro returned control to us */
455 if (simix_global->current_process->iwannadie)
456 SIMIX_context_stop(simix_global->current_process->context);
459 void SIMIX_process_schedule(smx_process_t new_process)
461 xbt_assert0(simix_global->current_process == simix_global->maestro_process,
462 "This function can only be called from maestro context");
463 DEBUG1("Scheduling context: '%s'", new_process->name);
465 /* update the current process */
466 simix_global->current_process = new_process;
468 /* schedule the context */
469 SIMIX_context_resume(new_process->context);
470 DEBUG1("Resumed from scheduling context: '%s'", new_process->name);
472 /* restore the current process to the previously saved process */
473 simix_global->current_process = simix_global->maestro_process;
476 /* callback: context fetching */
477 ex_ctx_t *SIMIX_process_get_exception(void)
479 return simix_global->current_process->exception;
482 /* callback: termination */
483 void SIMIX_process_exception_terminate(xbt_ex_t * e)