Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
9160e07c5d974a25cec808cbc56e380a264f82b7
[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("Function MSG_global_init() is deprecated by MSG_global_init_args().");
36   MSG_global_init_args(&argc,argv);
37 }
38
39 /** \ingroup msg_simulation
40  * \brief Initialize some MSG internal data.
41  */
42 void MSG_global_init_args(int *argc, char **argv)
43 {
44   if (!msg_global) {
45     surf_init(argc, argv);      /* Initialize some common structures. Warning, it sets msg_global=NULL */
46      
47     msg_global = xbt_new0(s_MSG_Global_t,1);
48
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   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("%s does not end by \"%s\". It may cause troubles when using Paje\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 /** \ingroup msg_simulation
239  * \brief Defines the verbosity of the simulation.
240  */
241 void MSG_set_verbosity(MSG_outputmode_t mode)
242 {
243   CRITICAL0("MSG_set_verbosity : Deprecated function. Use the XBT logging interface.");
244 }
245
246 /** \defgroup m_channel_management    Understanding channels
247  *  \brief This section briefly describes the channel notion of MSG
248  *  (#m_channel_t).
249  *
250  *  For convenience, the simulator provides the notion of channel
251  *  that is close to the tag notion in MPI. A channel is not a
252  *  socket. It doesn't need to be opened neither closed. It rather
253  *  corresponds to the ports opened on the different machines.
254  */
255
256
257 /** \ingroup m_channel_management
258  * \brief Set the number of channel in the simulation.
259  *
260  * This function has to be called to fix the number of channel in the
261    simulation before creating any host. Indeed, each channel is
262    represented by a different mailbox on each #m_host_t. This
263    function can then be called only once. This function takes only one
264    parameter.
265  * \param number the number of channel in the simulation. It has to be >0
266  */
267 MSG_error_t MSG_set_channel_number(int number)
268 {
269   xbt_assert0((msg_global) && (msg_global->max_channel == 0), "Channel number already set!");
270
271   msg_global->max_channel = number;
272
273   return MSG_OK;
274 }
275
276 /** \ingroup m_simulation
277  * \brief Set the sharing policy used for the links
278  *
279  * This function can be called to change the sharing policy used for the links 
280    (see \ref paper_tcp). By default the store and forward mechanism is used
281    with a parameter equal to 0.1. This function has to be called before creating 
282    any link. 
283  * \param mode the sharing policy used for the links: can be either 
284    MSG_STORE_AND_FORWARD or MSG_TCP.
285  * \param param a parameter for the sharing policy. It has to be >0. It is 
286    currently used only for the MSG_STORE_AND_FORWARD flavor and represents the
287    granularity of the communications (i.e. the packet size).
288  */
289 MSG_error_t MSG_set_sharing_policy(MSG_sharing_t mode, double param)
290 {
291   CRITICAL0("MSG_set_sharing_policy: this function is now deprecated and useless. Store and forward does not exist anymore. Please stop using it.");
292   
293   return MSG_OK;
294 }
295
296 /** \ingroup m_channel_management
297  * \brief Return the number of channel in the simulation.
298  *
299  * This function has to be called once the number of channel is fixed. I can't 
300    figure out a reason why anyone would like to call this function but nevermind.
301  * \return the number of channel in the simulation.
302  */
303 int MSG_get_channel_number(void)
304 {
305   xbt_assert0((msg_global)&&(msg_global->max_channel != 0), "Channel number not set yet!");
306
307   return msg_global->max_channel;
308 }
309
310 /** \ingroup msg_simulation
311  * \brief Launch the MSG simulation
312  */
313 MSG_error_t MSG_main(void)
314 {
315   m_process_t process = NULL;
316   int nbprocess,i;
317   double elapsed_time = 0.0;
318
319   /* Clean IO before the run */
320   fflush(stdout);
321   fflush(stderr);
322
323   surf_solve(); /* Takes traces into account. Returns 0.0 */
324 /* xbt_fifo_size(msg_global->process_to_run) */
325   while (1) {
326     xbt_context_empty_trash();
327     while ((process = xbt_fifo_pop(msg_global->process_to_run))) {
328 /*       fprintf(stderr,"-> %s (%d)\n",process->name, process->simdata->PID); */
329       DEBUG3("Scheduling  %s(%d) on %s",             
330              process->name,process->simdata->PID,
331              process->simdata->host->name);
332       msg_global->current_process = process;
333       fflush(NULL);
334       xbt_context_schedule(process->simdata->context);
335       msg_global->current_process = NULL;
336     }
337     DEBUG1("%lg : Calling surf_solve",MSG_getClock());
338     elapsed_time = surf_solve();
339     DEBUG1("Elapsed_time %lg",elapsed_time);
340
341 /*     fprintf(stderr, "====== %lg =====\n",Now); */
342 /*     if (elapsed_time==0.0) { */
343 /*       fprintf(stderr, "No change in time\n"); */
344 /*     } */
345     if (elapsed_time<0.0) {
346 /*       fprintf(stderr, "We're done %lg\n",elapsed_time); */
347       break;
348     }
349
350     {
351       surf_action_t action = NULL;
352       surf_resource_t resource = NULL;
353       m_task_t task = NULL;
354       
355       xbt_dynar_foreach(resource_list, i, resource) {
356         while ((action =
357                xbt_swag_extract(resource->common_public->states.
358                                 failed_action_set))) {
359           task = action->data;
360           if(task) {
361             int _cursor;
362             DEBUG1("** %s failed **",task->name);
363 /*          fprintf(stderr,"** %s **\n",task->name); */
364             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
365               DEBUG3("\t preparing to wake up %s(%d) on %s",         
366                      process->name,process->simdata->PID,
367                      process->simdata->host->name);
368               xbt_fifo_unshift(msg_global->process_to_run, process);
369             }
370             process=NULL;
371           }
372         }
373         while ((action =
374                xbt_swag_extract(resource->common_public->states.
375                                 done_action_set))) {
376           task = action->data;
377           if(task) {
378             int _cursor;
379             DEBUG1("** %s done **",task->name);
380 /*          fprintf(stderr,"** %s **\n",task->name); */
381             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
382               DEBUG3("\t preparing to wake up %s(%d) on %s",         
383                      process->name,process->simdata->PID,
384                      process->simdata->host->name);
385               xbt_fifo_unshift(msg_global->process_to_run, process);
386             }
387             process=NULL;
388           }
389         }
390       }
391     }
392   }
393
394   if ((nbprocess=xbt_fifo_size(msg_global->process_list)) == 0) {
395     fprintf(stderr,
396             "MSG: Congratulations ! Simulation terminated : all process are over\n");
397     return MSG_OK;
398   } else {
399     xbt_fifo_item_t item = NULL;
400     fprintf(stderr,"MSG: Oops ! Deadlock or code not perfectly clean.\n");
401     fprintf(stderr,"MSG: %d processes are still running, waiting for something.\n",
402             nbprocess);
403     /*  List the process and their state */
404     fprintf(stderr,"MSG: <process>(<pid>) on <host>: <status>.\n");
405     xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
406       simdata_process_t p_simdata = (simdata_process_t) process->simdata;
407       simdata_host_t h_simdata=(simdata_host_t)p_simdata->host->simdata;
408       
409
410       fprintf(stderr,"MSG:  %s(%d) on %s: ",
411              process->name,p_simdata->PID,
412              p_simdata->host->name);
413
414       if (process->simdata->blocked)      
415         fprintf(stderr,"[blocked] ");
416       if (process->simdata->suspended)    
417         fprintf(stderr,"[suspended] ");
418
419       for (i=0; i<msg_global->max_channel; i++) {
420         if (h_simdata->sleeping[i] == process) {
421           fprintf(stderr,"Listening on channel %d.\n",i);
422           break;
423         }
424       }
425       if (i==msg_global->max_channel) {
426         if(p_simdata->waiting_task) {
427           if(p_simdata->waiting_task->simdata->compute) {
428             if(p_simdata->put_host) 
429               fprintf(stderr,"Trying to send a task on Host %s, channel %d.\n",
430                       p_simdata->put_host->name, p_simdata->put_channel);
431             else 
432               fprintf(stderr,"Waiting for %s to finish.\n",p_simdata->waiting_task->name);
433           } else if (p_simdata->waiting_task->simdata->comm)
434             fprintf(stderr,"Waiting for %s to be finished transfered.\n",
435                     p_simdata->waiting_task->name);
436           else
437             fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
438         }
439         else { /* Must be trying to put a task somewhere */
440           fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
441         }
442       } 
443     }
444     if(XBT_LOG_ISENABLED(msg, xbt_log_priority_debug) ||
445        XBT_LOG_ISENABLED(global, xbt_log_priority_debug)) {
446       DEBUG0("Aborting!");
447       xbt_abort();
448     }
449
450     return MSG_WARNING;
451   }
452 }
453
454 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList)  */
455 /* { */
456 /*   simdata_task_t simdata = NULL; */
457 /*   xbt_fifo_item_t i = NULL; */
458 /*   m_process_t p = NULL; */
459   
460 /*   xbt_assert0((t!=NULL),"Invalid task"); */
461 /*   simdata = t->simdata; */
462
463 /* #define KILL(task) if(task) SG_failTask(task) */
464 /*   KILL(simdata->compute); */
465 /*   KILL(simdata->TCP_comm); */
466 /*   KILL(simdata->s[0]); */
467 /*   KILL(simdata->s[1]); */
468 /*   KILL(simdata->s[2]); */
469 /*   KILL(simdata->s[3]); */
470 /*   KILL(simdata->sleep); */
471 /* #undef KILL   */
472 /* /\*   if(simdata->comm) SG_failEndToEndTransfer(simdata->comm); *\/ */
473   
474 /*   xbt_fifo_foreach(simdata->sleeping,i,p,m_process_t) { */
475 /*     if(!TBX_HashTable_isInList(failedProcessList,p,TBX_basicHash))  */
476 /*       TBX_HashTable_insert(failedProcessList,p,TBX_basicHash); */
477 /*   } */
478   
479 /* } */
480
481 /* static xbt_fifo_t MSG_buildFailedHostList(double begin, double end) */
482 /* { */
483 /*   xbt_fifo_t failedHostList = xbt_fifo_new(); */
484 /*   m_host_t host = NULL; */
485 /*   xbt_fifo_item_t i; */
486
487 /*   xbt_fifo_foreach(msg_global->host,i,host,m_host_t) { */
488 /*     SG_Resource r= ((simdata_host_t) (host->simdata))->host; */
489
490 /*     if(SG_evaluateFailureTrace(r->failure_trace,begin,end)!=-1.0) */
491 /*       xbt_fifo_insert(failedHostList,host); */
492 /*   } */
493
494 /*   return failedHostList; */
495 /* } */
496
497 /** \ingroup msg_simulation
498  * \brief Kill all running process
499
500  * \param reset_PIDs should we reset the PID numbers. A negative
501  *   number means no reset and a positive number will be used to set the PID
502  *   of the next newly created process.
503  */
504 int MSG_process_killall(int reset_PIDs)
505 {
506   xbt_fifo_item_t i = NULL;
507   m_process_t p = NULL;
508   m_process_t self = MSG_process_self();
509
510   while((p=xbt_fifo_shift(msg_global->process_list))) {
511     if(p!=self) MSG_process_kill(p);
512   }
513
514   if(reset_PIDs>0) {
515     msg_global->PID = reset_PIDs; 
516     msg_global->session++;
517  }
518
519   xbt_context_empty_trash();
520
521   if(self) {
522     xbt_context_yield();
523   }
524
525   return msg_global->PID;
526 }
527
528 /** \ingroup msg_simulation
529  * \brief Clean the MSG simulation
530  */
531 MSG_error_t MSG_clean(void)
532 {
533   xbt_fifo_item_t i = NULL;
534   m_host_t h = NULL;
535   m_process_t p = NULL;
536
537
538   while((p=xbt_fifo_shift(msg_global->process_list))) {
539     MSG_process_kill(p);
540   }
541   xbt_context_exit();
542
543   xbt_fifo_foreach(msg_global->host,i,h,m_host_t) {
544     __MSG_host_destroy(h);
545   }
546   xbt_fifo_free(msg_global->host);
547   xbt_fifo_free(msg_global->process_to_run);
548   xbt_fifo_free(msg_global->process_list);
549   xbt_dict_free(&(msg_global->registered_functions));
550
551   if(msg_global->paje_output) {
552     fclose(msg_global->paje_output);
553     msg_global->paje_output = NULL;
554   }
555   free(msg_global);
556   surf_finalize();
557
558   return MSG_OK;
559 }
560
561
562 /** \ingroup msg_easier_life
563  * \brief A clock (in second).
564  * \deprecated Use MSG_get_clock
565  */
566 double MSG_getClock(void) {
567   return surf_get_clock();
568 }
569
570 /** \ingroup msg_easier_life
571  * \brief A clock (in second).
572  */
573 double MSG_get_clock(void) {
574   return surf_get_clock();
575 }
576