Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Adding more verbose informations to Paje
[simgrid.git] / src / msg / global.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(global, msg,
12                                 "Logging specific to MSG (global)");
13
14 int __stop_at_time = -1.0 ;
15
16 MSG_Global_t msg_global = NULL;
17
18 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList); */
19 /* static xbt_fifo_t MSG_buildFailedHostList(double a, double b); */
20
21 /** \defgroup msg_simulation   MSG simulation Functions
22  *  \brief This section describes the functions you need to know to
23  *  set up a simulation. You should have a look at \ref MSG_examples 
24  *  to have an overview of their usage.
25  *    \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Simulation functions" --> \endhtmlonly
26  */
27
28 /********************************* MSG **************************************/
29
30 /** \ingroup msg_simulation
31  * \brief Initialize some MSG internal data.
32  */
33 void MSG_global_init_args(int *argc, char **argv)
34 {
35   MSG_global_init(argc,argv);
36 }
37
38 /** \ingroup msg_simulation
39  * \brief Initialize some MSG internal data.
40  */
41 void MSG_global_init(int *argc, char **argv)
42 {
43   if (!msg_global) {
44     surf_init(argc, argv);      /* Initialize some common structures. Warning, it sets msg_global=NULL */
45      
46     msg_global = xbt_new0(s_MSG_Global_t,1);
47
48     xbt_context_init();
49     msg_global->host = xbt_fifo_new();
50     msg_global->process_to_run = xbt_fifo_new();
51     msg_global->process_list = xbt_fifo_new();
52     msg_global->max_channel = 0;
53     msg_global->current_process = NULL;
54     msg_global->registered_functions = xbt_dict_new();
55     msg_global->PID = 1;
56   }
57 }
58
59 /** \ingroup msg_easier_life
60  * \brief Traces MSG events in the Paje format.
61  */
62 void MSG_paje_output(const char *filename)
63 {
64   int i;
65   const char *paje_preembule="%EventDef SetLimits       0\n"
66     "%  StartTime       date\n"
67     "%  EndTime date\n"
68     "%EndEventDef\n"
69     "%EventDef  PajeDefineContainerType 1\n"
70     "%  NewType string\n"
71     "%  ContainerType   string\n"
72     "%  NewName string\n"
73     "%EndEventDef\n"
74     "%EventDef  PajeDefineEventType     2\n"
75     "%  NewType string\n"
76     "%  ContainerType   string\n"
77     "%  NewName string\n"
78     "%EndEventDef\n"
79     "%EventDef  PajeDefineStateType     3\n"
80     "%  NewType string\n"
81     "%  ContainerType   string\n"
82     "%  NewName string\n"
83     "%EndEventDef\n"
84     "%EventDef  PajeDefineVariableType  4\n"
85     "%  NewType string\n"
86     "%  ContainerType   string\n"
87     "%  NewName string\n"
88     "%EndEventDef\n"
89     "%EventDef  PajeDefineLinkType      5\n"
90     "%  NewType string\n"
91     "%  ContainerType   string\n"
92     "%  SourceContainerType     string\n"
93     "%  DestContainerType       string\n"
94     "%  NewName string\n"
95     "%EndEventDef\n"
96     "%EventDef  PajeDefineEntityValue   6\n"
97     "%  NewValue        string\n"
98     "%  EntityType      string\n"
99     "%  NewName string\n"
100     "%EndEventDef\n"
101     "%EventDef  PajeCreateContainer     7\n"
102     "%  Time    date\n"
103     "%  NewContainer    string\n"
104     "%  NewContainerType        string\n"
105     "%  Container       string\n"
106     "%  NewName string\n"
107     "%EndEventDef\n"
108     "%EventDef  PajeDestroyContainer    8\n"
109     "%  Time    date\n"
110     "%  Name    string\n"
111     "%  Type    string\n"
112     "%EndEventDef\n"
113     "%EventDef  PajeNewEvent    9\n"
114     "%  Time    date\n"
115     "%  EntityType      string\n"
116     "%  Container       string\n"
117     "%  Value   string\n"
118     "%EndEventDef\n"
119     "%EventDef  PajeSetState    10\n"
120     "%  Time    date\n"
121     "%  EntityType      string\n"
122     "%  Container       string\n"
123     "%  Value   string\n"
124     "%EndEventDef\n"
125     "%EventDef  PajeSetState    101\n"
126     "%  Time    date\n"
127     "%  EntityType      string\n"
128     "%  Container       string\n"
129     "%  Value   string\n"
130     "%  FileName        string\n"
131     "%  LineNumber      int\n"
132     "%EndEventDef\n"
133     "%EventDef  PajePushState   111\n"
134     "%  Time    date\n"
135     "%  EntityType      string\n"
136     "%  Container       string\n"
137     "%  Value   string\n"
138     "%  FileName        string\n"
139     "%  LineNumber      int\n"
140     "%EndEventDef\n"
141     "%EventDef  PajePushState   11\n"
142     "%  Time    date\n"
143     "%  EntityType      string\n"
144     "%  Container       string\n"
145     "%  Value   string\n"
146     "%  TaskName        string\n"
147     "%EndEventDef\n"
148     "%EventDef  PajePopState    12\n"
149     "%  Time    date\n"
150     "%  EntityType      string\n"
151     "%  Container       string\n"
152     "%EndEventDef\n"
153     "%EventDef  PajeSetVariable 13\n"
154     "%  Time    date\n"
155     "%  EntityType      string\n"
156     "%  Container       string\n"
157     "%  Value   double\n"
158     "%EndEventDef\n"
159     "%EventDef  PajeAddVariable 14\n"
160     "%  Time    date\n"
161     "%  EntityType      string\n"
162     "%  Container       string\n"
163     "%  Value   double\n"
164     "%EndEventDef\n"
165     "%EventDef  PajeSubVariable 15\n"
166     "%  Time    date\n"
167     "%  EntityType      string\n"
168     "%  Container       string\n"
169     "%  Value   double\n"
170     "%EndEventDef\n"
171     "%EventDef  PajeStartLink   16\n"
172     "%  Time    date\n"
173     "%  EntityType      string\n"
174     "%  Container       string\n"
175     "%  Value   string\n"
176     "%  SourceContainer string\n"
177     "%  Key     string\n"
178     "%EndEventDef\n"
179     "%EventDef  PajeEndLink     17\n"
180     "%  Time    date\n"
181     "%  EntityType      string\n"
182     "%  Container       string\n"
183     "%  Value   string\n"
184     "%  DestContainer   string\n"
185     "%  Key     string\n"
186     "%EndEventDef\n";
187
188   const char *type_definitions = "1     Sim_t   0       Simulation_t\n"
189     "1  H_t     Sim_t   m_host_t\n"
190     "1  P_t     H_t     m_process_t\n"
191     "3  S_t     P_t     \"Process State\"\n"
192     "6  E       S_t     Executing\n"
193     "6  B       S_t     Blocked\n"
194     "6  C       S_t     Communicating\n"
195     "5  Comm    Sim_t   P_t     P_t     Communication_t\n";
196
197   const char *ext = ".trace";
198   int ext_len = strlen(ext);
199   int len;
200   m_host_t host;
201   m_process_t process;
202   xbt_fifo_item_t item = NULL;
203
204   xbt_assert0(msg_global, "Initialize MSG first\n");
205   xbt_assert0(!msg_global->paje_output, "Paje output already defined\n");
206   xbt_assert0(filename, "Need a real file name\n");
207
208   len = strlen(filename);
209   if((len<ext_len) || (strncmp(filename+len-ext_len,ext,ext_len))) {
210     CRITICAL2("The name of the Paje trace file \"%s\" does not end by \"%s\". Paje will cause difficulties to read it.\n",
211               filename,ext);
212   }
213
214   msg_global->paje_output=fopen(filename,"w");
215   xbt_assert1(msg_global->paje_output, "Failed to open %s \n",filename);
216
217   fprintf(msg_global->paje_output,"%s",paje_preembule);
218   fprintf(msg_global->paje_output,"%s",type_definitions);
219
220   /*    Channels    */
221   for(i=0; i<msg_global->max_channel; i++) {
222     fprintf(msg_global->paje_output, "6 COMM_%d Comm    \"Channel %d\"\n" ,i,i);
223   }
224   fprintf(msg_global->paje_output,
225           "7    0.0     CUR     Sim_t   0       \"MSG simulation\"\n");
226
227   /*    Hosts       */
228   xbt_fifo_foreach(msg_global->host,item,host,m_host_t) {
229     PAJE_HOST_NEW(host);
230   }
231
232   /*    Process       */
233   xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
234     PAJE_PROCESS_NEW(process);
235   }
236 }
237
238 /** \defgroup m_channel_management    Understanding channels
239  *  \brief This section briefly describes the channel notion of MSG
240  *  (#m_channel_t).
241  *    \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Channels" --> \endhtmlonly
242  * 
243  *
244  *  For convenience, the simulator provides the notion of channel
245  *  that is close to the tag notion in MPI. A channel is not a
246  *  socket. It doesn't need to be opened neither closed. It rather
247  *  corresponds to the ports opened on the different machines.
248  */
249
250
251 /** \ingroup m_channel_management
252  * \brief Set the number of channel in the simulation.
253  *
254  * This function has to be called to fix the number of channel in the
255    simulation before creating any host. Indeed, each channel is
256    represented by a different mailbox on each #m_host_t. This
257    function can then be called only once. This function takes only one
258    parameter.
259  * \param number the number of channel in the simulation. It has to be >0
260  */
261 MSG_error_t MSG_set_channel_number(int number)
262 {
263   xbt_assert0((msg_global) && (msg_global->max_channel == 0), "Channel number already set!");
264
265   msg_global->max_channel = number;
266
267   return MSG_OK;
268 }
269
270 /** \ingroup m_channel_management
271  * \brief Return the number of channel in the simulation.
272  *
273  * This function has to be called once the number of channel is fixed. I can't 
274    figure out a reason why anyone would like to call this function but nevermind.
275  * \return the number of channel in the simulation.
276  */
277 int MSG_get_channel_number(void)
278 {
279   xbt_assert0((msg_global)&&(msg_global->max_channel != 0), "Channel number not set yet!");
280
281   return msg_global->max_channel;
282 }
283
284 /** \ingroup msg_simulation
285  * \brief Launch the MSG simulation
286  */
287 MSG_error_t MSG_main(void)
288 {
289   m_process_t process = NULL;
290   int nbprocess,i;
291   double elapsed_time = 0.0;
292   int state_modifications = 1;
293   /* Clean IO before the run */
294   fflush(stdout);
295   fflush(stderr);
296
297   surf_solve(); /* Takes traces into account. Returns 0.0 */
298 /* xbt_fifo_size(msg_global->process_to_run) */
299   while (1) {
300     xbt_context_empty_trash();
301     if(xbt_fifo_size(msg_global->process_to_run) && (elapsed_time>0)) {
302       DEBUG0("**************************************************");
303     }
304     if((__stop_at_time>0) && (MSG_get_clock() >= __stop_at_time)) {
305       DEBUG0("Let's stop here!");
306     }
307
308     while ((process = xbt_fifo_pop(msg_global->process_to_run))) {
309       DEBUG3("Scheduling %s(%d) on %s",      
310              process->name,process->simdata->PID,
311              process->simdata->host->name);
312       msg_global->current_process = process;
313 /*       fflush(NULL); */
314       xbt_context_schedule(process->simdata->context);
315       msg_global->current_process = NULL;
316     }
317     
318     {
319       surf_action_t action = NULL;
320       surf_resource_t resource = NULL;
321       m_task_t task = NULL;
322
323       void *fun = NULL;
324       void *arg = NULL;
325
326       xbt_dynar_foreach(resource_list, i, resource) {
327         if(xbt_swag_size(resource->common_public->states.failed_action_set) ||
328            xbt_swag_size(resource->common_public->states.done_action_set))
329           state_modifications = 1;
330       }
331       
332       if(!state_modifications) {
333         DEBUG1("%g : Calling surf_solve",MSG_get_clock());
334         elapsed_time = surf_solve();
335         DEBUG1("Elapsed_time %g",elapsed_time);
336         
337         if (elapsed_time<0.0) {
338           /*       fprintf(stderr, "We're done %g\n",elapsed_time); */
339           break;
340         }
341       }
342
343       while (surf_timer_resource->extension_public->get(&fun,(void*)&arg)) {
344         DEBUG2("got %p %p", fun, arg);
345         if(fun==MSG_process_create_with_arguments) {
346           process_arg_t args = arg;
347           DEBUG2("Launching %s on %s", args->name, args->host->name);
348           process = MSG_process_create_with_arguments(args->name, args->code, 
349                                                       args->data, args->host,
350                                                       args->argc,args->argv);
351           if(args->kill_time > MSG_get_clock()) {
352             surf_timer_resource->extension_public->set(args->kill_time, 
353                                                        (void*) &MSG_process_kill,
354                                                        (void*) process);
355           }
356           xbt_free(args);
357         }
358         if(fun==MSG_process_kill) {
359           process = arg;
360           DEBUG3("Killing %s(%d) on %s", process->name, process->simdata->PID, 
361                  process->simdata->host->name);
362           MSG_process_kill(process);
363         }
364       }
365       
366       xbt_dynar_foreach(resource_list, i, resource) {
367         while ((action =
368                 xbt_swag_extract(resource->common_public->states.
369                                  failed_action_set))) {
370           task = action->data;
371           if(task) {
372             int _cursor;
373             DEBUG1("** %s failed **",task->name);
374             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
375               DEBUG3("\t preparing to wake up %s(%d) on %s",         
376                      process->name,process->simdata->PID,
377                      process->simdata->host->name);
378               xbt_fifo_unshift(msg_global->process_to_run, process);
379             }
380             process=NULL;
381           }
382         }
383         while ((action =
384                 xbt_swag_extract(resource->common_public->states.
385                                  done_action_set))) {
386           task = action->data;
387           if(task) {
388             int _cursor;
389             DEBUG1("** %s done **",task->name);
390             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
391               DEBUG3("\t preparing to wake up %s(%d) on %s",         
392                      process->name,process->simdata->PID,
393                      process->simdata->host->name);
394               xbt_fifo_unshift(msg_global->process_to_run, process);
395             }
396             process=NULL;
397           }
398         }
399       }
400     }
401     state_modifications = 0;
402   }
403
404   if ((nbprocess=xbt_fifo_size(msg_global->process_list)) == 0) {
405     INFO0("Congratulations ! Simulation terminated : all process are over");
406     return MSG_OK;
407   } else {
408     xbt_fifo_item_t item = NULL;
409     INFO0("Oops ! Deadlock or code not perfectly clean.");
410     INFO1("MSG: %d processes are still running, waiting for something.",
411           nbprocess);
412     /*  List the process and their state */
413     INFO0("MSG: <process>(<pid>) on <host>: <status>.");
414     xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
415       simdata_process_t p_simdata = (simdata_process_t) process->simdata;
416       simdata_host_t h_simdata=(simdata_host_t)p_simdata->host->simdata;
417       
418
419       INFO4("MSG:  %s(%d) on %s: %s",
420              process->name,p_simdata->PID,
421             p_simdata->host->name,
422             (process->simdata->blocked)?"[blocked] "
423             :((process->simdata->suspended)?"[suspended] ":""));
424
425       for (i=0; i<msg_global->max_channel; i++) {
426         if (h_simdata->sleeping[i] == process) {
427           INFO1("\tListening on channel %d.",i);
428           break;
429         }
430       }
431       if (i==msg_global->max_channel) {
432         if(p_simdata->waiting_task) {
433           if(p_simdata->waiting_task->simdata->compute) {
434             if(p_simdata->put_host) 
435               INFO2("\tTrying to send a task to Host %s, channel %d.",
436                     p_simdata->put_host->name, p_simdata->put_channel);
437             else 
438               INFO1("Waiting for %s to finish.",p_simdata->waiting_task->name);
439           } else if (p_simdata->waiting_task->simdata->comm)
440             INFO1("Waiting for %s to be finished transfered.",
441                     p_simdata->waiting_task->name);
442           else
443             INFO0("UNKNOWN STATUS. Please report this bug.");
444         }
445         else { /* Must be trying to put a task somewhere */
446           INFO0("UNKNOWN STATUS. Please report this bug.");
447         }
448       } 
449     }
450     if(XBT_LOG_ISENABLED(msg, xbt_log_priority_debug) ||
451        XBT_LOG_ISENABLED(global, xbt_log_priority_debug)) {
452       DEBUG0("Aborting!");
453       xbt_abort();
454     }
455
456     INFO0("Return a Warning.");
457     return MSG_WARNING;
458   }
459 }
460
461 /** \ingroup msg_simulation
462  * \brief Kill all running process
463
464  * \param reset_PIDs should we reset the PID numbers. A negative
465  *   number means no reset and a positive number will be used to set the PID
466  *   of the next newly created process.
467  */
468 int MSG_process_killall(int reset_PIDs)
469 {
470   m_process_t p = NULL;
471   m_process_t self = MSG_process_self();
472
473   while((p=xbt_fifo_pop(msg_global->process_list))) {
474     if(p!=self) MSG_process_kill(p);
475   }
476
477   if(reset_PIDs>0) {
478     msg_global->PID = reset_PIDs; 
479     msg_global->session++;
480  }
481
482   xbt_context_empty_trash();
483
484   if(self) {
485     xbt_context_yield();
486   }
487
488   return msg_global->PID;
489 }
490
491 /** \ingroup msg_simulation
492  * \brief Clean the MSG simulation
493  */
494 MSG_error_t MSG_clean(void)
495 {
496   xbt_fifo_item_t i = NULL;
497   m_host_t h = NULL;
498   m_process_t p = NULL;
499
500
501   while((p=xbt_fifo_pop(msg_global->process_list))) {
502     MSG_process_kill(p);
503   }
504   xbt_context_exit();
505
506   xbt_fifo_foreach(msg_global->host,i,h,m_host_t) {
507     __MSG_host_destroy(h);
508   }
509   xbt_fifo_free(msg_global->host);
510   xbt_fifo_free(msg_global->process_to_run);
511   xbt_fifo_free(msg_global->process_list);
512   xbt_dict_free(&(msg_global->registered_functions));
513
514   if(msg_global->paje_output) {
515     fclose(msg_global->paje_output);
516     msg_global->paje_output = NULL;
517   }
518   msg_config_finalize();
519   free(msg_global);
520   surf_exit();
521
522   return MSG_OK;
523 }
524
525
526 /** \ingroup msg_easier_life
527  * \brief A clock (in second).
528  */
529 double MSG_get_clock(void) {
530   return surf_get_clock();
531 }
532