3 /* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved. */
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. */
10 #include "xbt/error.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(global, msg,
12 "Logging specific to MSG (global)");
14 MSG_Global_t msg_global = NULL;
16 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList); */
17 /* static xbt_fifo_t MSG_buildFailedHostList(long double a, long double b); */
19 /********************************* MSG **************************************/
21 /** \ingroup msg_simulation
22 * \brief Initialize some MSG internal data.
24 void MSG_global_init(void)
29 CRITICAL0("Please stop using this function. Use MSG_global_init_args instead.");
31 MSG_global_init_args(&argc,argv);
34 /** \ingroup msg_simulation
35 * \brief Initialize some MSG internal data.
37 void MSG_global_init_args(int *argc, char **argv)
40 msg_global = xbt_new0(s_MSG_Global_t,1);
42 surf_init(argc, argv); /* Initialize some common structures */
44 msg_global->host = xbt_fifo_new();
45 msg_global->process_to_run = xbt_fifo_new();
46 msg_global->process_list = xbt_fifo_new();
47 msg_global->max_channel = 0;
48 msg_global->current_process = NULL;
49 msg_global->registered_functions = xbt_dict_new();
54 /** \ingroup msg_easier_life
55 * \brief Traces MSG events in the Paje format.
57 void MSG_paje_output(const char *filename)
60 const char *paje_preembule="%EventDef SetLimits 0\n"
64 "%EventDef PajeDefineContainerType 1\n"
66 "% ContainerType string\n"
69 "%EventDef PajeDefineEventType 2\n"
71 "% ContainerType string\n"
74 "%EventDef PajeDefineStateType 3\n"
76 "% ContainerType string\n"
79 "%EventDef PajeDefineVariableType 4\n"
81 "% ContainerType string\n"
84 "%EventDef PajeDefineLinkType 5\n"
86 "% ContainerType string\n"
87 "% SourceContainerType string\n"
88 "% DestContainerType string\n"
91 "%EventDef PajeDefineEntityValue 6\n"
93 "% EntityType string\n"
96 "%EventDef PajeCreateContainer 7\n"
98 "% NewContainer string\n"
99 "% NewContainerType string\n"
100 "% Container string\n"
103 "%EventDef PajeDestroyContainer 8\n"
108 "%EventDef PajeNewEvent 9\n"
110 "% EntityType string\n"
111 "% Container string\n"
114 "%EventDef PajeSetState 10\n"
116 "% EntityType string\n"
117 "% Container string\n"
120 "%EventDef PajeSetState 101\n"
122 "% EntityType string\n"
123 "% Container string\n"
125 "% FileName string\n"
128 "%EventDef PajePushState 111\n"
130 "% EntityType string\n"
131 "% Container string\n"
133 "% FileName string\n"
136 "%EventDef PajePushState 11\n"
138 "% EntityType string\n"
139 "% Container string\n"
142 "%EventDef PajePopState 12\n"
144 "% EntityType string\n"
145 "% Container string\n"
147 "%EventDef PajeSetVariable 13\n"
149 "% EntityType string\n"
150 "% Container string\n"
153 "%EventDef PajeAddVariable 14\n"
155 "% EntityType string\n"
156 "% Container string\n"
159 "%EventDef PajeSubVariable 15\n"
161 "% EntityType string\n"
162 "% Container string\n"
165 "%EventDef PajeStartLink 16\n"
167 "% EntityType string\n"
168 "% Container string\n"
170 "% SourceContainer string\n"
173 "%EventDef PajeEndLink 17\n"
175 "% EntityType string\n"
176 "% Container string\n"
178 "% DestContainer string\n"
182 const char *type_definitions = "1 Sim_t 0 Simulation_t\n"
183 "1 H_t Sim_t m_host_t\n"
184 "1 P_t H_t m_process_t\n"
185 "3 S_t P_t \"Process State\"\n"
186 "6 E S_t Executing\n"
188 "6 C S_t Communicating\n"
189 "5 Comm Sim_t P_t P_t Communication_t\n";
191 const char *ext = ".trace";
192 int ext_len = strlen(ext);
195 xbt_assert0(msg_global, "Initialize MSG first\n");
196 xbt_assert0(!msg_global->paje_output, "Paje output allready defined\n");
197 xbt_assert0(filename, "Need a real file name\n");
199 len = strlen(filename);
200 if((len<ext_len) || (strncmp(filename+len-ext_len,ext,ext_len))) {
201 CRITICAL2("%s does not end by \"%s\". It may cause troubles when using Paje\n",
205 xbt_assert0(filename, "Need a real file name\n");
207 msg_global->paje_output=fopen(filename,"w");
208 xbt_assert1(msg_global->paje_output, "Failed to open %s \n",filename);
210 fprintf(msg_global->paje_output,"%s",paje_preembule);
211 fprintf(msg_global->paje_output,"%s",type_definitions);
212 for(i=0; i<msg_global->max_channel; i++) {
213 fprintf(msg_global->paje_output, "6 COMM_%d Comm \"Channel %d\"\n" ,i,i);
215 fprintf(msg_global->paje_output,
216 "7 0.0 CUR Sim_t 0 \"MSG simulation\"\n");
220 /** \ingroup msg_simulation
221 * \brief Defines the verbosity of the simulation.
223 void MSG_set_verbosity(MSG_outputmode_t mode)
225 CRITICAL0("MSG_set_verbosity : Not implemented yet.");
228 /** \ingroup m_channel_management
229 * \brief Set the number of channel in the simulation.
231 * This function has to be called to fix the number of channel in the
232 simulation before creating any host. Indeed, each channel is
233 represented by a different mailbox on each #m_host_t. This
234 function can then be called only once. This function takes only one
236 * \param number the number of channel in the simulation. It has to be >0
238 MSG_error_t MSG_set_channel_number(int number)
240 xbt_assert0((msg_global) && (msg_global->max_channel == 0), "Channel number already set!");
242 msg_global->max_channel = number;
247 /** \ingroup m_simulation
248 * \brief Set the sharing policy used for the links
250 * This function can be called to change the sharing policy used for the links
251 (see \ref paper_tcp). By default the store and forward mechanism is used
252 with a parameter equal to 0.1. This function has to be called before creating
254 * \param mode the sharing policy used for the links: can be either
255 MSG_STORE_AND_FORWARD or MSG_TCP.
256 * \param param a parameter for the sharing policy. It has to be >0. It is
257 currently used only for the MSG_STORE_AND_FORWARD flavor and represents the
258 granularity of the communications (i.e. the packet size).
260 MSG_error_t MSG_set_sharing_policy(MSG_sharing_t mode, long double param)
262 CRITICAL0("MSG_set_sharing_policy: this function is now deprecated and useless. Store and forward does not exist anymore. Please stop using it.");
267 /** \ingroup m_channel_management
268 * \brief Return the number of channel in the simulation.
270 * This function has to be called once the number of channel is fixed. I can't
271 figure out a reason why anyone would like to call this function but nevermind.
272 * \return the number of channel in the simulation.
274 int MSG_get_channel_number(void)
276 xbt_assert0((msg_global)&&(msg_global->max_channel != 0), "Channel number not set yet!");
278 return msg_global->max_channel;
281 /** \ingroup msg_simulation
282 * \brief Launch the MSG simulation
284 MSG_error_t MSG_main(void)
286 m_process_t process = NULL;
288 double elapsed_time = 0.0;
290 /* Clean IO before the run */
294 surf_solve(); /* Takes traces into account. Returns 0.0 */
295 /* xbt_fifo_size(msg_global->process_to_run) */
297 xbt_context_empty_trash();
298 while ((process = xbt_fifo_pop(msg_global->process_to_run))) {
299 /* fprintf(stderr,"-> %s (%d)\n",process->name, process->simdata->PID); */
300 DEBUG3("Scheduling %s(%d) on %s",
301 process->name,process->simdata->PID,
302 process->simdata->host->name);
303 msg_global->current_process = process;
304 xbt_context_schedule(process->simdata->context);
305 msg_global->current_process = NULL;
307 DEBUG1("%Lg : Calling surf_solve",MSG_getClock());
308 elapsed_time = surf_solve();
309 DEBUG1("Elapsed_time %lg",elapsed_time);
311 /* fprintf(stderr, "====== %Lg =====\n",Now); */
312 /* if (elapsed_time==0.0) { */
313 /* fprintf(stderr, "No change in time\n"); */
315 if (elapsed_time<0.0) {
316 /* fprintf(stderr, "We're done %lg\n",elapsed_time); */
321 surf_action_t action = NULL;
322 surf_resource_t resource = NULL;
323 m_task_t task = NULL;
325 xbt_dynar_foreach(resource_list, i, resource) {
327 xbt_swag_extract(resource->common_public->states.
328 failed_action_set))) {
332 DEBUG1("** %s failed **",task->name);
333 /* fprintf(stderr,"** %s **\n",task->name); */
334 xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
335 DEBUG3("\t preparing to wake up %s(%d) on %s",
336 process->name,process->simdata->PID,
337 process->simdata->host->name);
338 xbt_fifo_unshift(msg_global->process_to_run, process);
344 xbt_swag_extract(resource->common_public->states.
349 DEBUG1("** %s done **",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);
364 if ((nbprocess=xbt_fifo_size(msg_global->process_list)) == 0) {
366 "MSG: Congratulations ! Simulation terminated : all process are over\n");
369 xbt_fifo_item_t item = NULL;
370 fprintf(stderr,"MSG: Oops ! Deadlock or code not perfectly clean.\n");
371 fprintf(stderr,"MSG: %d processes are still running, waiting for something.\n",
373 /* List the process and their state */
374 fprintf(stderr,"MSG: <process>(<pid>) on <host>: <status>.\n");
375 xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
376 simdata_process_t p_simdata = (simdata_process_t) process->simdata;
377 simdata_host_t h_simdata=(simdata_host_t)p_simdata->host->simdata;
380 fprintf(stderr,"MSG: %s(%d) on %s: ",
381 process->name,p_simdata->PID,
382 p_simdata->host->name);
384 if (process->simdata->blocked)
385 fprintf(stderr,"[blocked] ");
386 if (process->simdata->suspended)
387 fprintf(stderr,"[suspended] ");
389 for (i=0; i<msg_global->max_channel; i++) {
390 if (h_simdata->sleeping[i] == process) {
391 fprintf(stderr,"Listening on channel %d.\n",i);
395 if (i==msg_global->max_channel) {
396 if(p_simdata->waiting_task) {
397 if(p_simdata->waiting_task->simdata->compute) {
398 if(p_simdata->put_host)
399 fprintf(stderr,"Trying to send a task on Host %s, channel %d.\n",
400 p_simdata->put_host->name, p_simdata->put_channel);
402 fprintf(stderr,"Waiting for %s to finish.\n",p_simdata->waiting_task->name);
403 } else if (p_simdata->waiting_task->simdata->comm)
404 fprintf(stderr,"Waiting for %s to be finished transfered.\n",
405 p_simdata->waiting_task->name);
407 fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
409 else { /* Must be trying to put a task somewhere */
410 fprintf(stderr,"UNKNOWN STATUS. Please report this bug.\n");
414 if(XBT_LOG_ISENABLED(msg, xbt_log_priority_debug) ||
415 XBT_LOG_ISENABLED(global, xbt_log_priority_debug)) {
424 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList) */
426 /* simdata_task_t simdata = NULL; */
427 /* xbt_fifo_item_t i = NULL; */
428 /* m_process_t p = NULL; */
430 /* xbt_assert0((t!=NULL),"Invalid task"); */
431 /* simdata = t->simdata; */
433 /* #define KILL(task) if(task) SG_failTask(task) */
434 /* KILL(simdata->compute); */
435 /* KILL(simdata->TCP_comm); */
436 /* KILL(simdata->s[0]); */
437 /* KILL(simdata->s[1]); */
438 /* KILL(simdata->s[2]); */
439 /* KILL(simdata->s[3]); */
440 /* KILL(simdata->sleep); */
442 /* /\* if(simdata->comm) SG_failEndToEndTransfer(simdata->comm); *\/ */
444 /* xbt_fifo_foreach(simdata->sleeping,i,p,m_process_t) { */
445 /* if(!TBX_HashTable_isInList(failedProcessList,p,TBX_basicHash)) */
446 /* TBX_HashTable_insert(failedProcessList,p,TBX_basicHash); */
451 /* static xbt_fifo_t MSG_buildFailedHostList(long double begin, long double end) */
453 /* xbt_fifo_t failedHostList = xbt_fifo_new(); */
454 /* m_host_t host = NULL; */
455 /* xbt_fifo_item_t i; */
457 /* xbt_fifo_foreach(msg_global->host,i,host,m_host_t) { */
458 /* SG_Resource r= ((simdata_host_t) (host->simdata))->host; */
460 /* if(SG_evaluateFailureTrace(r->failure_trace,begin,end)!=-1.0) */
461 /* xbt_fifo_insert(failedHostList,host); */
464 /* return failedHostList; */
467 /** \ingroup msg_simulation
468 * \brief Kill all running process
470 * \param reset_PIDs should we reset the PID numbers. A negative
471 * number means no reset and a positive number will be used to set the PID
472 * of the next newly created process.
474 int MSG_process_killall(int reset_PIDs)
476 xbt_fifo_item_t i = NULL;
477 m_process_t p = NULL;
479 while((p=xbt_fifo_shift(msg_global->process_list))) {
482 xbt_context_empty_trash();
484 msg_global->PID = reset_PIDs;
485 msg_global->session++;
488 return msg_global->PID;
491 /** \ingroup msg_simulation
492 * \brief Clean the MSG simulation
494 MSG_error_t MSG_clean(void)
496 xbt_fifo_item_t i = NULL;
498 m_process_t p = NULL;
501 while((p=xbt_fifo_shift(msg_global->process_list))) {
506 xbt_fifo_foreach(msg_global->host,i,h,m_host_t) {
507 __MSG_host_destroy(h);
509 xbt_fifo_free(msg_global->host);
510 xbt_fifo_free(msg_global->process_to_run);
511 xbt_fifo_free(msg_global->process_list);
512 xbt_dict_free(&(msg_global->registered_functions));
514 if(msg_global->paje_output) {
515 fclose(msg_global->paje_output);
516 msg_global->paje_output = NULL;
518 xbt_free(msg_global);
525 /** \ingroup msg_easier_life
526 * \brief A clock (in second).
528 long double MSG_getClock(void) {
529 return surf_get_clock();