Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
correction
[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/error.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(global, msg,
12                                 "Logging specific to MSG (global)");
13
14 MSG_Global_t msg_global = NULL;
15
16 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList); */
17 /* static xbt_fifo_t MSG_buildFailedHostList(double a, double b); */
18
19 /** \defgroup msg_simulation   MSG simulation Functions
20  *  \brief This section describes the functions you need to know to
21  *  set up a simulation. You should have a look at \ref MSG_examples 
22  *  to have an overview of their usage.
23  */
24
25 /********************************* MSG **************************************/
26
27 /** \ingroup msg_simulation
28  * \brief Initialize some MSG internal data.
29  */
30 void MSG_global_init(void)
31 {
32   int argc=0;
33   char **argv=NULL;
34
35   CRITICAL0("Please stop using this function. Use MSG_global_init_args instead.");
36   DIE_IMPOSSIBLE;
37   MSG_global_init_args(&argc,argv);
38 }
39
40 /** \ingroup msg_simulation
41  * \brief Initialize some MSG internal data.
42  */
43 void MSG_global_init_args(int *argc, char **argv)
44 {
45   if (!msg_global) {
46     msg_global = xbt_new0(s_MSG_Global_t,1);
47
48     surf_init(argc, argv);      /* Initialize some common structures */
49     xbt_context_init();
50     msg_global->host = xbt_fifo_new();
51     msg_global->process_to_run = xbt_fifo_new();
52     msg_global->process_list = xbt_fifo_new();
53     msg_global->max_channel = 0;
54     msg_global->current_process = NULL;
55     msg_global->registered_functions = xbt_dict_new();
56     msg_global->PID = 1;
57   }
58 }
59
60 /** \ingroup msg_easier_life
61  * \brief Traces MSG events in the Paje format.
62  */
63 void MSG_paje_output(const char *filename)
64 {
65   int i;
66   const char *paje_preembule="%EventDef SetLimits       0\n"
67     "%  StartTime       date\n"
68     "%  EndTime date\n"
69     "%EndEventDef\n"
70     "%EventDef  PajeDefineContainerType 1\n"
71     "%  NewType string\n"
72     "%  ContainerType   string\n"
73     "%  NewName string\n"
74     "%EndEventDef\n"
75     "%EventDef  PajeDefineEventType     2\n"
76     "%  NewType string\n"
77     "%  ContainerType   string\n"
78     "%  NewName string\n"
79     "%EndEventDef\n"
80     "%EventDef  PajeDefineStateType     3\n"
81     "%  NewType string\n"
82     "%  ContainerType   string\n"
83     "%  NewName string\n"
84     "%EndEventDef\n"
85     "%EventDef  PajeDefineVariableType  4\n"
86     "%  NewType string\n"
87     "%  ContainerType   string\n"
88     "%  NewName string\n"
89     "%EndEventDef\n"
90     "%EventDef  PajeDefineLinkType      5\n"
91     "%  NewType string\n"
92     "%  ContainerType   string\n"
93     "%  SourceContainerType     string\n"
94     "%  DestContainerType       string\n"
95     "%  NewName string\n"
96     "%EndEventDef\n"
97     "%EventDef  PajeDefineEntityValue   6\n"
98     "%  NewValue        string\n"
99     "%  EntityType      string\n"
100     "%  NewName string\n"
101     "%EndEventDef\n"
102     "%EventDef  PajeCreateContainer     7\n"
103     "%  Time    date\n"
104     "%  NewContainer    string\n"
105     "%  NewContainerType        string\n"
106     "%  Container       string\n"
107     "%  NewName string\n"
108     "%EndEventDef\n"
109     "%EventDef  PajeDestroyContainer    8\n"
110     "%  Time    date\n"
111     "%  Name    string\n"
112     "%  Type    string\n"
113     "%EndEventDef\n"
114     "%EventDef  PajeNewEvent    9\n"
115     "%  Time    date\n"
116     "%  EntityType      string\n"
117     "%  Container       string\n"
118     "%  Value   string\n"
119     "%EndEventDef\n"
120     "%EventDef  PajeSetState    10\n"
121     "%  Time    date\n"
122     "%  EntityType      string\n"
123     "%  Container       string\n"
124     "%  Value   string\n"
125     "%EndEventDef\n"
126     "%EventDef  PajeSetState    101\n"
127     "%  Time    date\n"
128     "%  EntityType      string\n"
129     "%  Container       string\n"
130     "%  Value   string\n"
131     "%  FileName        string\n"
132     "%  LineNumber      int\n"
133     "%EndEventDef\n"
134     "%EventDef  PajePushState   111\n"
135     "%  Time    date\n"
136     "%  EntityType      string\n"
137     "%  Container       string\n"
138     "%  Value   string\n"
139     "%  FileName        string\n"
140     "%  LineNumber      int\n"
141     "%EndEventDef\n"
142     "%EventDef  PajePushState   11\n"
143     "%  Time    date\n"
144     "%  EntityType      string\n"
145     "%  Container       string\n"
146     "%  Value   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
201   xbt_assert0(msg_global, "Initialize MSG first\n");
202   xbt_assert0(!msg_global->paje_output, "Paje output allready defined\n");
203   xbt_assert0(filename, "Need a real file name\n");
204
205   len = strlen(filename);
206   if((len<ext_len) || (strncmp(filename+len-ext_len,ext,ext_len))) {
207     CRITICAL2("%s does not end by \"%s\". It may cause troubles when using Paje\n",
208               filename,ext);
209   }
210
211   xbt_assert0(filename, "Need a real file name\n");
212
213   msg_global->paje_output=fopen(filename,"w");
214   xbt_assert1(msg_global->paje_output, "Failed to open %s \n",filename);
215
216   fprintf(msg_global->paje_output,"%s",paje_preembule);
217   fprintf(msg_global->paje_output,"%s",type_definitions);
218   for(i=0; i<msg_global->max_channel; i++) {
219     fprintf(msg_global->paje_output, "6 COMM_%d Comm    \"Channel %d\"\n" ,i,i);
220   }
221   fprintf(msg_global->paje_output,
222           "7    0.0     CUR     Sim_t   0       \"MSG simulation\"\n");
223
224 }
225
226 /** \ingroup msg_simulation
227  * \brief Defines the verbosity of the simulation.
228  */
229 void MSG_set_verbosity(MSG_outputmode_t mode)
230 {
231   CRITICAL0("MSG_set_verbosity : Not implemented yet.");
232 }
233
234 /** \defgroup m_channel_management    Understanding channels
235  *  \brief This section briefly describes the channel notion of MSG
236  *  (#m_channel_t).
237  *
238  *  For convenience, the simulator provides the notion of channel
239  *  that is close to the tag notion in MPI. A channel is not a
240  *  socket. It doesn't need to be opened neither closed. It rather
241  *  corresponds to the ports opened on the different machines.
242  */
243
244
245 /** \ingroup m_channel_management
246  * \brief Set the number of channel in the simulation.
247  *
248  * This function has to be called to fix the number of channel in the
249    simulation before creating any host. Indeed, each channel is
250    represented by a different mailbox on each #m_host_t. This
251    function can then be called only once. This function takes only one
252    parameter.
253  * \param number the number of channel in the simulation. It has to be >0
254  */
255 MSG_error_t MSG_set_channel_number(int number)
256 {
257   xbt_assert0((msg_global) && (msg_global->max_channel == 0), "Channel number already set!");
258
259   msg_global->max_channel = number;
260
261   return MSG_OK;
262 }
263
264 /** \ingroup m_simulation
265  * \brief Set the sharing policy used for the links
266  *
267  * This function can be called to change the sharing policy used for the links 
268    (see \ref paper_tcp). By default the store and forward mechanism is used
269    with a parameter equal to 0.1. This function has to be called before creating 
270    any link. 
271  * \param mode the sharing policy used for the links: can be either 
272    MSG_STORE_AND_FORWARD or MSG_TCP.
273  * \param param a parameter for the sharing policy. It has to be >0. It is 
274    currently used only for the MSG_STORE_AND_FORWARD flavor and represents the
275    granularity of the communications (i.e. the packet size).
276  */
277 MSG_error_t MSG_set_sharing_policy(MSG_sharing_t mode, double param)
278 {
279   CRITICAL0("MSG_set_sharing_policy: this function is now deprecated and useless. Store and forward does not exist anymore. Please stop using it.");
280   
281   return MSG_OK;
282 }
283
284 /** \ingroup m_channel_management
285  * \brief Return the number of channel in the simulation.
286  *
287  * This function has to be called once the number of channel is fixed. I can't 
288    figure out a reason why anyone would like to call this function but nevermind.
289  * \return the number of channel in the simulation.
290  */
291 int MSG_get_channel_number(void)
292 {
293   xbt_assert0((msg_global)&&(msg_global->max_channel != 0), "Channel number not set yet!");
294
295   return msg_global->max_channel;
296 }
297
298 /** \ingroup msg_simulation
299  * \brief Launch the MSG simulation
300  */
301 MSG_error_t MSG_main(void)
302 {
303   m_process_t process = NULL;
304   int nbprocess,i;
305   double elapsed_time = 0.0;
306
307   /* Clean IO before the run */
308   fflush(stdout);
309   fflush(stderr);
310
311   surf_solve(); /* Takes traces into account. Returns 0.0 */
312 /* xbt_fifo_size(msg_global->process_to_run) */
313   while (1) {
314     xbt_context_empty_trash();
315     while ((process = xbt_fifo_pop(msg_global->process_to_run))) {
316 /*       fprintf(stderr,"-> %s (%d)\n",process->name, process->simdata->PID); */
317       DEBUG3("Scheduling  %s(%d) on %s",             
318              process->name,process->simdata->PID,
319              process->simdata->host->name);
320       msg_global->current_process = process;
321       xbt_context_schedule(process->simdata->context);
322       msg_global->current_process = NULL;
323     }
324     DEBUG1("%lg : Calling surf_solve",MSG_getClock());
325     elapsed_time = surf_solve();
326     DEBUG1("Elapsed_time %lg",elapsed_time);
327
328 /*     fprintf(stderr, "====== %lg =====\n",Now); */
329 /*     if (elapsed_time==0.0) { */
330 /*       fprintf(stderr, "No change in time\n"); */
331 /*     } */
332     if (elapsed_time<0.0) {
333 /*       fprintf(stderr, "We're done %lg\n",elapsed_time); */
334       break;
335     }
336
337     {
338       surf_action_t action = NULL;
339       surf_resource_t resource = NULL;
340       m_task_t task = NULL;
341       
342       xbt_dynar_foreach(resource_list, i, resource) {
343         while ((action =
344                xbt_swag_extract(resource->common_public->states.
345                                 failed_action_set))) {
346           task = action->data;
347           if(task) {
348             int _cursor;
349             DEBUG1("** %s failed **",task->name);
350 /*          fprintf(stderr,"** %s **\n",task->name); */
351             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
352               DEBUG3("\t preparing to wake up %s(%d) on %s",         
353                      process->name,process->simdata->PID,
354                      process->simdata->host->name);
355               xbt_fifo_unshift(msg_global->process_to_run, process);
356             }
357             process=NULL;
358           }
359         }
360         while ((action =
361                xbt_swag_extract(resource->common_public->states.
362                                 done_action_set))) {
363           task = action->data;
364           if(task) {
365             int _cursor;
366             DEBUG1("** %s done **",task->name);
367 /*          fprintf(stderr,"** %s **\n",task->name); */
368             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
369               DEBUG3("\t preparing to wake up %s(%d) on %s",         
370                      process->name,process->simdata->PID,
371                      process->simdata->host->name);
372               xbt_fifo_unshift(msg_global->process_to_run, process);
373             }
374             process=NULL;
375           }
376         }
377       }
378     }
379   }
380
381   if ((nbprocess=xbt_fifo_size(msg_global->process_list)) == 0) {
382     fprintf(stderr,
383             "MSG: Congratulations ! Simulation terminated : all process are over\n");
384     return MSG_OK;
385   } else {
386     xbt_fifo_item_t item = NULL;
387     fprintf(stderr,"MSG: Oops ! Deadlock or code not perfectly clean.\n");
388     fprintf(stderr,"MSG: %d processes are still running, waiting for something.\n",
389             nbprocess);
390     /*  List the process and their state */
391     fprintf(stderr,"MSG: <process>(<pid>) on <host>: <status>.\n");
392     xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
393       simdata_process_t p_simdata = (simdata_process_t) process->simdata;
394       simdata_host_t h_simdata=(simdata_host_t)p_simdata->host->simdata;
395       
396
397       fprintf(stderr,"MSG:  %s(%d) on %s: ",
398              process->name,p_simdata->PID,
399              p_simdata->host->name);
400
401       if (process->simdata->blocked)      
402         fprintf(stderr,"[blocked] ");
403       if (process->simdata->suspended)    
404         fprintf(stderr,"[suspended] ");
405
406       for (i=0; i<msg_global->max_channel; i++) {
407         if (h_simdata->sleeping[i] == process) {
408           fprintf(stderr,"Listening on channel %d.\n",i);
409           break;
410         }
411       }
412       if (i==msg_global->max_channel) {
413         if(p_simdata->waiting_task) {
414           if(p_simdata->waiting_task->simdata->compute) {
415             if(p_simdata->put_host) 
416               fprintf(stderr,"Trying to send a task on Host %s, channel %d.\n",
417                       p_simdata->put_host->name, p_simdata->put_channel);
418             else 
419               fprintf(stderr,"Waiting for %s to finish.\n",p_simdata->waiting_task->name);
420           } else if (p_simdata->waiting_task->simdata->comm)
421             fprintf(stderr,"Waiting for %s to be finished transfered.\n",
422                     p_simdata->waiting_task->name);
423           else
424             fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
425         }
426         else { /* Must be trying to put a task somewhere */
427           fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
428         }
429       } 
430     }
431     if(XBT_LOG_ISENABLED(msg, xbt_log_priority_debug) ||
432        XBT_LOG_ISENABLED(global, xbt_log_priority_debug)) {
433       DEBUG0("Aborting!");
434       xbt_abort();
435     }
436
437     return MSG_WARNING;
438   }
439 }
440
441 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList)  */
442 /* { */
443 /*   simdata_task_t simdata = NULL; */
444 /*   xbt_fifo_item_t i = NULL; */
445 /*   m_process_t p = NULL; */
446   
447 /*   xbt_assert0((t!=NULL),"Invalid task"); */
448 /*   simdata = t->simdata; */
449
450 /* #define KILL(task) if(task) SG_failTask(task) */
451 /*   KILL(simdata->compute); */
452 /*   KILL(simdata->TCP_comm); */
453 /*   KILL(simdata->s[0]); */
454 /*   KILL(simdata->s[1]); */
455 /*   KILL(simdata->s[2]); */
456 /*   KILL(simdata->s[3]); */
457 /*   KILL(simdata->sleep); */
458 /* #undef KILL   */
459 /* /\*   if(simdata->comm) SG_failEndToEndTransfer(simdata->comm); *\/ */
460   
461 /*   xbt_fifo_foreach(simdata->sleeping,i,p,m_process_t) { */
462 /*     if(!TBX_HashTable_isInList(failedProcessList,p,TBX_basicHash))  */
463 /*       TBX_HashTable_insert(failedProcessList,p,TBX_basicHash); */
464 /*   } */
465   
466 /* } */
467
468 /* static xbt_fifo_t MSG_buildFailedHostList(double begin, double end) */
469 /* { */
470 /*   xbt_fifo_t failedHostList = xbt_fifo_new(); */
471 /*   m_host_t host = NULL; */
472 /*   xbt_fifo_item_t i; */
473
474 /*   xbt_fifo_foreach(msg_global->host,i,host,m_host_t) { */
475 /*     SG_Resource r= ((simdata_host_t) (host->simdata))->host; */
476
477 /*     if(SG_evaluateFailureTrace(r->failure_trace,begin,end)!=-1.0) */
478 /*       xbt_fifo_insert(failedHostList,host); */
479 /*   } */
480
481 /*   return failedHostList; */
482 /* } */
483
484 /** \ingroup msg_simulation
485  * \brief Kill all running process
486
487  * \param reset_PIDs should we reset the PID numbers. A negative
488  *   number means no reset and a positive number will be used to set the PID
489  *   of the next newly created process.
490  */
491 int MSG_process_killall(int reset_PIDs)
492 {
493   xbt_fifo_item_t i = NULL;
494   m_process_t p = NULL;
495
496   while((p=xbt_fifo_shift(msg_global->process_list))) {
497     MSG_process_kill(p);
498   }
499   xbt_context_empty_trash();
500   if(reset_PIDs>0) {
501     msg_global->PID = reset_PIDs; 
502     msg_global->session++;
503  }
504
505   return msg_global->PID;
506 }
507
508 /** \ingroup msg_simulation
509  * \brief Clean the MSG simulation
510  */
511 MSG_error_t MSG_clean(void)
512 {
513   xbt_fifo_item_t i = NULL;
514   m_host_t h = NULL;
515   m_process_t p = NULL;
516
517
518   while((p=xbt_fifo_shift(msg_global->process_list))) {
519     MSG_process_kill(p);
520   }
521   xbt_context_exit();
522
523   xbt_fifo_foreach(msg_global->host,i,h,m_host_t) {
524     __MSG_host_destroy(h);
525   }
526   xbt_fifo_free(msg_global->host);
527   xbt_fifo_free(msg_global->process_to_run);
528   xbt_fifo_free(msg_global->process_list);
529   xbt_dict_free(&(msg_global->registered_functions));
530
531   if(msg_global->paje_output) {
532     fclose(msg_global->paje_output);
533     msg_global->paje_output = NULL;
534   }
535   xbt_free(msg_global);
536   surf_finalize();
537
538   return MSG_OK;
539 }
540
541
542 /** \ingroup msg_easier_life
543  * \brief A clock (in second).
544  */
545 double MSG_getClock(void) {
546   return surf_get_clock();
547 }
548