Logo AND Algorithmique Numérique Distribuée

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