Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
start to untangle the MSG actor creation mess
[simgrid.git] / src / msg / msg_process.cpp
1 /* Copyright (c) 2004-2015. 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 "simgrid/s4u/host.hpp"
9 #include "src/simix/ActorImpl.hpp"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_process, msg, "Logging specific to MSG (process)");
12
13 /** @addtogroup m_process_management
14  *
15  *  Processes (#msg_process_t) are independent agents that can do stuff on their own. They are in charge of executing
16  *  your code interacting with the simulated world.
17  *  A process may be defined as a <em>code</em> with some <em>private data</em>.
18  *  Processes must be located on <em>hosts</em> (#msg_host_t), and they exchange data by sending tasks (#msg_task_t)
19  *  that are similar to envelops containing data.
20  */
21
22 /******************************** Process ************************************/
23 /**
24  * \brief Cleans the MSG data of a process.
25  * \param smx_proc a SIMIX process
26  */
27 void MSG_process_cleanup_from_SIMIX(smx_actor_t smx_actor)
28 {
29   MsgActorExt* msg_actor;
30
31   // get the MSG process from the SIMIX process
32   if (smx_actor == SIMIX_process_self()) {
33     /* avoid a SIMIX request if this function is called by the process itself */
34     msg_actor = (MsgActorExt*)SIMIX_process_self_get_data();
35     SIMIX_process_self_set_data(nullptr);
36   } else {
37     msg_actor = (MsgActorExt*)smx_actor->data;
38     simcall_process_set_data(smx_actor, nullptr);
39   }
40
41   TRACE_msg_process_destroy(smx_actor->name.c_str(), smx_actor->pid);
42   // free the data if a function was provided
43   if (msg_actor && msg_actor->data && msg_global->process_data_cleanup) {
44     msg_global->process_data_cleanup(msg_actor->data);
45   }
46
47   // free the MSG process
48   xbt_free(msg_actor);
49   SIMIX_process_cleanup(smx_actor);
50 }
51
52 /* This function creates a MSG process. It has the prototype enforced by SIMIX_function_register_process_create */
53 smx_actor_t MSG_process_create_from_SIMIX(const char* name, std::function<void()> code, void* data, sg_host_t host,
54                                           xbt_dict_t properties, int auto_restart, smx_actor_t parent_process)
55 {
56   msg_process_t p = MSG_process_create_with_environment(name, std::move(code), data, host, properties);
57   if (p) {
58     MSG_process_auto_restart_set(p,auto_restart);
59   }
60   return p;
61 }
62
63 /** \ingroup m_process_management
64  * \brief Creates and runs a new #msg_process_t.
65  *
66  * Does exactly the same as #MSG_process_create_with_arguments but without providing standard arguments
67  * (\a argc, \a argv, \a start_time, \a kill_time).
68  * \sa MSG_process_create_with_arguments
69  */
70 msg_process_t MSG_process_create(const char *name, xbt_main_func_t code, void *data, msg_host_t host)
71 {
72   return MSG_process_create_with_environment(name, code, data, host, 0, nullptr, nullptr);
73 }
74
75 /** \ingroup m_process_management
76  * \brief Creates and runs a new #msg_process_t.
77
78  * A constructor for #msg_process_t taking four arguments and returning the corresponding object. The structure (and
79  * the corresponding thread) is created, and put in the list of ready process.
80  * \param name a name for the object. It is for user-level information and can be nullptr.
81  * \param code is a function describing the behavior of the process. It should then only use functions described
82  * in \ref m_process_management (to create a new #msg_process_t for example),
83    in \ref m_host_management (only the read-only functions i.e. whose name contains the word get),
84    in \ref m_task_management (to create or destroy some #msg_task_t for example) and
85    in \ref msg_task_usage (to handle file transfers and task processing).
86  * \param data a pointer to any data one may want to attach to the new object.  It is for user-level information and
87  *        can be nullptr. It can be retrieved with the function \ref MSG_process_get_data.
88  * \param host the location where the new process is executed.
89  * \param argc first argument passed to \a code
90  * \param argv second argument passed to \a code
91  * \see msg_process_t
92  * \return The new corresponding object.
93  */
94
95 msg_process_t MSG_process_create_with_arguments(const char *name, xbt_main_func_t code, void *data, msg_host_t host,
96                                               int argc, char **argv)
97 {
98   return MSG_process_create_with_environment(name, code, data, host, argc, argv, nullptr);
99 }
100
101 /** \ingroup m_process_management
102  * \brief Creates and runs a new #msg_process_t.
103
104  * A constructor for #msg_process_t taking four arguments and returning the corresponding object. The structure (and
105  * the corresponding thread) is created, and put in the list of ready process.
106  * \param name a name for the object. It is for user-level information and can be nullptr.
107  * \param code is a function describing the behavior of the process. It should then only use functions described
108  * in \ref m_process_management (to create a new #msg_process_t for example),
109    in \ref m_host_management (only the read-only functions i.e. whose name contains the word get),
110    in \ref m_task_management (to create or destroy some #msg_task_t for example) and
111    in \ref msg_task_usage (to handle file transfers and task processing).
112  * \param data a pointer to any data one may want to attach to the new object.  It is for user-level information and
113  *        can be nullptr. It can be retrieved with the function \ref MSG_process_get_data.
114  * \param host the location where the new process is executed.
115  * \param argc first argument passed to \a code
116  * \param argv second argument passed to \a code. WARNING, these strings are freed by the SimGrid kernel when the
117  *             process exits, so they cannot be static nor shared between several processes.
118  * \param properties list a properties defined for this process
119  * \see msg_process_t
120  * \return The new corresponding object.
121  */
122 msg_process_t MSG_process_create_with_environment(const char *name, xbt_main_func_t code, void *data, msg_host_t host,
123                                                   int argc, char **argv, xbt_dict_t properties)
124 {
125   std::function<void()> function;
126   if (code)
127     function = simgrid::xbt::wrapMain(code, argc, const_cast<const char*const*>(argv));
128   msg_process_t res = MSG_process_create_with_environment(name,
129     std::move(function), data, host, properties);
130   for (int i = 0; i != argc; ++i)
131     xbt_free(argv[i]);
132   xbt_free(argv);
133   return res;
134 }
135
136 msg_process_t MSG_process_create_with_environment(
137   const char *name, std::function<void()> code, void *data,
138   msg_host_t host, xbt_dict_t properties)
139 {
140   xbt_assert(code != nullptr && host != nullptr, "Invalid parameters: host and code params must not be nullptr");
141   MsgActorExt* msgExt = new MsgActorExt(data);
142
143   /* Let's create the process: SIMIX may decide to start it right now,
144    * even before returning the flow control to us */
145   msg_process_t process = simcall_process_create(name, std::move(code), msgExt, host, properties, 0);
146
147   if (!process) { /* Undo everything */
148     delete msgExt;
149     return nullptr;
150   }
151   else {
152     simcall_process_on_exit(process,(int_f_pvoid_pvoid_t)TRACE_msg_process_kill,process);
153   }
154   return process;
155 }
156
157 /* Become a process in the simulation
158  *
159  * Currently this can only be called by the main thread (once) and only work with some thread factories
160  * (currently ThreadContextFactory).
161  *
162  * In the future, it might be extended in order to attach other threads created by a third party library.
163  */
164 msg_process_t MSG_process_attach(const char *name, void *data, msg_host_t host, xbt_dict_t properties)
165 {
166   xbt_assert(host != nullptr, "Invalid parameters: host and code params must not be nullptr");
167
168   /* Let's create the process: SIMIX may decide to start it right now, even before returning the flow control to us */
169   msg_process_t process = SIMIX_process_attach(name, new MsgActorExt(data), host->cname(), properties, nullptr);
170   if (!process)
171     xbt_die("Could not attach");
172   simcall_process_on_exit(process,(int_f_pvoid_pvoid_t)TRACE_msg_process_kill,process);
173   return process;
174 }
175
176 /** Detach a process attached with `MSG_process_attach()`
177  *
178  *  This is called when the current process has finished its job.
179  *  Used in the main thread, it waits for the simulation to finish before  returning. When it returns, the other
180  *  simulated processes and the maestro are destroyed.
181  */
182 void MSG_process_detach()
183 {
184   SIMIX_process_detach();
185 }
186
187 /** \ingroup m_process_management
188  * \param process poor victim
189  *
190  * This function simply kills a \a process... scary isn't it ? :)
191  */
192 void MSG_process_kill(msg_process_t process)
193 {
194   simcall_process_kill(process);
195 }
196
197 /**
198 * \brief Wait for the completion of a #msg_process_t.
199 *
200 * \param process the process to wait for
201 * \param timeout wait until the process is over, or the timeout occurs
202 */
203 msg_error_t MSG_process_join(msg_process_t process, double timeout){
204   simcall_process_join(process, timeout);
205   return MSG_OK;
206 }
207
208 /** \ingroup m_process_management
209  * \brief Migrates a process to another location.
210  *
211  * This function checks whether \a process and \a host are valid pointers and change the value of the #msg_host_t on
212  * which \a process is running.
213  */
214 msg_error_t MSG_process_migrate(msg_process_t process, msg_host_t host)
215 {
216   TRACE_msg_process_change_host(process, MSG_process_get_host(process), host);
217   simcall_process_set_host(process, host);
218   return MSG_OK;
219 }
220
221 /** Yield the current actor; let the other actors execute first */
222 void MSG_process_yield()
223 {
224   simgrid::simix::kernelImmediate([] { /* do nothing*/ });
225 }
226
227 /** \ingroup m_process_management
228  * \brief Returns the user data of a process.
229  *
230  * This function checks whether \a process is a valid pointer and returns the user data associated to this process.
231  */
232 void* MSG_process_get_data(msg_process_t process)
233 {
234   xbt_assert(process != nullptr, "Invalid parameter: first parameter must not be nullptr!");
235
236   /* get from SIMIX the MSG process data, and then the user data */
237   MsgActorExt* msgExt = (MsgActorExt*)process->data;
238   if (msgExt)
239     return msgExt->data;
240   else
241     return nullptr;
242 }
243
244 /** \ingroup m_process_management
245  * \brief Sets the user data of a process.
246  *
247  * This function checks whether \a process is a valid pointer and sets the user data associated to this process.
248  */
249 msg_error_t MSG_process_set_data(msg_process_t process, void *data)
250 {
251   xbt_assert(process != nullptr, "Invalid parameter: first parameter must not be nullptr!");
252
253   MsgActorExt* msgExt = (MsgActorExt*)process->data;
254   msgExt->data        = data;
255
256   return MSG_OK;
257 }
258
259 /** \ingroup m_process_management
260  * \brief Sets a cleanup function to be called to free the userdata of a process when a process is destroyed.
261  * \param data_cleanup a cleanup function for the userdata of a process, or nullptr to call no function
262  */
263 XBT_PUBLIC(void) MSG_process_set_data_cleanup(void_f_pvoid_t data_cleanup) {
264   msg_global->process_data_cleanup = data_cleanup;
265 }
266
267 /** \ingroup m_process_management
268  * \brief Return the location on which a process is running.
269  * \param process a process (nullptr means the current one)
270  * \return the msg_host_t corresponding to the location on which \a process is running.
271  */
272 msg_host_t MSG_process_get_host(msg_process_t process)
273 {
274   if (process == nullptr) {
275     return MSG_process_self()->host;
276   } else {
277     return process->host;
278   }
279 }
280
281 /** \ingroup m_process_management
282  *
283  * \brief Return a #msg_process_t given its PID.
284  *
285  * This function search in the list of all the created msg_process_t for a msg_process_t  whose PID is equal to \a PID.
286  * If no host is found, \c nullptr is returned.
287    Note that the PID are uniq in the whole simulation, not only on a given host.
288  */
289 msg_process_t MSG_process_from_PID(int PID)
290 {
291   return SIMIX_process_from_PID(PID);
292 }
293
294 /** @brief returns a list of all currently existing processes */
295 xbt_dynar_t MSG_processes_as_dynar() {
296   return SIMIX_processes_as_dynar();
297 }
298
299 /** @brief Return the current number MSG processes. */
300 int MSG_process_get_number()
301 {
302   return SIMIX_process_count();
303 }
304
305 /** \ingroup m_process_management
306  * \brief Set the kill time of a process.
307  *
308  * \param process a process
309  * \param kill_time the time when the process is killed.
310  */
311 msg_error_t MSG_process_set_kill_time(msg_process_t process, double kill_time)
312 {
313   simcall_process_set_kill_time(process,kill_time);
314   return MSG_OK;
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 and return its PID (or 0 in case of problem).
321  */
322 int MSG_process_get_PID(msg_process_t process)
323 {
324   /* Do not raise an exception here: this function is called by the logs
325    * and the exceptions, so it would be called back again and again */
326   if (process == nullptr)
327     return 0;
328   return process->pid;
329 }
330
331 /** \ingroup m_process_management
332  * \brief Returns the process ID of the parent of \a process.
333  *
334  * This function checks whether \a process is a valid pointer and return its PID.
335  * Returns -1 if the process has not been created by any other process.
336  */
337 int MSG_process_get_PPID(msg_process_t process)
338 {
339   return process->ppid;
340 }
341
342 /** \ingroup m_process_management
343  * \brief Return the name of a process.
344  *
345  * This function checks whether \a process is a valid pointer and return its name.
346  */
347 const char *MSG_process_get_name(msg_process_t process)
348 {
349   return process->name.c_str();
350 }
351
352 /** \ingroup m_process_management
353  * \brief Returns the value of a given process property
354  *
355  * \param process a process
356  * \param name a property name
357  * \return value of a property (or nullptr if the property is not set)
358  */
359 const char *MSG_process_get_property_value(msg_process_t process, const char *name)
360 {
361   return (char*) xbt_dict_get_or_null(MSG_process_get_properties(process), name);
362 }
363
364 /** \ingroup m_process_management
365  * \brief Return the list of properties
366  *
367  * This function returns all the parameters associated with a process
368  */
369 xbt_dict_t MSG_process_get_properties(msg_process_t process)
370 {
371   xbt_assert(process != nullptr, "Invalid parameter: First argument must not be nullptr");
372   return simcall_process_get_properties(process);
373 }
374
375 /** \ingroup m_process_management
376  * \brief Return the PID of the current process.
377  *
378  * This function returns the PID of the currently running #msg_process_t.
379  */
380 int MSG_process_self_PID()
381 {
382   return MSG_process_get_PID(MSG_process_self());
383 }
384
385 /** \ingroup m_process_management
386  * \brief Return the PPID of the current process.
387  *
388  * This function returns the PID of the parent of the currently running #msg_process_t.
389  */
390 int MSG_process_self_PPID()
391 {
392   return MSG_process_get_PPID(MSG_process_self());
393 }
394
395 /** \ingroup m_process_management
396  * \brief Return the current process.
397  *
398  * This function returns the currently running #msg_process_t.
399  */
400 msg_process_t MSG_process_self()
401 {
402   return SIMIX_process_self();
403 }
404
405 /** \ingroup m_process_management
406  * \brief Suspend the process.
407  *
408  * This function suspends the process by suspending the task on which it was waiting for the completion.
409  */
410 msg_error_t MSG_process_suspend(msg_process_t process)
411 {
412   xbt_assert(process != nullptr, "Invalid parameter: First argument must not be nullptr");
413
414   TRACE_msg_process_suspend(process);
415   simcall_process_suspend(process);
416   return MSG_OK;
417 }
418
419 /** \ingroup m_process_management
420  * \brief Resume a suspended process.
421  *
422  * This function resumes a suspended process by resuming the task on which it was waiting for the completion.
423  */
424 msg_error_t MSG_process_resume(msg_process_t process)
425 {
426   xbt_assert(process != nullptr, "Invalid parameter: First argument must not be nullptr");
427
428   TRACE_msg_process_resume(process);
429   simcall_process_resume(process);
430   return MSG_OK;
431 }
432
433 /** \ingroup m_process_management
434  * \brief Returns true if the process is suspended .
435  *
436  * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
437  */
438 int MSG_process_is_suspended(msg_process_t process)
439 {
440   xbt_assert(process != nullptr, "Invalid parameter: First argument must not be nullptr");
441   return simcall_process_is_suspended(process);
442 }
443
444 smx_context_t MSG_process_get_smx_ctx(msg_process_t process) {
445   return SIMIX_process_get_context(process);
446 }
447 /**
448  * \ingroup m_process_management
449  * \brief Add a function to the list of "on_exit" functions for the current process.
450  * The on_exit functions are the functions executed when your process is killed.
451  * You should use them to free the data used by your process.
452  */
453 void MSG_process_on_exit(int_f_pvoid_pvoid_t fun, void *data) {
454   simcall_process_on_exit(MSG_process_self(),fun,data);
455 }
456 /**
457  * \ingroup m_process_management
458  * \brief Sets the "auto-restart" flag of the process.
459  * If the flag is set to 1, the process will be automatically restarted when its host comes back up.
460  */
461 XBT_PUBLIC(void) MSG_process_auto_restart_set(msg_process_t process, int auto_restart) {
462   simcall_process_auto_restart_set(process,auto_restart);
463 }
464 /*
465  * \ingroup m_process_management
466  * \brief Restarts a process from the beginning.
467  */
468 XBT_PUBLIC(msg_process_t) MSG_process_restart(msg_process_t process) {
469   return simcall_process_restart(process);
470 }