Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
make communications from an host to itself instantaneous
[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   xbt_fifo_remove(((m_process_t) arg)->simdata->host->simdata->process_list, arg);
49   xbt_free(((m_process_t) arg)->name);
50   xbt_free(((m_process_t) arg)->simdata);
51   xbt_free(arg);
52 }
53
54 m_process_t MSG_process_create_with_arguments(const char *name,
55                                               m_process_code_t code, void *data,
56                                               m_host_t host, int argc, char **argv)
57 {
58   simdata_process_t simdata = xbt_new0(s_simdata_process_t,1);
59   m_process_t process = xbt_new0(s_m_process_t,1);
60   m_process_t self = NULL;
61   static int PID = 1;
62
63   xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
64   /* Simulator Data */
65
66   simdata->PID = PID++;
67   simdata->host = host;
68   simdata->waiting_task = NULL;
69   simdata->argc = argc;
70   simdata->argv = argv;
71   simdata->context = xbt_context_new(code, NULL, NULL, 
72                                      MSG_process_cleanup, process, 
73                                      simdata->argc, simdata->argv);
74
75   if((self=msg_global->current_process)) {
76     simdata->PPID = MSG_process_get_PID(self);
77   } else {
78     simdata->PPID = -1;
79   }
80   simdata->last_errno=MSG_OK;
81
82
83   /* Process structure */
84   process->name = xbt_strdup(name);
85   process->simdata = simdata;
86   process->data = data;
87
88   xbt_fifo_push(host->simdata->process_list, process);
89
90   /* /////////////// FIX du current_process !!! ////////////// */
91   self = msg_global->current_process;
92   xbt_context_start(process->simdata->context);
93   msg_global->current_process = self;
94
95   xbt_fifo_push(msg_global->process_list, process);
96   xbt_fifo_push(msg_global->process_to_run, process);
97
98   return process;
99 }
100
101 void MSG_process_free(m_process_t process)
102 {
103   xbt_fifo_remove(msg_global->process_list,process);
104   xbt_context_free(process->simdata->context);
105   MSG_process_cleanup(process);
106 }
107
108 /** \ingroup m_process_management
109  * \brief Migrates an agent to another location.
110  *
111  * This functions checks whether \a process and \a host are valid pointers
112    and change the value of the #m_host_t on which \a process is running.
113  */
114 MSG_error_t MSG_process_change_host(m_process_t process, m_host_t host)
115 {
116   simdata_process_t simdata = NULL;
117
118   /* Sanity check */
119
120   xbt_assert0(((process) && (process->simdata)
121           && (host)), "Invalid parameters");
122   simdata = process->simdata;
123
124   xbt_fifo_remove(simdata->host->simdata->process_list,process);
125   simdata->host = host;
126   xbt_fifo_push(host->simdata->process_list,process);
127
128   return MSG_OK;
129 }
130
131 /** \ingroup m_process_management
132  * \brief Return the user data of a #m_process_t.
133  *
134  * This functions checks whether \a process is a valid pointer or not 
135    and return the user data associated to \a process if it is possible.
136  */
137 void *MSG_process_get_data(m_process_t process)
138 {
139   xbt_assert0((process != NULL), "Invalid parameters");
140
141   return (process->data);
142 }
143
144 /** \ingroup m_process_management
145  * \brief Set the user data of a #m_process_t.
146  *
147  * This functions checks whether \a process is a valid pointer or not 
148    and set the user data associated to \a process if it is possible.
149  */
150 MSG_error_t MSG_process_set_data(m_process_t process,void *data)
151 {
152   xbt_assert0((process != NULL), "Invalid parameters");
153   xbt_assert0((process->data == NULL), "Data already set");
154   
155   process->data = data;
156    
157   return MSG_OK;
158 }
159
160 /** \ingroup m_process_management
161  * \brief Return the location on which an agent is running.
162  *
163  * This functions checks whether \a process is a valid pointer or not 
164    and return the m_host_t corresponding to the location on which \a 
165    process is running.
166  */
167 m_host_t MSG_process_get_host(m_process_t process)
168 {
169   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
170
171   return (((simdata_process_t) process->simdata)->host);
172 }
173
174 /** \ingroup m_process_management
175  *
176  * \brief Return a #m_process_t given its PID.
177  *
178  * This functions search in the list of all the created m_process_t for a m_process_t 
179    whose PID is equal to \a PID. If no host is found, \c NULL is returned. 
180    Note that the PID are uniq in the whole simulation, not only on a given host.
181  */
182 m_process_t MSG_process_from_PID(int PID)
183 {
184   xbt_fifo_item_t i = NULL;
185   m_process_t process = NULL;
186
187   xbt_fifo_foreach(msg_global->process_list,i,process,m_process_t) {
188     if(MSG_process_get_PID(process) == PID) return process;
189   }
190   return NULL;
191 }
192
193 /** \ingroup m_process_management
194  * \brief Returns the process ID of \a process.
195  *
196  * This functions checks whether \a process is a valid pointer or not 
197    and return its PID.
198  */
199 int MSG_process_get_PID(m_process_t process)
200 {
201   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
202
203   return (((simdata_process_t) process->simdata)->PID);
204 }
205
206
207 /** \ingroup m_process_management
208  * \brief Returns the process ID of the parent of \a process.
209  *
210  * This functions checks whether \a process is a valid pointer or not 
211    and return its PID. Returns -1 if the agent has not been created by 
212    another agent.
213  */
214 int MSG_process_get_PPID(m_process_t process)
215 {
216   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
217
218   return (((simdata_process_t) process->simdata)->PPID);
219 }
220
221 /** \ingroup m_process_management
222  * \brief Return the name of an agent.
223  *
224  * This functions checks whether \a process is a valid pointer or not 
225    and return its name.
226  */
227 const char *MSG_process_get_name(m_process_t process)
228 {
229   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
230
231   return (process->name);
232 }
233
234 /** \ingroup m_process_management
235  * \brief Return the PID of the current agent.
236  *
237  * This functions returns the PID of the currently running #m_process_t.
238  */
239 int MSG_process_self_PID(void)
240 {
241   return (MSG_process_get_PID(MSG_process_self()));
242 }
243
244 /** \ingroup m_process_management
245  * \brief Return the PPID of the current agent.
246  *
247  * This functions returns the PID of the parent of the currently
248  * running #m_process_t.
249  */
250 int MSG_process_self_PPID(void)
251 {
252   return (MSG_process_get_PPID(MSG_process_self()));
253 }
254
255 /** \ingroup m_process_management
256  * \brief Return the current agent.
257  *
258  * This functions returns the currently running #m_process_t.
259  */
260 m_process_t MSG_process_self(void)
261 {
262   return msg_global->current_process;
263 }
264
265 /** \ingroup m_process_management
266  * \brief Suspend the process.
267  *
268  * This functions suspend the process by suspending the task on which
269  * it was waiting for the completion.
270  */
271 MSG_error_t MSG_process_suspend(m_process_t process)
272 {
273   simdata_process_t simdata = NULL;
274   simdata_task_t simdata_task = NULL;
275   int i;
276
277   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
278
279   if(process!=MSG_process_self()) {
280     simdata = process->simdata;
281     
282     xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !");
283
284     simdata_task = simdata->waiting_task->simdata;
285
286     simdata->suspended = 1;
287     if(simdata->blocked) return MSG_OK;
288
289     xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&&
290                 !((simdata_task->compute)&&(simdata_task->comm)),
291                 "Got a problem in deciding which action to choose !");
292     simdata->suspended = 1;
293     if(simdata_task->compute) 
294       surf_workstation_resource->common_public->suspend(simdata_task->compute);
295     else
296       surf_workstation_resource->common_public->suspend(simdata_task->comm);
297   } else {
298     m_task_t dummy = MSG_TASK_UNINITIALIZED;
299     dummy = MSG_task_create("suspended", 0.0, 0, NULL);
300
301     simdata = process->simdata;
302     simdata->suspended = 1;
303     __MSG_task_execute(process,dummy);
304     surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
305     __MSG_wait_for_computation(process,dummy);
306     simdata->suspended = 0;
307
308     MSG_task_destroy(dummy);
309   }
310   return MSG_OK;
311 }
312
313 /** \ingroup m_process_management
314  * \brief Resume a suspended process.
315  *
316  * This functions resume a suspended process by resuming the task on
317  * which it was waiting for the completion.
318  */
319 MSG_error_t MSG_process_resume(m_process_t process)
320 {
321   simdata_process_t simdata = NULL;
322   simdata_task_t simdata_task = NULL;
323   int i;
324
325   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
326   CHECK_HOST();
327
328   simdata = process->simdata;
329
330   if(simdata->blocked) {
331     simdata->suspended = 0; /* He'll wake up by itself */
332     MSG_RETURN(MSG_OK);
333   }
334
335   if(!(simdata->waiting_task)) {
336     xbt_assert0(0,"Process not waiting for anything else. Weird !");
337     return MSG_WARNING;
338   }
339   simdata_task = simdata->waiting_task->simdata;
340
341
342   if(simdata_task->compute) 
343     surf_workstation_resource->common_public->resume(simdata_task->compute);
344   else 
345     surf_workstation_resource->common_public->resume(simdata_task->comm);
346
347   MSG_RETURN(MSG_OK);
348 }
349
350 /** \ingroup m_process_management
351  * \brief Returns true if the process is suspended .
352  *
353  * This checks whether a process is suspended or not by inspecting the
354  * task on which it was waiting for the completion.
355  */
356 int MSG_process_isSuspended(m_process_t process)
357 {
358   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
359
360   return (process->simdata->suspended);
361 }
362
363
364
365
366
367 MSG_error_t __MSG_process_block(void)
368 {
369   m_process_t process = MSG_process_self();
370
371   m_task_t dummy = MSG_TASK_UNINITIALIZED;
372   dummy = MSG_task_create("blocked", 0.0, 0, NULL);
373   
374   process->simdata->blocked=1;
375   __MSG_task_execute(process,dummy);
376   surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
377   __MSG_wait_for_computation(process,dummy);
378   process->simdata->blocked=0;
379
380   if(process->simdata->suspended)
381     MSG_process_suspend(process);
382   
383   MSG_task_destroy(dummy);
384
385   return MSG_OK;
386 }
387
388 MSG_error_t __MSG_process_unblock(m_process_t process)
389 {
390   simdata_process_t simdata = NULL;
391   simdata_task_t simdata_task = NULL;
392   int i;
393
394   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
395   CHECK_HOST();
396
397   simdata = process->simdata;
398   if(!(simdata->waiting_task)) {
399     xbt_assert0(0,"Process not waiting for anything else. Weird !");
400     return MSG_WARNING;
401   }
402   simdata_task = simdata->waiting_task->simdata;
403
404   xbt_assert0(simdata->blocked,"Process not blocked");
405
406   surf_workstation_resource->common_public->resume(simdata_task->compute);
407
408   MSG_RETURN(MSG_OK);
409 }
410
411 int __MSG_process_isBlocked(m_process_t process)
412 {
413   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
414
415   return (process->simdata->blocked);
416 }