Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Simix Initial structure
[simgrid.git] / src / simix / smx_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/log.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
12                                 "Logging specific to SIMIX (process)");
13 /** \defgroup m_process_management Management Functions of Agents
14  *  \brief This section describes the agent structure of MSG
15  *  (#m_process_t) and the functions for managing it.
16  *    \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Agents" --> \endhtmlonly
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 smx_process_t SIMIX_process_create(const char *name,
34                                smx_process_code_t code, void *data,
35                                smx_host_t host)
36 {
37   return SIMIX_process_create_with_arguments(name, code, data, host, -1, NULL);
38 }
39
40 static void SIMIX_process_cleanup(void *arg)
41 {
42   xbt_swag_remove(arg, simix_global->process_list);
43   xbt_swag_remove(arg, simix_global->process_to_run);
44   xbt_swag_remove(arg, ((smx_process_t) arg)->simdata->host->simdata->process_list);
45   free(((smx_process_t) arg)->name);
46   ((smx_process_t) arg)->name = NULL;
47   free(((smx_process_t) arg)->simdata);
48   ((smx_process_t) arg)->simdata = NULL;
49   free(arg);
50 }
51
52 /** \ingroup m_process_management
53  * \brief Creates and runs a new #m_process_t.
54
55  * A constructor for #m_process_t taking four arguments and returning the 
56  * corresponding object. The structure (and the corresponding thread) is
57  * created, and put in the list of ready process.
58  * \param name a name for the object. It is for user-level information
59    and can be NULL.
60  * \param code is a function describing the behavior of the agent. It
61    should then only use functions described in \ref
62    m_process_management (to create a new #m_process_t for example),
63    in \ref m_host_management (only the read-only functions i.e. whose
64    name contains the word get), in \ref m_task_management (to create
65    or destroy some #m_task_t for example) and in \ref
66    msg_gos_functions (to handle file transfers and task processing).
67  * \param data a pointer to any data one may want to attach to the new
68    object.  It is for user-level information and can be NULL. It can
69    be retrieved with the function \ref MSG_process_get_data.
70  * \param host the location where the new agent is executed.
71  * \param argc first argument passed to \a code
72  * \param argv second argument passed to \a code
73  * \see m_process_t
74  * \return The new corresponding object.
75  */
76 smx_process_t SIMIX_process_create_with_arguments(const char *name,
77                                               smx_process_code_t code, void *data,
78                                               smx_host_t host, int argc, char **argv)
79 {
80   simdata_process_t simdata = xbt_new0(s_simdata_process_t,1);
81   smx_process_t process = xbt_new0(s_smx_process_t,1);
82   smx_process_t self = NULL;
83
84   xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
85   /* Simulator Data */
86
87   simdata->host = host;
88   simdata->argc = argc;
89   simdata->argv = argv;
90   simdata->context = xbt_context_new(code, NULL, NULL, 
91                                      SIMIX_process_cleanup, process, 
92                                      simdata->argc, simdata->argv);
93
94   if((self=simix_global->current_process)) {
95     //simdata->PPID = MSG_process_get_PID(self);
96   } else {
97    // simdata->PPID = -1;
98   }
99   simdata->last_errno=SIMIX_OK;
100
101
102   /* Process structure */
103   process->name = xbt_strdup(name);
104   process->simdata = simdata;
105   process->data = data;
106
107   xbt_swag_insert_at_head(process, host->simdata->process_list);
108
109   /* *************** FIX du current_process !!! *************** */
110   self = simix_global->current_process;
111   xbt_context_start(process->simdata->context);
112   simix_global->current_process = self;
113
114   xbt_swag_insert_at_head(process,simix_global->process_list);
115   DEBUG2("Inserting %s(%s) in the to_run list",process->name,
116          host->name);
117   xbt_swag_insert_at_head(process,simix_global->process_to_run);
118
119   return process;
120 }
121
122 /** \ingroup m_process_management
123  * \param process poor victim
124  *
125  * This function simply kills a \a process... scarry isn't it ? :)
126  */
127 void SIMIX_process_kill(smx_process_t process)
128 {
129   //int i;
130   simdata_process_t p_simdata = process->simdata;
131   //simdata_host_t h_simdata= p_simdata->host->simdata;
132   //int _cursor;
133   //smx_process_t proc = NULL;
134
135   DEBUG2("Killing %s on %s",process->name, p_simdata->host->name);
136   
137   /*
138   
139   if(p_simdata->waiting_task) {
140     xbt_dynar_foreach(p_simdata->waiting_task->simdata->sleeping,_cursor,proc) {
141       if(proc==process) 
142         xbt_dynar_remove_at(p_simdata->waiting_task->simdata->sleeping,_cursor,&proc);
143     }
144     if(p_simdata->waiting_task->simdata->compute)
145       surf_workstation_resource->common_public->
146         action_free(p_simdata->waiting_task->simdata->compute);
147     else if (p_simdata->waiting_task->simdata->comm) {
148       surf_workstation_resource->common_public->
149         action_change_state(p_simdata->waiting_task->simdata->comm,SURF_ACTION_FAILED);
150       surf_workstation_resource->common_public->
151         action_free(p_simdata->waiting_task->simdata->comm);
152     } else {
153       xbt_die("UNKNOWN STATUS. Please report this bug.");
154     }
155   }
156
157   if ((i==msg_global->max_channel) && (process!=MSG_process_self()) && 
158       (!p_simdata->waiting_task)) {
159     xbt_die("UNKNOWN STATUS. Please report this bug.");
160   }
161 */
162   xbt_swag_remove(process,simix_global->process_to_run);
163   xbt_swag_remove(process,simix_global->process_list);
164   xbt_context_free(process->simdata->context);
165
166   if(process==SIMIX_process_self()) {
167     /* I just killed myself */
168     xbt_context_yield();
169   }
170 }
171
172 /** \ingroup m_process_management
173  * \brief Migrates an agent to another location.
174  *
175  * This functions checks whether \a process and \a host are valid pointers
176    and change the value of the #m_host_t on which \a process is running.
177  */
178 SIMIX_error_t SIMIX_process_change_host(smx_process_t process, smx_host_t host)
179 {
180   simdata_process_t simdata = NULL;
181
182   /* Sanity check */
183
184   xbt_assert0(((process) && (process->simdata)
185           && (host)), "Invalid parameters");
186   simdata = process->simdata;
187
188   xbt_swag_remove(process,simdata->host->simdata->process_list);
189   simdata->host = host;
190   xbt_swag_insert_at_head(process,host->simdata->process_list);
191
192   return SIMIX_OK;
193 }
194
195 /** \ingroup m_process_management
196  * \brief Return the user data of a #m_process_t.
197  *
198  * This functions checks whether \a process is a valid pointer or not 
199    and return the user data associated to \a process if it is possible.
200  */
201 void *SIMIX_process_get_data(smx_process_t process)
202 {
203   xbt_assert0((process != NULL), "Invalid parameters");
204
205   return (process->data);
206 }
207
208 /** \ingroup m_process_management
209  * \brief Set the user data of a #m_process_t.
210  *
211  * This functions checks whether \a process is a valid pointer or not 
212    and set the user data associated to \a process if it is possible.
213  */
214 SIMIX_error_t SIMIX_process_set_data(smx_process_t process,void *data)
215 {
216   xbt_assert0((process != NULL), "Invalid parameters");
217   xbt_assert0((process->data == NULL), "Data already set");
218   
219   process->data = data;
220    
221   return SIMIX_OK;
222 }
223
224 /** \ingroup m_process_management
225  * \brief Return the location on which an agent is running.
226  *
227  * This functions checks whether \a process is a valid pointer or not 
228    and return the m_host_t corresponding to the location on which \a 
229    process is running.
230  */
231 smx_host_t SIMIX_process_get_host(smx_process_t process)
232 {
233   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
234
235   return (((simdata_process_t) process->simdata)->host);
236 }
237
238 /** \ingroup m_process_management
239  *
240  * \brief Return a #m_process_t given its PID.
241  *
242  * This functions search in the list of all the created m_process_t for a m_process_t 
243    whose PID is equal to \a PID. If no host is found, \c NULL is returned. 
244    Note that the PID are uniq in the whole simulation, not only on a given host.
245  */
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
259 /** \ingroup m_process_management
260  * \brief Returns the process ID of \a process.
261  *
262  * This functions checks whether \a process is a valid pointer or not 
263    and return its PID.
264  */
265 /*
266 int MSG_process_get_PID(m_process_t process)
267 {
268   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
269
270   return (((simdata_process_t) process->simdata)->PID);
271 }
272 */
273 /** \ingroup m_process_management
274  * \brief Returns the process ID of the parent of \a process.
275  *
276  * This functions checks whether \a process is a valid pointer or not 
277    and return its PID. Returns -1 if the agent has not been created by 
278    another agent.
279  */
280 /*
281 int MSG_process_get_PPID(m_process_t process)
282 {
283   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
284
285   return (((simdata_process_t) process->simdata)->PPID);
286 }
287 */
288 /** \ingroup m_process_management
289  * \brief Return the name of an agent.
290  *
291  * This functions checks whether \a process is a valid pointer or not 
292    and return its name.
293  */
294 const char *SIMIX_process_get_name(smx_process_t process)
295 {
296   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
297
298   return (process->name);
299 }
300
301 /** \ingroup m_process_management
302  * \brief Return the PID of the current agent.
303  *
304  * This functions returns the PID of the currently running #m_process_t.
305  */
306 /*
307 int MSG_process_self_PID(void)
308 {
309   return (MSG_process_get_PID(MSG_process_self()));
310 }
311 */
312 /** \ingroup m_process_management
313  * \brief Return the PPID of the current agent.
314  *
315  * This functions returns the PID of the parent of the currently
316  * running #m_process_t.
317  */
318 /*
319 int MSG_process_self_PPID(void)
320 {
321   return (MSG_process_get_PPID(MSG_process_self()));
322 }
323 */
324 /** \ingroup m_process_management
325  * \brief Return the current agent.
326  *
327  * This functions returns the currently running #m_process_t.
328  */
329 smx_process_t SIMIX_process_self(void)
330 {
331   return simix_global ? simix_global->current_process : NULL;
332 }
333
334 /** \ingroup m_process_management
335  * \brief Suspend the process.
336  *
337  * This functions suspend the process by suspending the task on which
338  * it was waiting for the completion.
339  */
340 SIMIX_error_t SIMIX_process_suspend(smx_process_t process)
341 {
342 /*
343   simdata_process_t simdata = NULL;
344   simdata_task_t simdata_task = NULL;
345
346   XBT_IN2("(%p(%s))", process, process->name);
347
348   xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
349
350   PAJE_PROCESS_PUSH_STATE(process,"S",NULL);
351
352   if(process!=SIMIX_process_self()) {
353     simdata = process->simdata;
354     
355     xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !");
356
357     simdata_task = simdata->waiting_task->simdata;
358
359     simdata->suspended = 1;
360     if(simdata->blocked) {
361       XBT_OUT;
362       return SIMIX_OK;
363     }
364
365     xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&&
366                 !((simdata_task->compute)&&(simdata_task->comm)),
367                 "Got a problem in deciding which action to choose !");
368     simdata->suspended = 1;
369     if(simdata_task->compute) 
370       surf_workstation_resource->common_public->suspend(simdata_task->compute);
371     else
372       surf_workstation_resource->common_public->suspend(simdata_task->comm);
373   } else {
374     m_task_t dummy = MSG_TASK_UNINITIALIZED;
375     dummy = MSG_task_create("suspended", 0.0, 0, NULL);
376
377     simdata = process->simdata;
378     simdata->suspended = 1;
379     __MSG_task_execute(process,dummy);
380     surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
381     __MSG_wait_for_computation(process,dummy);
382     simdata->suspended = 0;
383
384     MSG_task_destroy(dummy);
385   }
386   XBT_OUT;
387   */
388   return SIMIX_OK;
389 }
390
391 /** \ingroup m_process_management
392  * \brief Resume a suspended process.
393  *
394  * This functions resume a suspended process by resuming the task on
395  * which it was waiting for the completion.
396  */
397 SIMIX_error_t SIMIX_process_resume(smx_process_t process)
398 {
399 /*
400   simdata_process_t simdata = NULL;
401   simdata_task_t simdata_task = NULL;
402
403   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
404   CHECK_HOST();
405
406   XBT_IN2("(%p(%s))", process, process->name);
407
408   if(process == SIMIX_process_self()) {
409     XBT_OUT;
410     SIMIX_RETURN(SIMIX_OK);
411   }
412
413   simdata = process->simdata;
414
415   if(simdata->blocked) {
416     PAJE_PROCESS_POP_STATE(process);
417
418     simdata->suspended = 0; *//* He'll wake up by itself */
419     /*XBT_OUT;
420     SIMIX_RETURN(SIMIX_OK);
421   }
422
423   if(!(simdata->waiting_task)) {
424     xbt_assert0(0,"Process not waiting for anything else. Weird !");
425     XBT_OUT;
426     return SIMIX_WARNING;
427   }
428   simdata_task = simdata->waiting_task->simdata;
429
430
431   if(simdata_task->compute) {
432     surf_workstation_resource->common_public->resume(simdata_task->compute);
433     PAJE_PROCESS_POP_STATE(process);
434   }
435   else {
436     PAJE_PROCESS_POP_STATE(process);
437     surf_workstation_resource->common_public->resume(simdata_task->comm);
438   }
439
440   XBT_OUT;
441   */
442   SIMIX_RETURN(SIMIX_OK);
443 }
444
445 /** \ingroup m_process_management
446  * \brief Returns true if the process is suspended .
447  *
448  * This checks whether a process is suspended or not by inspecting the
449  * task on which it was waiting for the completion.
450  */
451 int SIMIX_process_is_suspended(smx_process_t process)
452 {
453   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
454
455   return (process->simdata->suspended);
456 }
457
458 int __SIMIX_process_block(double max_duration, const char *info)
459 {
460 /*
461   smx_process_t process = SIMIX_process_self();
462   m_task_t dummy = SIMIX_TASK_UNINITIALIZED;
463   char blocked_name[512];
464   snprintf(blocked_name,512,"blocked [%s] (%s:%s)",
465           info, process->name, process->simdata->host->name);
466
467   XBT_IN1(": max_duration=%g",max_duration);
468
469   dummy = MSG_task_create(blocked_name, 0.0, 0, NULL);
470   
471   PAJE_PROCESS_PUSH_STATE(process,"B",NULL);
472
473   process->simdata->blocked=1;
474   __MSG_task_execute(process,dummy);
475   surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
476   if(max_duration>=0)
477     surf_workstation_resource->common_public->set_max_duration(dummy->simdata->compute, 
478                                                                max_duration);
479   __MSG_wait_for_computation(process,dummy);
480   MSG_task_destroy(dummy);
481   process->simdata->blocked=0;
482
483   if(process->simdata->suspended) {
484     DEBUG0("I've been suspended in the meantime");    
485     SIMIX_process_suspend(process);
486     DEBUG0("I've been resumed, let's keep going");    
487   }
488
489   PAJE_PROCESS_POP_STATE(process);
490
491   XBT_OUT;
492   */
493   return 1;
494 }
495
496 SIMIX_error_t __SIMIX_process_unblock(smx_process_t process)
497 {
498 /*
499   simdata_process_t simdata = NULL;
500   simdata_task_t simdata_task = NULL;
501
502   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
503   CHECK_HOST();
504
505   XBT_IN2(": %s unblocking %s", SIMIX_process_self()->name,process->name);
506
507   simdata = process->simdata;
508   if(!(simdata->waiting_task)) {
509     xbt_assert0(0,"Process not waiting for anything else. Weird !");
510     XBT_OUT;
511     return SIMIX_WARNING;
512   }
513   simdata_task = simdata->waiting_task->simdata;
514
515   xbt_assert0(simdata->blocked,"Process not blocked");
516
517   surf_workstation_resource->common_public->resume(simdata_task->compute);
518
519   XBT_OUT;
520 */
521   SIMIX_RETURN(SIMIX_OK);
522 }
523
524 int __SIMIX_process_isBlocked(smx_process_t process)
525 {
526   xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
527
528   return (process->simdata->blocked);
529 }