Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Reverting Mt's modifications. There is a problem in MSG_process_kill. I need to ensur...
[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 /** \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  *  We need to simulate many independent scheduling decisions, so
19  *  the concept of <em>process</em> is at the heart of the
20  *  simulator. A process may be defined as a <em>code</em>, with
21  *  some <em>private data</em>, executing in a <em>location</em>.
22  *  \see m_process_t
23  */
24
25 /******************************** Process ************************************/
26 /** \ingroup m_process_management
27  * \brief Creates and runs a new #m_process_t.
28  *
29  * Does exactly the same as #MSG_process_create_with_arguments but without 
30    providing standard arguments (\a argc, \a argv, \a start_time, \a kill_time).
31  * \sa MSG_process_create_with_arguments
32  */
33 m_process_t MSG_process_create(const char *name,
34                                m_process_code_t code, void *data,
35                                m_host_t host)
36 {
37   return MSG_process_create_with_arguments(name, code, data, host, -1, NULL);
38 }
39
40 static void MSG_process_cleanup(void *arg)
41 {
42
43   while(((m_process_t)arg)->simdata->paje_state) {
44     PAJE_PROCESS_POP_STATE((m_process_t)arg);
45   }
46
47   PAJE_PROCESS_FREE(arg);
48
49   xbt_fifo_remove(msg_global->process_list, arg);
50   xbt_fifo_remove(msg_global->process_to_run, arg);
51   xbt_fifo_remove(((m_process_t) arg)->simdata->host->simdata->process_list, arg);
52   free(((m_process_t) arg)->name);
53   free(((m_process_t) arg)->simdata);
54   free(arg);
55 }
56
57 /** \ingroup m_process_management
58  * \brief Creates and runs a new #m_process_t.
59
60  * A constructor for #m_process_t taking four arguments and returning the 
61  * corresponding object. The structure (and the corresponding thread) is
62  * created, and put in the list of ready process.
63  * \param name a name for the object. It is for user-level information
64    and can be NULL.
65  * \param code is a function describing the behavior of the agent. It
66    should then only use functions described in \ref
67    m_process_management (to create a new #m_process_t for example),
68    in \ref m_host_management (only the read-only functions i.e. whose
69    name contains the word get), in \ref m_task_management (to create
70    or destroy some #m_task_t for example) and in \ref
71    msg_gos_functions (to handle file transfers and task processing).
72  * \param data a pointer to any data may want to attach to the new
73    object.  It is for user-level information and can be NULL. It can
74    be retrieved with the function \ref MSG_process_get_data.
75  * \param host the location where the new agent is executed.
76  * \param argc first argument passed to \a code
77  * \param argv second argument passed to \a code
78  * \see m_process_t
79  * \return The new corresponding object.
80  */
81 m_process_t MSG_process_create_with_arguments(const char *name,
82                                               m_process_code_t code, void *data,
83                                               m_host_t host, int argc, char **argv)
84 {
85   simdata_process_t simdata = xbt_new0(s_simdata_process_t,1);
86   m_process_t process = xbt_new0(s_m_process_t,1);
87   m_process_t self = NULL;
88
89   xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
90   /* Simulator Data */
91
92   simdata->PID = msg_global->PID++;
93   simdata->host = host;
94   simdata->waiting_task = NULL;
95   simdata->argc = argc;
96   simdata->argv = argv;
97   simdata->context = xbt_context_new(code, NULL, NULL, 
98                                      MSG_process_cleanup, process, 
99                                      simdata->argc, simdata->argv);
100
101   if((self=msg_global->current_process)) {
102     simdata->PPID = MSG_process_get_PID(self);
103   } else {
104     simdata->PPID = -1;
105   }
106   simdata->last_errno=MSG_OK;
107
108
109   /* Process structure */
110   process->name = xbt_strdup(name);
111   process->simdata = simdata;
112   process->data = data;
113
114   xbt_fifo_push(host->simdata->process_list, process);
115
116   /* /////////////// FIX du current_process !!! ////////////// */
117   self = msg_global->current_process;
118   xbt_context_start(process->simdata->context);
119   msg_global->current_process = self;
120
121   xbt_fifo_push(msg_global->process_list, process);
122   xbt_fifo_push(msg_global->process_to_run, process);
123
124   PAJE_PROCESS_NEW(process);
125
126   return process;
127 }
128
129 /** \ingroup m_process_management
130  * \param process poor victim
131  *
132  * This function simply kills a \a process... scarry isn't it ? :)
133  */
134 void MSG_process_kill(m_process_t process)
135 {
136   int i;
137   simdata_process_t p_simdata = process->simdata;
138   simdata_host_t h_simdata= p_simdata->host->simdata;
139
140 /*   fprintf(stderr,"Killing %s(%d) on %s.\n",process->name, */
141 /*        p_simdata->PID,p_simdata->host->name); */
142   
143   for (i=0; i<msg_global->max_channel; i++) {
144     if (h_simdata->sleeping[i] == process) {
145       h_simdata->sleeping[i] = NULL;
146       break;
147     }
148   }
149   if (i==msg_global->max_channel) {
150     if(p_simdata->waiting_task) {
151       if(p_simdata->waiting_task->simdata->compute)
152         surf_workstation_resource->common_public->
153           action_free(p_simdata->waiting_task->simdata->compute);
154       else if (p_simdata->waiting_task->simdata->comm)
155         surf_workstation_resource->common_public->
156           action_change_state(p_simdata->waiting_task->simdata->comm,SURF_ACTION_FAILED);
157       else
158         CRITICAL0("UNKNOWN STATUS. Please report this bug.");
159     } else { /* Must be trying to put a task somewhere */
160       if(process==MSG_process_self()) {
161         return;
162       } else {
163         CRITICAL0("UNKNOWN STATUS. Please report this bug.");
164       }
165     }
166   }
167
168   xbt_fifo_remove(msg_global->process_to_run,process);
169   xbt_fifo_remove(msg_global->process_list,process);
170   xbt_context_free(process->simdata->context);
171 }
172
173 /** \ingroup m_process_management
174  * \brief Migrates an agent to another location.
175  *
176  * This functions checks whether \a process and \a host are valid pointers
177    and change the value of the #m_host_t on which \a process is running.
178  */
179 MSG_error_t MSG_process_change_host(m_process_t process, m_host_t host)
180 {
181   simdata_process_t simdata = NULL;
182
183   /* Sanity check */
184
185   xbt_assert0(((process) && (process->simdata)
186           && (host)), "Invalid parameters");
187   simdata = process->simdata;
188
189   xbt_fifo_remove(simdata->host->simdata->process_list,process);
190   simdata->host = host;
191   xbt_fifo_push(host->simdata->process_list,process);
192
193   return MSG_OK;
194 }
195
196 /** \ingroup m_process_management
197  * \brief Return the user data of a #m_process_t.
198  *
199  * This functions checks whether \a process is a valid pointer or not 
200    and return the user data associated to \a process if it is possible.
201  */
202 void *MSG_process_get_data(m_process_t process)
203 {
204   xbt_assert0((process != NULL), "Invalid parameters");
205
206   return (process->data);
207 }
208
209 /** \ingroup m_process_management
210  * \brief Set the user data of a #m_process_t.
211  *
212  * This functions checks whether \a process is a valid pointer or not 
213    and set the user data associated to \a process if it is possible.
214  */
215 MSG_error_t MSG_process_set_data(m_process_t process,void *data)
216 {
217   xbt_assert0((process != NULL), "Invalid parameters");
218   xbt_assert0((process->data == NULL), "Data already set");
219   
220   process->data = data;
221    
222   return MSG_OK;
223 }
224
225 /** \ingroup m_process_management
226  * \brief Return the location on which an agent is running.
227  *
228  * This functions checks whether \a process is a valid pointer or not 
229    and return the m_host_t corresponding to the location on which \a 
230    process is running.
231  */
232 m_host_t MSG_process_get_host(m_process_t process)
233 {
234   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
235
236   return (((simdata_process_t) process->simdata)->host);
237 }
238
239 /** \ingroup m_process_management
240  *
241  * \brief Return a #m_process_t given its PID.
242  *
243  * This functions search in the list of all the created m_process_t for a m_process_t 
244    whose PID is equal to \a PID. If no host is found, \c NULL is returned. 
245    Note that the PID are uniq in the whole simulation, not only on a given host.
246  */
247 m_process_t MSG_process_from_PID(int PID)
248 {
249   xbt_fifo_item_t i = NULL;
250   m_process_t process = NULL;
251
252   xbt_fifo_foreach(msg_global->process_list,i,process,m_process_t) {
253     if(MSG_process_get_PID(process) == PID) return process;
254   }
255   return NULL;
256 }
257
258 /** \ingroup m_process_management
259  * \brief Returns the process ID of \a process.
260  *
261  * This functions checks whether \a process is a valid pointer or not 
262    and return its PID.
263  */
264 int MSG_process_get_PID(m_process_t process)
265 {
266   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
267
268   return (((simdata_process_t) process->simdata)->PID);
269 }
270
271 /** \ingroup m_process_management
272  * \brief Returns the process ID of the parent of \a process.
273  *
274  * This functions checks whether \a process is a valid pointer or not 
275    and return its PID. Returns -1 if the agent has not been created by 
276    another agent.
277  */
278 int MSG_process_get_PPID(m_process_t process)
279 {
280   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
281
282   return (((simdata_process_t) process->simdata)->PPID);
283 }
284
285 /** \ingroup m_process_management
286  * \brief Return the name of an agent.
287  *
288  * This functions checks whether \a process is a valid pointer or not 
289    and return its name.
290  */
291 const char *MSG_process_get_name(m_process_t process)
292 {
293   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
294
295   return (process->name);
296 }
297
298 /** \ingroup m_process_management
299  * \brief Return the PID of the current agent.
300  *
301  * This functions returns the PID of the currently running #m_process_t.
302  */
303 int MSG_process_self_PID(void)
304 {
305   return (MSG_process_get_PID(MSG_process_self()));
306 }
307
308 /** \ingroup m_process_management
309  * \brief Return the PPID of the current agent.
310  *
311  * This functions returns the PID of the parent of the currently
312  * running #m_process_t.
313  */
314 int MSG_process_self_PPID(void)
315 {
316   return (MSG_process_get_PPID(MSG_process_self()));
317 }
318
319 /** \ingroup m_process_management
320  * \brief Return the current agent.
321  *
322  * This functions returns the currently running #m_process_t.
323  */
324 m_process_t MSG_process_self(void)
325 {
326   return msg_global ? msg_global->current_process : NULL;
327 }
328
329 /** \ingroup m_process_management
330  * \brief Suspend the process.
331  *
332  * This functions suspend the process by suspending the task on which
333  * it was waiting for the completion.
334  */
335 MSG_error_t MSG_process_suspend(m_process_t process)
336 {
337   simdata_process_t simdata = NULL;
338   simdata_task_t simdata_task = NULL;
339   int i;
340
341   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
342
343   PAJE_PROCESS_PUSH_STATE(process,"S");
344
345   if(process!=MSG_process_self()) {
346     simdata = process->simdata;
347     
348     xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !");
349
350     simdata_task = simdata->waiting_task->simdata;
351
352     simdata->suspended = 1;
353     if(simdata->blocked) return MSG_OK;
354
355     xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&&
356                 !((simdata_task->compute)&&(simdata_task->comm)),
357                 "Got a problem in deciding which action to choose !");
358     simdata->suspended = 1;
359     if(simdata_task->compute) 
360       surf_workstation_resource->common_public->suspend(simdata_task->compute);
361     else
362       surf_workstation_resource->common_public->suspend(simdata_task->comm);
363   } else {
364     m_task_t dummy = MSG_TASK_UNINITIALIZED;
365     dummy = MSG_task_create("suspended", 0.0, 0, NULL);
366
367     simdata = process->simdata;
368     simdata->suspended = 1;
369     __MSG_task_execute(process,dummy);
370     surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
371     __MSG_wait_for_computation(process,dummy);
372     simdata->suspended = 0;
373
374     MSG_task_destroy(dummy);
375   }
376   return MSG_OK;
377 }
378
379 /** \ingroup m_process_management
380  * \brief Resume a suspended process.
381  *
382  * This functions resume a suspended process by resuming the task on
383  * which it was waiting for the completion.
384  */
385 MSG_error_t MSG_process_resume(m_process_t process)
386 {
387   simdata_process_t simdata = NULL;
388   simdata_task_t simdata_task = NULL;
389   int i;
390
391   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
392   CHECK_HOST();
393
394   simdata = process->simdata;
395
396
397   if(simdata->blocked) {
398     PAJE_PROCESS_POP_STATE(process);
399
400     simdata->suspended = 0; /* He'll wake up by itself */
401     MSG_RETURN(MSG_OK);
402   }
403
404   if(!(simdata->waiting_task)) {
405     xbt_assert0(0,"Process not waiting for anything else. Weird !");
406     return MSG_WARNING;
407   }
408   simdata_task = simdata->waiting_task->simdata;
409
410
411   if(simdata_task->compute) {
412     surf_workstation_resource->common_public->resume(simdata_task->compute);
413     PAJE_PROCESS_POP_STATE(process);
414   }
415   else {
416     PAJE_PROCESS_POP_STATE(process);
417     surf_workstation_resource->common_public->resume(simdata_task->comm);
418   }
419
420   MSG_RETURN(MSG_OK);
421 }
422
423 /** \ingroup m_process_management
424  * \brief Returns true if the process is suspended .
425  *
426  * This checks whether a process is suspended or not by inspecting the
427  * task on which it was waiting for the completion.
428  */
429 int MSG_process_isSuspended(m_process_t process)
430 {
431   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
432
433   return (process->simdata->suspended);
434 }
435
436 MSG_error_t __MSG_process_block(void)
437 {
438   m_process_t process = MSG_process_self();
439
440   m_task_t dummy = MSG_TASK_UNINITIALIZED;
441   dummy = MSG_task_create("blocked", 0.0, 0, NULL);
442   
443   PAJE_PROCESS_PUSH_STATE(process,"B");
444
445   process->simdata->blocked=1;
446   __MSG_task_execute(process,dummy);
447   surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
448   __MSG_wait_for_computation(process,dummy);
449   process->simdata->blocked=0;
450
451   if(process->simdata->suspended)
452     MSG_process_suspend(process);
453   
454   MSG_task_destroy(dummy);
455
456   return MSG_OK;
457 }
458
459 MSG_error_t __MSG_process_unblock(m_process_t process)
460 {
461   simdata_process_t simdata = NULL;
462   simdata_task_t simdata_task = NULL;
463   int i;
464
465   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
466   CHECK_HOST();
467
468   simdata = process->simdata;
469   if(!(simdata->waiting_task)) {
470     xbt_assert0(0,"Process not waiting for anything else. Weird !");
471     return MSG_WARNING;
472   }
473   simdata_task = simdata->waiting_task->simdata;
474
475   xbt_assert0(simdata->blocked,"Process not blocked");
476
477   surf_workstation_resource->common_public->resume(simdata_task->compute);
478
479   PAJE_PROCESS_POP_STATE(process);
480
481   MSG_RETURN(MSG_OK);
482 }
483
484 int __MSG_process_isBlocked(m_process_t process)
485 {
486   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
487
488   return (process->simdata->blocked);
489 }