Logo AND Algorithmique Numérique Distribuée

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