Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Move gcc attributes wrappers to this file (needed for splintification)
[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   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     msg_global = xbt_new0(s_MSG_Global_t,1);
46
47     surf_init(argc, argv);      /* Initialize some common structures */
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     "%EndEventDef\n"
147     "%EventDef  PajePopState    12\n"
148     "%  Time    date\n"
149     "%  EntityType      string\n"
150     "%  Container       string\n"
151     "%EndEventDef\n"
152     "%EventDef  PajeSetVariable 13\n"
153     "%  Time    date\n"
154     "%  EntityType      string\n"
155     "%  Container       string\n"
156     "%  Value   double\n"
157     "%EndEventDef\n"
158     "%EventDef  PajeAddVariable 14\n"
159     "%  Time    date\n"
160     "%  EntityType      string\n"
161     "%  Container       string\n"
162     "%  Value   double\n"
163     "%EndEventDef\n"
164     "%EventDef  PajeSubVariable 15\n"
165     "%  Time    date\n"
166     "%  EntityType      string\n"
167     "%  Container       string\n"
168     "%  Value   double\n"
169     "%EndEventDef\n"
170     "%EventDef  PajeStartLink   16\n"
171     "%  Time    date\n"
172     "%  EntityType      string\n"
173     "%  Container       string\n"
174     "%  Value   string\n"
175     "%  SourceContainer string\n"
176     "%  Key     string\n"
177     "%EndEventDef\n"
178     "%EventDef  PajeEndLink     17\n"
179     "%  Time    date\n"
180     "%  EntityType      string\n"
181     "%  Container       string\n"
182     "%  Value   string\n"
183     "%  DestContainer   string\n"
184     "%  Key     string\n"
185     "%EndEventDef\n";
186
187   const char *type_definitions = "1     Sim_t   0       Simulation_t\n"
188     "1  H_t     Sim_t   m_host_t\n"
189     "1  P_t     H_t     m_process_t\n"
190     "3  S_t     P_t     \"Process State\"\n"
191     "6  E       S_t     Executing\n"
192     "6  B       S_t     Blocked\n"
193     "6  C       S_t     Communicating\n"
194     "5  Comm    Sim_t   P_t     P_t     Communication_t\n";
195
196   const char *ext = ".trace";
197   int ext_len = strlen(ext);
198   int len;
199
200   xbt_assert0(msg_global, "Initialize MSG first\n");
201   xbt_assert0(!msg_global->paje_output, "Paje output allready defined\n");
202   xbt_assert0(filename, "Need a real file name\n");
203
204   len = strlen(filename);
205   if((len<ext_len) || (strncmp(filename+len-ext_len,ext,ext_len))) {
206     CRITICAL2("%s does not end by \"%s\". It may cause troubles when using Paje\n",
207               filename,ext);
208   }
209
210   xbt_assert0(filename, "Need a real file name\n");
211
212   msg_global->paje_output=fopen(filename,"w");
213   xbt_assert1(msg_global->paje_output, "Failed to open %s \n",filename);
214
215   fprintf(msg_global->paje_output,"%s",paje_preembule);
216   fprintf(msg_global->paje_output,"%s",type_definitions);
217   for(i=0; i<msg_global->max_channel; i++) {
218     fprintf(msg_global->paje_output, "6 COMM_%d Comm    \"Channel %d\"\n" ,i,i);
219   }
220   fprintf(msg_global->paje_output,
221           "7    0.0     CUR     Sim_t   0       \"MSG simulation\"\n");
222
223 }
224
225 /** \ingroup msg_simulation
226  * \brief Defines the verbosity of the simulation.
227  */
228 void MSG_set_verbosity(MSG_outputmode_t mode)
229 {
230   CRITICAL0("MSG_set_verbosity : Not implemented yet.");
231 }
232
233 /** \defgroup m_channel_management    Understanding channels
234  *  \brief This section briefly describes the channel notion of MSG
235  *  (#m_channel_t).
236  *
237  *  For convenience, the simulator provides the notion of channel
238  *  that is close to the tag notion in MPI. A channel is not a
239  *  socket. It doesn't need to be opened neither closed. It rather
240  *  corresponds to the ports opened on the different machines.
241  */
242
243
244 /** \ingroup m_channel_management
245  * \brief Set the number of channel in the simulation.
246  *
247  * This function has to be called to fix the number of channel in the
248    simulation before creating any host. Indeed, each channel is
249    represented by a different mailbox on each #m_host_t. This
250    function can then be called only once. This function takes only one
251    parameter.
252  * \param number the number of channel in the simulation. It has to be >0
253  */
254 MSG_error_t MSG_set_channel_number(int number)
255 {
256   xbt_assert0((msg_global) && (msg_global->max_channel == 0), "Channel number already set!");
257
258   msg_global->max_channel = number;
259
260   return MSG_OK;
261 }
262
263 /** \ingroup m_simulation
264  * \brief Set the sharing policy used for the links
265  *
266  * This function can be called to change the sharing policy used for the links 
267    (see \ref paper_tcp). By default the store and forward mechanism is used
268    with a parameter equal to 0.1. This function has to be called before creating 
269    any link. 
270  * \param mode the sharing policy used for the links: can be either 
271    MSG_STORE_AND_FORWARD or MSG_TCP.
272  * \param param a parameter for the sharing policy. It has to be >0. It is 
273    currently used only for the MSG_STORE_AND_FORWARD flavor and represents the
274    granularity of the communications (i.e. the packet size).
275  */
276 MSG_error_t MSG_set_sharing_policy(MSG_sharing_t mode, double param)
277 {
278   CRITICAL0("MSG_set_sharing_policy: this function is now deprecated and useless. Store and forward does not exist anymore. Please stop using it.");
279   
280   return MSG_OK;
281 }
282
283 /** \ingroup m_channel_management
284  * \brief Return the number of channel in the simulation.
285  *
286  * This function has to be called once the number of channel is fixed. I can't 
287    figure out a reason why anyone would like to call this function but nevermind.
288  * \return the number of channel in the simulation.
289  */
290 int MSG_get_channel_number(void)
291 {
292   xbt_assert0((msg_global)&&(msg_global->max_channel != 0), "Channel number not set yet!");
293
294   return msg_global->max_channel;
295 }
296
297 /** \ingroup msg_simulation
298  * \brief Launch the MSG simulation
299  */
300 MSG_error_t MSG_main(void)
301 {
302   m_process_t process = NULL;
303   int nbprocess,i;
304   double elapsed_time = 0.0;
305
306   /* Clean IO before the run */
307   fflush(stdout);
308   fflush(stderr);
309
310   surf_solve(); /* Takes traces into account. Returns 0.0 */
311 /* xbt_fifo_size(msg_global->process_to_run) */
312   while (1) {
313     xbt_context_empty_trash();
314     while ((process = xbt_fifo_pop(msg_global->process_to_run))) {
315 /*       fprintf(stderr,"-> %s (%d)\n",process->name, process->simdata->PID); */
316       DEBUG3("Scheduling  %s(%d) on %s",             
317              process->name,process->simdata->PID,
318              process->simdata->host->name);
319       msg_global->current_process = process;
320       xbt_context_schedule(process->simdata->context);
321       msg_global->current_process = NULL;
322     }
323     DEBUG1("%lg : Calling surf_solve",MSG_getClock());
324     elapsed_time = surf_solve();
325     DEBUG1("Elapsed_time %lg",elapsed_time);
326
327 /*     fprintf(stderr, "====== %lg =====\n",Now); */
328 /*     if (elapsed_time==0.0) { */
329 /*       fprintf(stderr, "No change in time\n"); */
330 /*     } */
331     if (elapsed_time<0.0) {
332 /*       fprintf(stderr, "We're done %lg\n",elapsed_time); */
333       break;
334     }
335
336     {
337       surf_action_t action = NULL;
338       surf_resource_t resource = NULL;
339       m_task_t task = NULL;
340       
341       xbt_dynar_foreach(resource_list, i, resource) {
342         while ((action =
343                xbt_swag_extract(resource->common_public->states.
344                                 failed_action_set))) {
345           task = action->data;
346           if(task) {
347             int _cursor;
348             DEBUG1("** %s failed **",task->name);
349 /*          fprintf(stderr,"** %s **\n",task->name); */
350             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
351               DEBUG3("\t preparing to wake up %s(%d) on %s",         
352                      process->name,process->simdata->PID,
353                      process->simdata->host->name);
354               xbt_fifo_unshift(msg_global->process_to_run, process);
355             }
356             process=NULL;
357           }
358         }
359         while ((action =
360                xbt_swag_extract(resource->common_public->states.
361                                 done_action_set))) {
362           task = action->data;
363           if(task) {
364             int _cursor;
365             DEBUG1("** %s done **",task->name);
366 /*          fprintf(stderr,"** %s **\n",task->name); */
367             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
368               DEBUG3("\t preparing to wake up %s(%d) on %s",         
369                      process->name,process->simdata->PID,
370                      process->simdata->host->name);
371               xbt_fifo_unshift(msg_global->process_to_run, process);
372             }
373             process=NULL;
374           }
375         }
376       }
377     }
378   }
379
380   if ((nbprocess=xbt_fifo_size(msg_global->process_list)) == 0) {
381     fprintf(stderr,
382             "MSG: Congratulations ! Simulation terminated : all process are over\n");
383     return MSG_OK;
384   } else {
385     xbt_fifo_item_t item = NULL;
386     fprintf(stderr,"MSG: Oops ! Deadlock or code not perfectly clean.\n");
387     fprintf(stderr,"MSG: %d processes are still running, waiting for something.\n",
388             nbprocess);
389     /*  List the process and their state */
390     fprintf(stderr,"MSG: <process>(<pid>) on <host>: <status>.\n");
391     xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
392       simdata_process_t p_simdata = (simdata_process_t) process->simdata;
393       simdata_host_t h_simdata=(simdata_host_t)p_simdata->host->simdata;
394       
395
396       fprintf(stderr,"MSG:  %s(%d) on %s: ",
397              process->name,p_simdata->PID,
398              p_simdata->host->name);
399
400       if (process->simdata->blocked)      
401         fprintf(stderr,"[blocked] ");
402       if (process->simdata->suspended)    
403         fprintf(stderr,"[suspended] ");
404
405       for (i=0; i<msg_global->max_channel; i++) {
406         if (h_simdata->sleeping[i] == process) {
407           fprintf(stderr,"Listening on channel %d.\n",i);
408           break;
409         }
410       }
411       if (i==msg_global->max_channel) {
412         if(p_simdata->waiting_task) {
413           if(p_simdata->waiting_task->simdata->compute) {
414             if(p_simdata->put_host) 
415               fprintf(stderr,"Trying to send a task on Host %s, channel %d.\n",
416                       p_simdata->put_host->name, p_simdata->put_channel);
417             else 
418               fprintf(stderr,"Waiting for %s to finish.\n",p_simdata->waiting_task->name);
419           } else if (p_simdata->waiting_task->simdata->comm)
420             fprintf(stderr,"Waiting for %s to be finished transfered.\n",
421                     p_simdata->waiting_task->name);
422           else
423             fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
424         }
425         else { /* Must be trying to put a task somewhere */
426           fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
427         }
428       } 
429     }
430     if(XBT_LOG_ISENABLED(msg, xbt_log_priority_debug) ||
431        XBT_LOG_ISENABLED(global, xbt_log_priority_debug)) {
432       DEBUG0("Aborting!");
433       xbt_abort();
434     }
435
436     return MSG_WARNING;
437   }
438 }
439
440 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList)  */
441 /* { */
442 /*   simdata_task_t simdata = NULL; */
443 /*   xbt_fifo_item_t i = NULL; */
444 /*   m_process_t p = NULL; */
445   
446 /*   xbt_assert0((t!=NULL),"Invalid task"); */
447 /*   simdata = t->simdata; */
448
449 /* #define KILL(task) if(task) SG_failTask(task) */
450 /*   KILL(simdata->compute); */
451 /*   KILL(simdata->TCP_comm); */
452 /*   KILL(simdata->s[0]); */
453 /*   KILL(simdata->s[1]); */
454 /*   KILL(simdata->s[2]); */
455 /*   KILL(simdata->s[3]); */
456 /*   KILL(simdata->sleep); */
457 /* #undef KILL   */
458 /* /\*   if(simdata->comm) SG_failEndToEndTransfer(simdata->comm); *\/ */
459   
460 /*   xbt_fifo_foreach(simdata->sleeping,i,p,m_process_t) { */
461 /*     if(!TBX_HashTable_isInList(failedProcessList,p,TBX_basicHash))  */
462 /*       TBX_HashTable_insert(failedProcessList,p,TBX_basicHash); */
463 /*   } */
464   
465 /* } */
466
467 /* static xbt_fifo_t MSG_buildFailedHostList(double begin, double end) */
468 /* { */
469 /*   xbt_fifo_t failedHostList = xbt_fifo_new(); */
470 /*   m_host_t host = NULL; */
471 /*   xbt_fifo_item_t i; */
472
473 /*   xbt_fifo_foreach(msg_global->host,i,host,m_host_t) { */
474 /*     SG_Resource r= ((simdata_host_t) (host->simdata))->host; */
475
476 /*     if(SG_evaluateFailureTrace(r->failure_trace,begin,end)!=-1.0) */
477 /*       xbt_fifo_insert(failedHostList,host); */
478 /*   } */
479
480 /*   return failedHostList; */
481 /* } */
482
483 /** \ingroup msg_simulation
484  * \brief Kill all running process
485
486  * \param reset_PIDs should we reset the PID numbers. A negative
487  *   number means no reset and a positive number will be used to set the PID
488  *   of the next newly created process.
489  */
490 int MSG_process_killall(int reset_PIDs)
491 {
492   xbt_fifo_item_t i = NULL;
493   m_process_t p = NULL;
494
495   while((p=xbt_fifo_shift(msg_global->process_list))) {
496     MSG_process_kill(p);
497   }
498   xbt_context_empty_trash();
499   if(reset_PIDs>0) {
500     msg_global->PID = reset_PIDs; 
501     msg_global->session++;
502  }
503
504   return msg_global->PID;
505 }
506
507 /** \ingroup msg_simulation
508  * \brief Clean the MSG simulation
509  */
510 MSG_error_t MSG_clean(void)
511 {
512   xbt_fifo_item_t i = NULL;
513   m_host_t h = NULL;
514   m_process_t p = NULL;
515
516
517   while((p=xbt_fifo_shift(msg_global->process_list))) {
518     MSG_process_kill(p);
519   }
520   xbt_context_exit();
521
522   xbt_fifo_foreach(msg_global->host,i,h,m_host_t) {
523     __MSG_host_destroy(h);
524   }
525   xbt_fifo_free(msg_global->host);
526   xbt_fifo_free(msg_global->process_to_run);
527   xbt_fifo_free(msg_global->process_list);
528   xbt_dict_free(&(msg_global->registered_functions));
529
530   if(msg_global->paje_output) {
531     fclose(msg_global->paje_output);
532     msg_global->paje_output = NULL;
533   }
534   free(msg_global);
535   surf_finalize();
536
537   return MSG_OK;
538 }
539
540
541 /** \ingroup msg_easier_life
542  * \brief A clock (in second).
543  */
544 double MSG_getClock(void) {
545   return surf_get_clock();
546 }
547