Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Simplify the management of processes in MSG.
[simgrid.git] / src / msg / m_process.c
1 /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7 #include "msg/private.h"
8 #include "xbt/sysdep.h"
9 #include "xbt/log.h"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_process, msg,
12                                 "Logging specific to MSG (process)");
13
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.
17  */
18 /** @addtogroup m_process_management
19  *    \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Agents" --> \endhtmlonly
20  *
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>.
25  *  \see m_process_t
26  */
27
28 /******************************** Process ************************************/
29 void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc)
30 {
31   simdata_process_t msg_proc;
32
33   if (smx_proc == SIMIX_process_self()) {
34     /* avoid a SIMIX request if this function is called by the process itself */
35     msg_proc = SIMIX_process_self_get_data();
36   }
37   else {
38     msg_proc = SIMIX_req_process_get_data(smx_proc);
39   }
40
41 #ifdef HAVE_TRACING
42   TRACE_msg_process_end(smx_proc);
43 #endif
44
45   xbt_free(msg_proc);
46   SIMIX_req_process_cleanup(smx_proc);
47 }
48
49 /* This function creates a MSG process. It has the prototype enforced by SIMIX_function_register_process_create */
50 void MSG_process_create_from_SIMIX(smx_process_t* process, const char *name,
51                                     xbt_main_func_t code, void *data,
52                                     const char *hostname, int argc, char **argv,
53                                     xbt_dict_t properties)
54 {
55   m_host_t host = MSG_get_host_by_name(hostname);
56   m_process_t p = MSG_process_create_with_environment(name, code, data,
57                                                       host, argc, argv,
58                                                       properties);
59   *((m_process_t*) process) = p;
60 }
61
62 /** \ingroup m_process_management
63  * \brief Creates and runs a new #m_process_t.
64  *
65  * Does exactly the same as #MSG_process_create_with_arguments but without
66    providing standard arguments (\a argc, \a argv, \a start_time, \a kill_time).
67  * \sa MSG_process_create_with_arguments
68  */
69 m_process_t MSG_process_create(const char *name,
70                                xbt_main_func_t code, void *data,
71                                m_host_t host)
72 {
73   return MSG_process_create_with_environment(name, code, data, host, -1,
74                                              NULL, NULL);
75 }
76
77 /** \ingroup m_process_management
78  * \brief Creates and runs a new #m_process_t.
79
80  * A constructor for #m_process_t taking four arguments and returning the
81  * corresponding object. The structure (and the corresponding thread) is
82  * created, and put in the list of ready process.
83  * \param name a name for the object. It is for user-level information
84    and can be NULL.
85  * \param code is a function describing the behavior of the agent. It
86    should then only use functions described in \ref
87    m_process_management (to create a new #m_process_t for example),
88    in \ref m_host_management (only the read-only functions i.e. whose
89    name contains the word get), in \ref m_task_management (to create
90    or destroy some #m_task_t for example) and in \ref
91    msg_gos_functions (to handle file transfers and task processing).
92  * \param data a pointer to any data one may want to attach to the new
93    object.  It is for user-level information and can be NULL. It can
94    be retrieved with the function \ref MSG_process_get_data.
95  * \param host the location where the new agent is executed.
96  * \param argc first argument passed to \a code
97  * \param argv second argument passed to \a code
98  * \see m_process_t
99  * \return The new corresponding object.
100  */
101
102 m_process_t MSG_process_create_with_arguments(const char *name,
103                                               xbt_main_func_t code,
104                                               void *data, m_host_t host,
105                                               int argc, char **argv)
106 {
107   return MSG_process_create_with_environment(name, code, data, host,
108                                              argc, argv, NULL);
109 }
110
111 /** \ingroup m_process_management
112  * \brief Creates and runs a new #m_process_t.
113
114  * A constructor for #m_process_t taking four arguments and returning the
115  * corresponding object. The structure (and the corresponding thread) is
116  * created, and put in the list of ready process.
117  * \param name a name for the object. It is for user-level information
118    and can be NULL.
119  * \param code is a function describing the behavior of the agent. It
120    should then only use functions described in \ref
121    m_process_management (to create a new #m_process_t for example),
122    in \ref m_host_management (only the read-only functions i.e. whose
123    name contains the word get), in \ref m_task_management (to create
124    or destroy some #m_task_t for example) and in \ref
125    msg_gos_functions (to handle file transfers and task processing).
126  * \param data a pointer to any data one may want to attach to the new
127    object.  It is for user-level information and can be NULL. It can
128    be retrieved with the function \ref MSG_process_get_data.
129  * \param host the location where the new agent is executed.
130  * \param argc first argument passed to \a code
131  * \param argv second argument passed to \a code
132  * \param properties list a properties defined for this process
133  * \see m_process_t
134  * \return The new corresponding object.
135  */
136 m_process_t MSG_process_create_with_environment(const char *name,
137                                                 xbt_main_func_t code,
138                                                 void *data, m_host_t host,
139                                                 int argc, char **argv,
140                                                 xbt_dict_t properties)
141 {
142   xbt_assert0(code != NULL && host != NULL, "Invalid parameters");
143   simdata_process_t simdata = xbt_new0(s_simdata_process_t, 1);
144   m_process_t process;
145
146   /* Simulator data for MSG */
147   simdata->PID = msg_global->PID++;
148   simdata->waiting_action = NULL;
149   simdata->waiting_task = NULL;
150   simdata->m_host = host;
151   simdata->argc = argc;
152   simdata->argv = argv;
153   simdata->data = data;
154   simdata->last_errno = MSG_OK;
155
156   if (SIMIX_process_self()) {
157     simdata->PPID = MSG_process_get_PID(MSG_process_self());
158   } else {
159     simdata->PPID = -1;
160   }
161
162   /* Let's create the process: SIMIX may decide to start it right now,
163    * even before returning the flow control to us */
164   SIMIX_req_process_create(&process, name, code, simdata, host->name,
165                            argc, argv, properties);
166
167 #ifdef HAVE_TRACING
168   TRACE_msg_process_create(process);
169 #endif
170
171   if (!process) {
172     /* Undo everything we have just changed */
173     msg_global->PID--;
174     xbt_free(simdata);
175     return NULL;
176   }
177
178   return process;
179 }
180
181 void MSG_process_kill_from_SIMIX(smx_process_t p)
182 {
183 #ifdef HAVE_TRACING
184   TRACE_msg_process_kill(p);
185 #endif
186   MSG_process_kill(p);
187 }
188
189 /** \ingroup m_process_management
190  * \param process poor victim
191  *
192  * This function simply kills a \a process... scary isn't it ? :)
193  */
194 void MSG_process_kill(m_process_t process)
195 {
196 #ifdef HAVE_TRACING
197   TRACE_msg_process_kill(process);
198 #endif
199
200   /* FIXME: why do we only cancel communication actions? is this useful? */
201   simdata_process_t p_simdata = SIMIX_req_process_get_data(process);
202   if (p_simdata->waiting_task && p_simdata->waiting_task->simdata->comm) {
203     SIMIX_req_comm_cancel(p_simdata->waiting_task->simdata->comm);
204   }
205  
206   SIMIX_req_process_kill(process);
207
208   return;
209 }
210
211 /** \ingroup m_process_management
212  * \brief Migrates an agent to another location.
213  *
214  * This function checks whether \a process and \a host are valid pointers
215    and change the value of the #m_host_t on which \a process is running.
216  */
217 MSG_error_t MSG_process_change_host(m_host_t host)
218 {
219   m_process_t process = MSG_process_self();
220   simdata_process_t simdata = SIMIX_process_self_get_data();
221   m_host_t now = simdata->m_host;
222   simdata->m_host = host;
223 #ifdef HAVE_TRACING
224   TRACE_msg_process_change_host(process, now, host);
225 #endif
226   SIMIX_req_process_change_host(process, now->name, host->name);
227   return MSG_OK;
228 }
229
230 /** \ingroup m_process_management
231  * \brief Returns the user data of a process.
232  *
233  * This function checks whether \a process is a valid pointer or not
234    and returns the user data associated to this process.
235  */
236 void* MSG_process_get_data(m_process_t process)
237 {
238   xbt_assert0(process != NULL, "Invalid parameter");
239
240   /* get from SIMIX the MSG process data, and then the user data */
241   simdata_process_t simdata = SIMIX_req_process_get_data(process);
242   return simdata->data;
243 }
244
245 /** \ingroup m_process_management
246  * \brief Sets the user data of a process.
247  *
248  * This function checks whether \a process is a valid pointer or not
249    and sets the user data associated to this process.
250  */
251 MSG_error_t MSG_process_set_data(m_process_t process, void *data)
252 {
253   xbt_assert0(process != NULL, "Invalid parameter");
254
255   simdata_process_t simdata = SIMIX_req_process_get_data(process);
256   simdata->data = data;
257
258   return MSG_OK;
259 }
260
261 /** \ingroup m_process_management
262  * \brief Return the location on which an agent is running.
263  *
264  * This function checks whether \a process is a valid pointer or not
265    and return the m_host_t corresponding to the location on which \a
266    process is running.
267  */
268 m_host_t MSG_process_get_host(m_process_t process)
269 {
270   xbt_assert0(process != NULL, "Invalid parameter");
271
272   simdata_process_t simdata = SIMIX_req_process_get_data(process);
273   return simdata->m_host;
274 }
275
276 /** \ingroup m_process_management
277  *
278  * \brief Return a #m_process_t given its PID.
279  *
280  * This function search in the list of all the created m_process_t for a m_process_t
281    whose PID is equal to \a PID. If no host is found, \c NULL is returned.
282    Note that the PID are uniq in the whole simulation, not only on a given host.
283  */
284 m_process_t MSG_process_from_PID(int PID)
285 {
286   /* FIXME: reimplement this function using SIMIX when we have a good PID.
287    * In the meantime, I guess nobody uses it so it should not break anything. */
288   THROW_UNIMPLEMENTED;
289 }
290
291 /** \ingroup m_process_management
292  * \brief Returns the process ID of \a process.
293  *
294  * This function checks whether \a process is a valid pointer or not
295    and return its PID (or 0 in case of problem).
296  */
297 int MSG_process_get_PID(m_process_t process)
298 {
299   /* Do not raise an exception here: this function is called by the logs
300    * and the exceptions, so it would be called back again and again */
301   if (process == NULL) {
302     return 0;
303   }
304
305   simdata_process_t simdata = SIMIX_req_process_get_data(process);
306
307   return simdata != NULL ? simdata->PID : 0;
308 }
309
310 /** \ingroup m_process_management
311  * \brief Returns the process ID of the parent of \a process.
312  *
313  * This function checks whether \a process is a valid pointer or not
314    and return its PID. Returns -1 if the agent has not been created by
315    another agent.
316  */
317 int MSG_process_get_PPID(m_process_t process)
318 {
319   xbt_assert0(process != NULL, "Invalid parameter");
320
321   simdata_process_t simdata = SIMIX_req_process_get_data(process);
322
323   return simdata->PPID;
324 }
325
326 /** \ingroup m_process_management
327  * \brief Return the name of an agent.
328  *
329  * This function checks whether \a process is a valid pointer or not
330    and return its name.
331  */
332 const char *MSG_process_get_name(m_process_t process)
333 {
334   xbt_assert0(process, "Invalid parameter");
335
336   return SIMIX_req_process_get_name(process);
337 }
338
339 /** \ingroup m_process_management
340  * \brief Returns the value of a given process property
341  *
342  * \param process a process
343  * \param name a property name
344  * \return value of a property (or NULL if the property is not set)
345  */
346 const char *MSG_process_get_property_value(m_process_t process,
347                                            const char *name)
348 {
349   return xbt_dict_get_or_null(MSG_process_get_properties(process), name);
350 }
351
352 /** \ingroup m_process_management
353  * \brief Return the list of properties
354  *
355  * This function returns all the parameters associated with a process
356  */
357 xbt_dict_t MSG_process_get_properties(m_process_t process)
358 {
359   xbt_assert0(process != NULL, "Invalid parameter");
360
361   return SIMIX_req_process_get_properties(process);
362
363 }
364
365 /** \ingroup m_process_management
366  * \brief Return the PID of the current agent.
367  *
368  * This function returns the PID of the currently running #m_process_t.
369  */
370 int MSG_process_self_PID(void)
371 {
372   return MSG_process_get_PID(MSG_process_self());
373 }
374
375 /** \ingroup m_process_management
376  * \brief Return the PPID of the current agent.
377  *
378  * This function returns the PID of the parent of the currently
379  * running #m_process_t.
380  */
381 int MSG_process_self_PPID(void)
382 {
383   return MSG_process_get_PPID(MSG_process_self());
384 }
385
386 /** \ingroup m_process_management
387  * \brief Return the current process.
388  *
389  * This function returns the currently running #m_process_t.
390  */
391 m_process_t MSG_process_self(void)
392 {
393   return SIMIX_process_self();
394 }
395
396 /** \ingroup m_process_management
397  * \brief Suspend the process.
398  *
399  * This function suspends the process by suspending the task on which
400  * it was waiting for the completion.
401  */
402 MSG_error_t MSG_process_suspend(m_process_t process)
403 {
404   xbt_assert0(process != NULL, "Invalid parameter");
405   CHECK_HOST();
406
407 #ifdef HAVE_TRACING
408   TRACE_msg_process_suspend(process);
409 #endif
410
411   SIMIX_req_process_suspend(process);
412   MSG_RETURN(MSG_OK);
413 }
414
415 /** \ingroup m_process_management
416  * \brief Resume a suspended process.
417  *
418  * This function resumes a suspended process by resuming the task on
419  * which it was waiting for the completion.
420  */
421 MSG_error_t MSG_process_resume(m_process_t process)
422 {
423   xbt_assert0(process != NULL, "Invalid parameter");
424   CHECK_HOST();
425
426 #ifdef HAVE_TRACING
427   TRACE_msg_process_resume(process);
428 #endif
429
430   SIMIX_req_process_resume(process);
431   MSG_RETURN(MSG_OK);
432 }
433
434 /** \ingroup m_process_management
435  * \brief Returns true if the process is suspended .
436  *
437  * This checks whether a process is suspended or not by inspecting the
438  * task on which it was waiting for the completion.
439  */
440 int MSG_process_is_suspended(m_process_t process)
441 {
442   xbt_assert0(process != NULL, "Invalid parameter");
443   return SIMIX_req_process_is_suspended(process);
444 }
445
446 smx_context_t MSG_process_get_smx_ctx(m_process_t process) {
447   return SIMIX_process_get_context(process);
448 }