1 /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. 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 "msg_private.h"
8 #include "xbt/sysdep.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_process, msg,
12 "Logging specific to MSG (process)");
14 /** \defgroup m_process_management Management Functions of Agents
15 * \brief This section describes the agent structure of MSG
16 * (#m_process_t) and the functions for managing it.
18 /** @addtogroup m_process_management
19 * \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Agents" --> \endhtmlonly
21 * We need to simulate many independent scheduling decisions, so
22 * the concept of <em>process</em> is at the heart of the
23 * simulator. A process may be defined as a <em>code</em>, with
24 * some <em>private data</em>, executing in a <em>location</em>.
28 /******************************** Process ************************************/
31 * \brief Cleans the MSG data of a process.
32 * \param smx_proc a SIMIX process
34 void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc)
36 simdata_process_t msg_proc;
38 if (smx_proc == SIMIX_process_self()) {
39 /* avoid a SIMIX request if this function is called by the process itself */
40 msg_proc = SIMIX_process_self_get_data(smx_proc);
41 SIMIX_process_self_set_data(smx_proc, NULL);
44 msg_proc = SIMIX_req_process_get_data(smx_proc);
45 SIMIX_req_process_set_data(smx_proc, NULL);
49 TRACE_msg_process_end(smx_proc);
55 /* This function creates a MSG process. It has the prototype enforced by SIMIX_function_register_process_create */
56 void MSG_process_create_from_SIMIX(smx_process_t* process, const char *name,
57 xbt_main_func_t code, void *data,
58 const char *hostname, int argc, char **argv,
59 xbt_dict_t properties)
61 m_host_t host = MSG_get_host_by_name(hostname);
62 m_process_t p = MSG_process_create_with_environment(name, code, data,
65 *((m_process_t*) process) = p;
68 /** \ingroup m_process_management
69 * \brief Creates and runs a new #m_process_t.
71 * Does exactly the same as #MSG_process_create_with_arguments but without
72 providing standard arguments (\a argc, \a argv, \a start_time, \a kill_time).
73 * \sa MSG_process_create_with_arguments
75 m_process_t MSG_process_create(const char *name,
76 xbt_main_func_t code, void *data,
79 return MSG_process_create_with_environment(name, code, data, host, -1,
83 /** \ingroup m_process_management
84 * \brief Creates and runs a new #m_process_t.
86 * A constructor for #m_process_t taking four arguments and returning the
87 * corresponding object. The structure (and the corresponding thread) is
88 * created, and put in the list of ready process.
89 * \param name a name for the object. It is for user-level information
91 * \param code is a function describing the behavior of the agent. It
92 should then only use functions described in \ref
93 m_process_management (to create a new #m_process_t for example),
94 in \ref m_host_management (only the read-only functions i.e. whose
95 name contains the word get), in \ref m_task_management (to create
96 or destroy some #m_task_t for example) and in \ref
97 msg_gos_functions (to handle file transfers and task processing).
98 * \param data a pointer to any data one may want to attach to the new
99 object. It is for user-level information and can be NULL. It can
100 be retrieved with the function \ref MSG_process_get_data.
101 * \param host the location where the new agent is executed.
102 * \param argc first argument passed to \a code
103 * \param argv second argument passed to \a code
105 * \return The new corresponding object.
108 m_process_t MSG_process_create_with_arguments(const char *name,
109 xbt_main_func_t code,
110 void *data, m_host_t host,
111 int argc, char **argv)
113 return MSG_process_create_with_environment(name, code, data, host,
117 /** \ingroup m_process_management
118 * \brief Creates and runs a new #m_process_t.
120 * A constructor for #m_process_t taking four arguments and returning the
121 * corresponding object. The structure (and the corresponding thread) is
122 * created, and put in the list of ready process.
123 * \param name a name for the object. It is for user-level information
125 * \param code is a function describing the behavior of the agent. It
126 should then only use functions described in \ref
127 m_process_management (to create a new #m_process_t for example),
128 in \ref m_host_management (only the read-only functions i.e. whose
129 name contains the word get), in \ref m_task_management (to create
130 or destroy some #m_task_t for example) and in \ref
131 msg_gos_functions (to handle file transfers and task processing).
132 * \param data a pointer to any data one may want to attach to the new
133 object. It is for user-level information and can be NULL. It can
134 be retrieved with the function \ref MSG_process_get_data.
135 * \param host the location where the new agent is executed.
136 * \param argc first argument passed to \a code
137 * \param argv second argument passed to \a code
138 * \param properties list a properties defined for this process
140 * \return The new corresponding object.
142 m_process_t MSG_process_create_with_environment(const char *name,
143 xbt_main_func_t code,
144 void *data, m_host_t host,
145 int argc, char **argv,
146 xbt_dict_t properties)
148 xbt_assert(code != NULL && host != NULL, "Invalid parameters");
149 simdata_process_t simdata = xbt_new0(s_simdata_process_t, 1);
152 /* Simulator data for MSG */
153 simdata->PID = msg_global->PID++;
154 simdata->waiting_action = NULL;
155 simdata->waiting_task = NULL;
156 simdata->m_host = host;
157 simdata->argc = argc;
158 simdata->argv = argv;
159 simdata->data = data;
160 simdata->last_errno = MSG_OK;
162 if (SIMIX_process_self()) {
163 simdata->PPID = MSG_process_get_PID(MSG_process_self());
169 TRACE_msg_process_create(name, simdata->PID, simdata->m_host);
172 /* Let's create the process: SIMIX may decide to start it right now,
173 * even before returning the flow control to us */
174 SIMIX_req_process_create(&process, name, code, simdata, host->name,
175 argc, argv, properties);
178 /* Undo everything we have just changed */
187 void MSG_process_kill_from_SIMIX(smx_process_t p)
190 TRACE_msg_process_kill(p);
195 /** \ingroup m_process_management
196 * \param process poor victim
198 * This function simply kills a \a process... scary isn't it ? :)
200 void MSG_process_kill(m_process_t process)
203 TRACE_msg_process_kill(process);
206 /* FIXME: why do we only cancel communication actions? is this useful? */
207 simdata_process_t p_simdata = SIMIX_req_process_get_data(process);
208 if (p_simdata->waiting_task && p_simdata->waiting_task->simdata->comm) {
209 SIMIX_req_comm_cancel(p_simdata->waiting_task->simdata->comm);
212 SIMIX_req_process_kill(process);
217 /** \ingroup m_process_management
218 * \brief Migrates an agent to another location.
220 * This function checks whether \a process and \a host are valid pointers
221 and change the value of the #m_host_t on which \a process is running.
223 MSG_error_t MSG_process_migrate(m_process_t process, m_host_t host)
225 simdata_process_t simdata = SIMIX_req_process_get_data(process);
226 simdata->m_host = host;
228 m_host_t now = simdata->m_host;
229 TRACE_msg_process_change_host(process, now, host);
231 SIMIX_req_process_change_host(process, host->simdata->smx_host);
235 /** \ingroup m_process_management
236 * \brief Returns the user data of a process.
238 * This function checks whether \a process is a valid pointer or not
239 and returns the user data associated to this process.
241 void* MSG_process_get_data(m_process_t process)
243 xbt_assert(process != NULL, "Invalid parameter");
245 /* get from SIMIX the MSG process data, and then the user data */
246 simdata_process_t simdata = SIMIX_req_process_get_data(process);
247 return simdata->data;
250 /** \ingroup m_process_management
251 * \brief Sets the user data of a process.
253 * This function checks whether \a process is a valid pointer or not
254 and sets the user data associated to this process.
256 MSG_error_t MSG_process_set_data(m_process_t process, void *data)
258 xbt_assert(process != NULL, "Invalid parameter");
260 simdata_process_t simdata = SIMIX_req_process_get_data(process);
261 simdata->data = data;
266 /** \ingroup m_process_management
267 * \brief Return the location on which an agent is running.
268 * \param process a process (NULL means the current one)
269 * \return the m_host_t corresponding to the location on which \a
270 * process is running.
272 m_host_t MSG_process_get_host(m_process_t process)
274 simdata_process_t simdata;
275 if (process == NULL) {
276 simdata = SIMIX_process_self_get_data(SIMIX_process_self());
279 simdata = SIMIX_req_process_get_data(process);
281 return simdata->m_host;
284 /** \ingroup m_process_management
286 * \brief Return a #m_process_t given its PID.
288 * This function search in the list of all the created m_process_t for a m_process_t
289 whose PID is equal to \a PID. If no host is found, \c NULL is returned.
290 Note that the PID are uniq in the whole simulation, not only on a given host.
292 m_process_t MSG_process_from_PID(int PID)
294 /* FIXME: reimplement this function using SIMIX when we have a good PID.
295 * In the meantime, I guess nobody uses it so it should not break anything. */
299 /** \ingroup m_process_management
300 * \brief Returns the process ID of \a process.
302 * This function checks whether \a process is a valid pointer or not
303 and return its PID (or 0 in case of problem).
305 int MSG_process_get_PID(m_process_t process)
307 /* Do not raise an exception here: this function is called by the logs
308 * and the exceptions, so it would be called back again and again */
309 if (process == NULL) {
313 simdata_process_t simdata = SIMIX_req_process_get_data(process);
315 return simdata != NULL ? simdata->PID : 0;
318 /** \ingroup m_process_management
319 * \brief Returns the process ID of the parent of \a process.
321 * This function checks whether \a process is a valid pointer or not
322 and return its PID. Returns -1 if the agent has not been created by
325 int MSG_process_get_PPID(m_process_t process)
327 xbt_assert(process != NULL, "Invalid parameter");
329 simdata_process_t simdata = SIMIX_req_process_get_data(process);
331 return simdata->PPID;
334 /** \ingroup m_process_management
335 * \brief Return the name of an agent.
337 * This function checks whether \a process is a valid pointer or not
340 const char *MSG_process_get_name(m_process_t process)
342 xbt_assert(process, "Invalid parameter");
344 return SIMIX_req_process_get_name(process);
347 /** \ingroup m_process_management
348 * \brief Returns the value of a given process property
350 * \param process a process
351 * \param name a property name
352 * \return value of a property (or NULL if the property is not set)
354 const char *MSG_process_get_property_value(m_process_t process,
357 return xbt_dict_get_or_null(MSG_process_get_properties(process), name);
360 /** \ingroup m_process_management
361 * \brief Return the list of properties
363 * This function returns all the parameters associated with a process
365 xbt_dict_t MSG_process_get_properties(m_process_t process)
367 xbt_assert(process != NULL, "Invalid parameter");
369 return SIMIX_req_process_get_properties(process);
373 /** \ingroup m_process_management
374 * \brief Return the PID of the current agent.
376 * This function returns the PID of the currently running #m_process_t.
378 int MSG_process_self_PID(void)
380 return MSG_process_get_PID(MSG_process_self());
383 /** \ingroup m_process_management
384 * \brief Return the PPID of the current agent.
386 * This function returns the PID of the parent of the currently
387 * running #m_process_t.
389 int MSG_process_self_PPID(void)
391 return MSG_process_get_PPID(MSG_process_self());
394 /** \ingroup m_process_management
395 * \brief Return the current process.
397 * This function returns the currently running #m_process_t.
399 m_process_t MSG_process_self(void)
401 return SIMIX_process_self();
404 /** \ingroup m_process_management
405 * \brief Suspend the process.
407 * This function suspends the process by suspending the task on which
408 * it was waiting for the completion.
410 MSG_error_t MSG_process_suspend(m_process_t process)
412 xbt_assert(process != NULL, "Invalid parameter");
416 TRACE_msg_process_suspend(process);
419 SIMIX_req_process_suspend(process);
423 /** \ingroup m_process_management
424 * \brief Resume a suspended process.
426 * This function resumes a suspended process by resuming the task on
427 * which it was waiting for the completion.
429 MSG_error_t MSG_process_resume(m_process_t process)
431 xbt_assert(process != NULL, "Invalid parameter");
435 TRACE_msg_process_resume(process);
438 SIMIX_req_process_resume(process);
442 /** \ingroup m_process_management
443 * \brief Returns true if the process is suspended .
445 * This checks whether a process is suspended or not by inspecting the
446 * task on which it was waiting for the completion.
448 int MSG_process_is_suspended(m_process_t process)
450 xbt_assert(process != NULL, "Invalid parameter");
451 return SIMIX_req_process_is_suspended(process);
454 smx_context_t MSG_process_get_smx_ctx(m_process_t process) {
455 return SIMIX_process_get_context(process);