Logo AND Algorithmique Numérique Distribuée

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