Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
f08dabb5d0d5f8fedc8e5d761e6cacd204deb1e7
[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       if (process->simdata->kill_time >= 0.0 &&
329           process->simdata->kill_time < surf_get_clock()) {
330         INFO3("KILLING %s(%d) on %s (kill_time elapsed; too bad)",
331                process->name,process->simdata->PID,
332                process->simdata->host->name);
333         MSG_process_kill(process);
334          
335       } else {
336         DEBUG3("Scheduling  %s(%d) on %s",           
337                process->name,process->simdata->PID,
338                process->simdata->host->name);
339         msg_global->current_process = process;
340         fflush(NULL);
341         xbt_context_schedule(process->simdata->context);
342         msg_global->current_process = NULL;
343       }
344     }
345     DEBUG1("%lg : Calling surf_solve",MSG_getClock());
346     elapsed_time = surf_solve();
347     DEBUG1("Elapsed_time %lg",elapsed_time);
348
349 /*     fprintf(stderr, "====== %lg =====\n",Now); */
350 /*     if (elapsed_time==0.0) { */
351 /*       fprintf(stderr, "No change in time\n"); */
352 /*     } */
353     if (elapsed_time<0.0) {
354 /*       fprintf(stderr, "We're done %lg\n",elapsed_time); */
355       break;
356     }
357
358     {
359       surf_action_t action = NULL;
360       surf_resource_t resource = NULL;
361       m_task_t task = NULL;
362       
363       xbt_dynar_foreach(resource_list, i, resource) {
364         while ((action =
365                xbt_swag_extract(resource->common_public->states.
366                                 failed_action_set))) {
367           task = action->data;
368           if(task) {
369             int _cursor;
370             DEBUG1("** %s failed **",task->name);
371 /*          fprintf(stderr,"** %s **\n",task->name); */
372             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
373               DEBUG3("\t preparing to wake up %s(%d) on %s",         
374                      process->name,process->simdata->PID,
375                      process->simdata->host->name);
376               xbt_fifo_unshift(msg_global->process_to_run, process);
377             }
378             process=NULL;
379           }
380         }
381         while ((action =
382                xbt_swag_extract(resource->common_public->states.
383                                 done_action_set))) {
384           task = action->data;
385           if(task) {
386             int _cursor;
387             DEBUG1("** %s done **",task->name);
388 /*          fprintf(stderr,"** %s **\n",task->name); */
389             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
390               DEBUG3("\t preparing to wake up %s(%d) on %s",         
391                      process->name,process->simdata->PID,
392                      process->simdata->host->name);
393               xbt_fifo_unshift(msg_global->process_to_run, process);
394             }
395             process=NULL;
396           }
397         }
398       }
399     }
400   }
401
402   if ((nbprocess=xbt_fifo_size(msg_global->process_list)) == 0) {
403     fprintf(stderr,
404             "MSG: Congratulations ! Simulation terminated : all process are over\n");
405     return MSG_OK;
406   } else {
407     xbt_fifo_item_t item = NULL;
408     fprintf(stderr,"MSG: Oops ! Deadlock or code not perfectly clean.\n");
409     fprintf(stderr,"MSG: %d processes are still running, waiting for something.\n",
410             nbprocess);
411     /*  List the process and their state */
412     fprintf(stderr,"MSG: <process>(<pid>) on <host>: <status>.\n");
413     xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
414       simdata_process_t p_simdata = (simdata_process_t) process->simdata;
415       simdata_host_t h_simdata=(simdata_host_t)p_simdata->host->simdata;
416       
417
418       fprintf(stderr,"MSG:  %s(%d) on %s: ",
419              process->name,p_simdata->PID,
420              p_simdata->host->name);
421
422       if (process->simdata->blocked)      
423         fprintf(stderr,"[blocked] ");
424       if (process->simdata->suspended)    
425         fprintf(stderr,"[suspended] ");
426
427       for (i=0; i<msg_global->max_channel; i++) {
428         if (h_simdata->sleeping[i] == process) {
429           fprintf(stderr,"Listening on channel %d.\n",i);
430           break;
431         }
432       }
433       if (i==msg_global->max_channel) {
434         if(p_simdata->waiting_task) {
435           if(p_simdata->waiting_task->simdata->compute) {
436             if(p_simdata->put_host) 
437               fprintf(stderr,"Trying to send a task on Host %s, channel %d.\n",
438                       p_simdata->put_host->name, p_simdata->put_channel);
439             else 
440               fprintf(stderr,"Waiting for %s to finish.\n",p_simdata->waiting_task->name);
441           } else if (p_simdata->waiting_task->simdata->comm)
442             fprintf(stderr,"Waiting for %s to be finished transfered.\n",
443                     p_simdata->waiting_task->name);
444           else
445             fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
446         }
447         else { /* Must be trying to put a task somewhere */
448           fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
449         }
450       } 
451     }
452     if(XBT_LOG_ISENABLED(msg, xbt_log_priority_debug) ||
453        XBT_LOG_ISENABLED(global, xbt_log_priority_debug)) {
454       DEBUG0("Aborting!");
455       xbt_abort();
456     }
457
458     return MSG_WARNING;
459   }
460 }
461
462 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList)  */
463 /* { */
464 /*   simdata_task_t simdata = NULL; */
465 /*   xbt_fifo_item_t i = NULL; */
466 /*   m_process_t p = NULL; */
467   
468 /*   xbt_assert0((t!=NULL),"Invalid task"); */
469 /*   simdata = t->simdata; */
470
471 /* #define KILL(task) if(task) SG_failTask(task) */
472 /*   KILL(simdata->compute); */
473 /*   KILL(simdata->TCP_comm); */
474 /*   KILL(simdata->s[0]); */
475 /*   KILL(simdata->s[1]); */
476 /*   KILL(simdata->s[2]); */
477 /*   KILL(simdata->s[3]); */
478 /*   KILL(simdata->sleep); */
479 /* #undef KILL   */
480 /* /\*   if(simdata->comm) SG_failEndToEndTransfer(simdata->comm); *\/ */
481   
482 /*   xbt_fifo_foreach(simdata->sleeping,i,p,m_process_t) { */
483 /*     if(!TBX_HashTable_isInList(failedProcessList,p,TBX_basicHash))  */
484 /*       TBX_HashTable_insert(failedProcessList,p,TBX_basicHash); */
485 /*   } */
486   
487 /* } */
488
489 /* static xbt_fifo_t MSG_buildFailedHostList(double begin, double end) */
490 /* { */
491 /*   xbt_fifo_t failedHostList = xbt_fifo_new(); */
492 /*   m_host_t host = NULL; */
493 /*   xbt_fifo_item_t i; */
494
495 /*   xbt_fifo_foreach(msg_global->host,i,host,m_host_t) { */
496 /*     SG_Resource r= ((simdata_host_t) (host->simdata))->host; */
497
498 /*     if(SG_evaluateFailureTrace(r->failure_trace,begin,end)!=-1.0) */
499 /*       xbt_fifo_insert(failedHostList,host); */
500 /*   } */
501
502 /*   return failedHostList; */
503 /* } */
504
505 /** \ingroup msg_simulation
506  * \brief Kill all running process
507
508  * \param reset_PIDs should we reset the PID numbers. A negative
509  *   number means no reset and a positive number will be used to set the PID
510  *   of the next newly created process.
511  */
512 int MSG_process_killall(int reset_PIDs)
513 {
514   xbt_fifo_item_t i = NULL;
515   m_process_t p = NULL;
516   m_process_t self = MSG_process_self();
517
518   while((p=xbt_fifo_shift(msg_global->process_list))) {
519     if(p!=self) MSG_process_kill(p);
520   }
521
522   if(reset_PIDs>0) {
523     msg_global->PID = reset_PIDs; 
524     msg_global->session++;
525  }
526
527   xbt_context_empty_trash();
528
529   if(self) {
530     xbt_context_yield();
531   }
532
533   return msg_global->PID;
534 }
535
536 /** \ingroup msg_simulation
537  * \brief Clean the MSG simulation
538  */
539 MSG_error_t MSG_clean(void)
540 {
541   xbt_fifo_item_t i = NULL;
542   m_host_t h = NULL;
543   m_process_t p = NULL;
544
545
546   while((p=xbt_fifo_shift(msg_global->process_list))) {
547     MSG_process_kill(p);
548   }
549   xbt_context_exit();
550
551   xbt_fifo_foreach(msg_global->host,i,h,m_host_t) {
552     __MSG_host_destroy(h);
553   }
554   xbt_fifo_free(msg_global->host);
555   xbt_fifo_free(msg_global->process_to_run);
556   xbt_fifo_free(msg_global->process_list);
557   xbt_dict_free(&(msg_global->registered_functions));
558
559   if(msg_global->paje_output) {
560     fclose(msg_global->paje_output);
561     msg_global->paje_output = NULL;
562   }
563   free(msg_global);
564   surf_finalize();
565
566   return MSG_OK;
567 }
568
569
570 /** \ingroup msg_easier_life
571  * \brief A clock (in second).
572  * \deprecated Use MSG_get_clock
573  */
574 double MSG_getClock(void) {
575   return surf_get_clock();
576 }
577
578 /** \ingroup msg_easier_life
579  * \brief A clock (in second).
580  */
581 double MSG_get_clock(void) {
582   return surf_get_clock();
583 }
584