Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
MSG almost works. It enabled me to find some bug in the SURF. I'm going to optimize...
[simgrid.git] / src / msg / m_process.c
1 /*      $Id$     */
2
3 /* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved.        */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include"private.h"
9 #include"xbt/sysdep.h"
10 #include "xbt/error.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(m_process, msg,
12                                 "Logging specific to MSG (process)");
13
14 /******************************** Process ************************************/
15 /** \ingroup m_process_management
16  * \brief Creates and runs a new #m_process_t.
17
18  * A constructor for #m_process_t taking four arguments and returning the 
19  * corresponding object. The structure (and the corresponding thread) is
20  * created, and put in the list of ready process.
21  * \param name a name for the object. It is for user-level information
22    and can be NULL.
23  * \param code is a function describing the behavior of the agent. It
24    should then only use functions described in \ref
25    m_process_management (to create a new #m_process_t for example),
26    in \ref m_host_management (only the read-only functions i.e. whose
27    name contains the word get), in \ref m_task_management (to create
28    or destroy some #m_task_t for example) and in \ref
29    msg_gos_functions (to handle file transfers and task processing).
30  * \param data a pointer to any data may want to attach to the new
31    object.  It is for user-level information and can be NULL. It can
32    be retrieved with the function \ref MSG_process_get_data.
33  * \param host the location where the new agent is executed.
34  * \see m_process_t
35  * \return The new corresponding object.
36  */
37 m_process_t MSG_process_create(const char *name,
38                                m_process_code_t code, void *data,
39                                m_host_t host)
40 {
41   return MSG_process_create_with_arguments(name, code, data, host, -1, NULL);
42 }
43
44 static void MSG_process_cleanup(void *arg)
45 {
46   xbt_fifo_remove(msg_global->process_list, arg);
47   xbt_fifo_remove(msg_global->process_to_run, arg);
48 }
49
50 m_process_t MSG_process_create_with_arguments(const char *name,
51                                               m_process_code_t code, void *data,
52                                               m_host_t host, int argc, char **argv)
53 {
54   simdata_process_t simdata = xbt_new0(s_simdata_process_t,1);
55   m_process_t process = xbt_new0(s_m_process_t,1);
56   m_process_t self = NULL;
57   static int PID = 1;
58
59   xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
60   /* Simulator Data */
61
62   simdata->PID = PID++;
63   simdata->host = host;
64   simdata->waiting_task = NULL;
65   simdata->argc = argc;
66   simdata->argv = argv;
67   simdata->context = xbt_context_new(code, NULL, NULL, 
68                                      MSG_process_cleanup, process, 
69                                      simdata->argc, simdata->argv);
70
71   if((self=msg_global->current_process)) {
72     simdata->PPID = MSG_process_get_PID(self);
73   } else {
74     simdata->PPID = -1;
75   }
76   simdata->last_errno=MSG_OK;
77
78
79   /* Process structure */
80   process->name = xbt_strdup(name);
81   process->simdata = simdata;
82   process->data = data;
83
84   xbt_fifo_push(host->simdata->process_list, process);
85
86   /* /////////////// FIX du current_process !!! ////////////// */
87   self = msg_global->current_process;
88   xbt_context_start(process->simdata->context);
89   msg_global->current_process = self;
90
91   xbt_fifo_push(msg_global->process_list, process);
92   xbt_fifo_push(msg_global->process_to_run, process);
93
94   return process;
95 }
96
97 /** \ingroup m_process_management
98  * \brief Migrates an agent to another location.
99  *
100  * This functions checks whether \a process and \a host are valid pointers
101    and change the value of the #m_host_t on which \a process is running.
102  */
103 MSG_error_t MSG_process_change_host(m_process_t process, m_host_t host)
104 {
105   simdata_process_t simdata = NULL;
106
107   /* Sanity check */
108
109   xbt_assert0(((process) && (process->simdata)
110           && (host)), "Invalid parameters");
111   simdata = process->simdata;
112
113   xbt_fifo_remove(simdata->host->simdata->process_list,process);
114   simdata->host = host;
115   xbt_fifo_push(host->simdata->process_list,process);
116
117   return MSG_OK;
118 }
119
120 /** \ingroup m_process_management
121  * \brief Return the user data of a #m_process_t.
122  *
123  * This functions checks whether \a process is a valid pointer or not 
124    and return the user data associated to \a process if it is possible.
125  */
126 void *MSG_process_get_data(m_process_t process)
127 {
128   xbt_assert0((process != NULL), "Invalid parameters");
129
130   return (process->data);
131 }
132
133 /** \ingroup m_process_management
134  * \brief Set the user data of a #m_process_t.
135  *
136  * This functions checks whether \a process is a valid pointer or not 
137    and set the user data associated to \a process if it is possible.
138  */
139 MSG_error_t MSG_process_set_data(m_process_t process,void *data)
140 {
141   xbt_assert0((process != NULL), "Invalid parameters");
142   xbt_assert0((process->data == NULL), "Data already set");
143   
144   process->data = data;
145    
146   return MSG_OK;
147 }
148
149 /** \ingroup m_process_management
150  * \brief Return the location on which an agent is running.
151  *
152  * This functions checks whether \a process is a valid pointer or not 
153    and return the m_host_t corresponding to the location on which \a 
154    process is running.
155  */
156 m_host_t MSG_process_get_host(m_process_t process)
157 {
158   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
159
160   return (((simdata_process_t) process->simdata)->host);
161 }
162
163 /** \ingroup m_process_management
164  *
165  * \brief Return a #m_process_t given its PID.
166  *
167  * This functions search in the list of all the created m_process_t for a m_process_t 
168    whose PID is equal to \a PID. If no host is found, \c NULL is returned. 
169    Note that the PID are uniq in the whole simulation, not only on a given host.
170  */
171 m_process_t MSG_process_from_PID(int PID)
172 {
173   xbt_fifo_item_t i = NULL;
174   m_process_t process = NULL;
175
176   xbt_fifo_foreach(msg_global->process_list,i,process,m_process_t) {
177     if(MSG_process_get_PID(process) == PID) return process;
178   }
179   return NULL;
180 }
181
182 /** \ingroup m_process_management
183  * \brief Returns the process ID of \a process.
184  *
185  * This functions checks whether \a process is a valid pointer or not 
186    and return its PID.
187  */
188 int MSG_process_get_PID(m_process_t process)
189 {
190   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
191
192   return (((simdata_process_t) process->simdata)->PID);
193 }
194
195
196 /** \ingroup m_process_management
197  * \brief Returns the process ID of the parent of \a process.
198  *
199  * This functions checks whether \a process is a valid pointer or not 
200    and return its PID. Returns -1 if the agent has not been created by 
201    another agent.
202  */
203 int MSG_process_get_PPID(m_process_t process)
204 {
205   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
206
207   return (((simdata_process_t) process->simdata)->PPID);
208 }
209
210 /** \ingroup m_process_management
211  * \brief Return the name of an agent.
212  *
213  * This functions checks whether \a process is a valid pointer or not 
214    and return its name.
215  */
216 const char *MSG_process_get_name(m_process_t process)
217 {
218   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
219
220   return (process->name);
221 }
222
223 /** \ingroup m_process_management
224  * \brief Return the PID of the current agent.
225  *
226  * This functions returns the PID of the currently running #m_process_t.
227  */
228 int MSG_process_self_PID(void)
229 {
230   return (MSG_process_get_PID(MSG_process_self()));
231 }
232
233 /** \ingroup m_process_management
234  * \brief Return the PPID of the current agent.
235  *
236  * This functions returns the PID of the parent of the currently
237  * running #m_process_t.
238  */
239 int MSG_process_self_PPID(void)
240 {
241   return (MSG_process_get_PPID(MSG_process_self()));
242 }
243
244 /** \ingroup m_process_management
245  * \brief Return the current agent.
246  *
247  * This functions returns the currently running #m_process_t.
248  */
249 m_process_t MSG_process_self(void)
250 {
251   return msg_global->current_process;
252 }
253
254 /** \ingroup m_process_management
255  * \brief Suspend the process.
256  *
257  * This functions suspend the process by suspending the task on which
258  * it was waiting for the completion.
259  */
260 MSG_error_t MSG_process_suspend(m_process_t process)
261 {
262   simdata_process_t simdata = NULL;
263   simdata_task_t simdata_task = NULL;
264   int i;
265
266   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
267
268   if(process!=MSG_process_self()) {
269     simdata = process->simdata;
270     
271     xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !");
272
273     simdata_task = simdata->waiting_task->simdata;
274
275     xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&&
276                 !((simdata_task->comm)&&(simdata_task->comm)),
277                 "Got a problem in deciding which action to choose !");
278     if(simdata_task->compute) 
279       surf_workstation_resource->extension_public->suspend(simdata_task->compute);
280     else
281       surf_workstation_resource->extension_public->suspend(simdata_task->comm);
282   } else {
283     m_task_t dummy = MSG_TASK_UNINITIALIZED;
284     dummy = MSG_task_create("suspended", 0.0, 0, NULL);
285
286     __MSG_task_execute(process,dummy);
287     surf_workstation_resource->extension_public->suspend(dummy->simdata->compute);
288     __MSG_wait_for_computation(process,dummy);
289
290     MSG_task_destroy(dummy);
291   }
292   return MSG_OK;
293 }
294
295 /** \ingroup m_process_management
296  * \brief Resume a suspended process.
297  *
298  * This functions resume a suspended process by resuming the task on
299  * which it was waiting for the completion.
300  */
301 MSG_error_t MSG_process_resume(m_process_t process)
302 {
303   simdata_process_t simdata = NULL;
304   simdata_task_t simdata_task = NULL;
305   int i;
306
307   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
308   CHECK_HOST();
309
310   simdata = process->simdata;
311   if(!(simdata->waiting_task)) {
312     xbt_assert0(0,"Process not waiting for anything else. Weird !");
313     return MSG_WARNING;
314   }
315   simdata_task = simdata->waiting_task->simdata;
316
317   if(simdata_task->compute) 
318     surf_workstation_resource->extension_public->resume(simdata_task->compute);
319   else 
320     surf_workstation_resource->extension_public->resume(simdata_task->comm);
321
322   MSG_RETURN(MSG_OK);
323 }
324
325 /** \ingroup m_process_management
326  * \brief Returns true if the process is suspended .
327  *
328  * This checks whether a process is suspended or not by inspecting the
329  * task on which it was waiting for the completion.
330  */
331 int MSG_process_isSuspended(m_process_t process)
332 {
333   simdata_process_t simdata = NULL;
334   simdata_task_t simdata_task = NULL;
335   int i;
336   
337   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
338
339   simdata = process->simdata;
340   if(!(simdata->waiting_task)) {
341     xbt_assert0(0,"Process not waiting for anything else. Weird !");
342     return 0;
343   }
344
345   simdata_task = simdata->waiting_task->simdata;
346
347   if(simdata_task->compute) 
348     return surf_workstation_resource->extension_public->is_suspended(simdata_task->compute);
349   else 
350     return surf_workstation_resource->extension_public->is_suspended(simdata_task->comm);
351 }