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. */
9 #include "xbt/sysdep.h"
11 #include "xbt/ex.h" /* ex_backtrace_display */
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_kernel, msg,
13 "Logging specific to MSG (kernel)");
15 int __stop_at_time = -1.0 ;
17 MSG_Global_t msg_global = NULL;
19 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList); */
20 /* static xbt_fifo_t MSG_buildFailedHostList(double a, double b); */
22 /** \defgroup msg_simulation MSG simulation Functions
23 * \brief This section describes the functions you need to know to
24 * set up a simulation. You should have a look at \ref MSG_examples
25 * to have an overview of their usage.
26 * \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Simulation functions" --> \endhtmlonly
29 /********************************* MSG **************************************/
31 /** \ingroup msg_simulation
32 * \brief Initialize some MSG internal data.
34 void MSG_global_init_args(int *argc, char **argv)
36 MSG_global_init(argc,argv);
39 /** \ingroup msg_simulation
40 * \brief Initialize some MSG internal data.
42 void MSG_global_init(int *argc, char **argv)
45 surf_init(argc, argv); /* Initialize some common structures. Warning, it sets msg_global=NULL */
47 msg_global = xbt_new0(s_MSG_Global_t,1);
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();
60 /** \ingroup msg_easier_life
61 * \brief Traces MSG events in the Paje format.
63 void MSG_paje_output(const char *filename)
66 const char *paje_preembule="%EventDef SetLimits 0\n"
70 "%EventDef PajeDefineContainerType 1\n"
72 "% ContainerType string\n"
75 "%EventDef PajeDefineEventType 2\n"
77 "% ContainerType string\n"
80 "%EventDef PajeDefineStateType 3\n"
82 "% ContainerType string\n"
85 "%EventDef PajeDefineVariableType 4\n"
87 "% ContainerType string\n"
90 "%EventDef PajeDefineLinkType 5\n"
92 "% ContainerType string\n"
93 "% SourceContainerType string\n"
94 "% DestContainerType string\n"
97 "%EventDef PajeDefineEntityValue 6\n"
99 "% EntityType string\n"
102 "%EventDef PajeCreateContainer 7\n"
104 "% NewContainer string\n"
105 "% NewContainerType string\n"
106 "% Container string\n"
109 "%EventDef PajeDestroyContainer 8\n"
114 "%EventDef PajeNewEvent 9\n"
116 "% EntityType string\n"
117 "% Container string\n"
120 "%EventDef PajeSetState 10\n"
122 "% EntityType string\n"
123 "% Container string\n"
126 "%EventDef PajeSetState 101\n"
128 "% EntityType string\n"
129 "% Container string\n"
131 "% FileName string\n"
134 "%EventDef PajePushState 111\n"
136 "% EntityType string\n"
137 "% Container string\n"
139 "% FileName string\n"
142 "%EventDef PajePushState 11\n"
144 "% EntityType string\n"
145 "% Container string\n"
147 "% TaskName string\n"
149 "%EventDef PajePopState 12\n"
151 "% EntityType string\n"
152 "% Container string\n"
154 "%EventDef PajeSetVariable 13\n"
156 "% EntityType string\n"
157 "% Container string\n"
160 "%EventDef PajeAddVariable 14\n"
162 "% EntityType string\n"
163 "% Container string\n"
166 "%EventDef PajeSubVariable 15\n"
168 "% EntityType string\n"
169 "% Container string\n"
172 "%EventDef PajeStartLink 16\n"
174 "% EntityType string\n"
175 "% Container string\n"
177 "% SourceContainer string\n"
180 "%EventDef PajeEndLink 17\n"
182 "% EntityType string\n"
183 "% Container string\n"
185 "% DestContainer string\n"
189 const char *type_definitions = "1 Sim_t 0 Simulation_t\n"
190 "1 H_t Sim_t m_host_t\n"
191 "1 P_t H_t m_process_t\n"
192 "3 S_t P_t \"Process State\"\n"
193 "6 E S_t Executing\n"
195 "6 C S_t Communicating\n"
196 "5 Comm Sim_t P_t P_t Communication_t\n";
198 const char *ext = ".trace";
199 int ext_len = strlen(ext);
203 xbt_fifo_item_t item = NULL;
205 xbt_assert0(msg_global, "Initialize MSG first\n");
206 xbt_assert0(!msg_global->paje_output, "Paje output already defined\n");
207 xbt_assert0(filename, "Need a real file name\n");
209 len = strlen(filename);
210 if((len<ext_len) || (strncmp(filename+len-ext_len,ext,ext_len))) {
211 CRITICAL2("The name of the Paje trace file \"%s\" does not end by \"%s\". Paje will cause difficulties to read it.\n",
215 msg_global->paje_output=fopen(filename,"w");
216 xbt_assert1(msg_global->paje_output, "Failed to open %s \n",filename);
218 fprintf(msg_global->paje_output,"%s",paje_preembule);
219 fprintf(msg_global->paje_output,"%s",type_definitions);
222 for(i=0; i<msg_global->max_channel; i++) {
223 fprintf(msg_global->paje_output, "6 COMM_%d Comm \"Channel %d\"\n" ,i,i);
225 fprintf(msg_global->paje_output,
226 "7 0.0 CUR Sim_t 0 \"MSG simulation\"\n");
229 xbt_fifo_foreach(msg_global->host,item,host,m_host_t) {
234 xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
235 PAJE_PROCESS_NEW(process);
239 /** \defgroup m_channel_management Understanding channels
240 * \brief This section briefly describes the channel notion of MSG
242 * \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Channels" --> \endhtmlonly
245 * For convenience, the simulator provides the notion of channel
246 * that is close to the tag notion in MPI. A channel is not a
247 * socket. It doesn't need to be opened neither closed. It rather
248 * corresponds to the ports opened on the different machines.
252 /** \ingroup m_channel_management
253 * \brief Set the number of channel in the simulation.
255 * This function has to be called to fix the number of channel in the
256 simulation before creating any host. Indeed, each channel is
257 represented by a different mailbox on each #m_host_t. This
258 function can then be called only once. This function takes only one
260 * \param number the number of channel in the simulation. It has to be >0
262 MSG_error_t MSG_set_channel_number(int number)
264 xbt_assert0((msg_global) && (msg_global->max_channel == 0), "Channel number already set!");
266 msg_global->max_channel = number;
271 /** \ingroup m_channel_management
272 * \brief Return the number of channel in the simulation.
274 * This function has to be called once the number of channel is fixed. I can't
275 figure out a reason why anyone would like to call this function but nevermind.
276 * \return the number of channel in the simulation.
278 int MSG_get_channel_number(void)
280 xbt_assert0((msg_global)&&(msg_global->max_channel != 0), "Channel number not set yet!");
282 return msg_global->max_channel;
285 void __MSG_display_process_status(void)
287 m_process_t process = NULL;
288 xbt_fifo_item_t item = NULL;
290 int nbprocess=xbt_fifo_size(msg_global->process_list);
292 INFO1("MSG: %d processes are still running, waiting for something.",
294 /* List the process and their state */
295 INFO0("MSG: <process>(<pid>) on <host>: <status>.");
296 xbt_fifo_foreach(msg_global->process_list,item,process,m_process_t) {
297 simdata_process_t p_simdata = (simdata_process_t) process->simdata;
298 simdata_host_t h_simdata=(simdata_host_t)p_simdata->host->simdata;
301 INFO4("MSG: %s(%d) on %s: %s",
302 process->name,p_simdata->PID,
303 p_simdata->host->name,
304 (process->simdata->blocked)?"[blocked] "
305 :((process->simdata->suspended)?"[suspended] ":""));
307 for (i=0; i<msg_global->max_channel; i++) {
308 if (h_simdata->sleeping[i] == process) {
309 INFO1("\tListening on channel %d.",i);
313 if (i==msg_global->max_channel) {
314 if(p_simdata->waiting_task) {
315 if(p_simdata->waiting_task->simdata->compute) {
316 if(p_simdata->put_host) {
317 INFO2("\tTrying to send a task to Host %s, channel %d.",
318 p_simdata->put_host->name, p_simdata->put_channel);
320 INFO1("Waiting for %s to finish.",p_simdata->waiting_task->name);
322 } else if (p_simdata->waiting_task->simdata->comm) {
323 INFO1("Waiting for %s to be finished transfered.",
324 p_simdata->waiting_task->name);
326 INFO0("UNKNOWN STATUS. Please report this bug.");
328 /* The following would display the trace of where the maestro thread is,
329 since this is the thread calling this. I'd like to get the other threads to
330 run this to see where they were blocked, but I'm not sure of how to do this */
331 /* xbt_backtrace_display(); */
332 } else { /* Must be trying to put a task somewhere */
333 INFO0("UNKNOWN STATUS. Please report this bug.");
339 /* FIXME: Yeah, I'll do it in a portable maner one day [Mt] */
342 static void inthandler(int ignored)
344 INFO0("CTRL-C pressed. Displaying status and bailing out");
345 __MSG_display_process_status();
349 /** \ingroup msg_simulation
350 * \brief Launch the MSG simulation
352 MSG_error_t MSG_main(void)
354 m_process_t process = NULL;
356 double elapsed_time = 0.0;
357 int state_modifications = 1;
359 /* Prepare to display some more info when dying on Ctrl-C pressing */
360 signal(SIGINT,inthandler);
362 /* Clean IO before the run */
366 surf_solve(); /* Takes traces into account. Returns 0.0 */
367 /* xbt_fifo_size(msg_global->process_to_run) */
369 xbt_context_empty_trash();
370 if(xbt_fifo_size(msg_global->process_to_run) && (elapsed_time>0)) {
371 DEBUG0("**************************************************");
373 if((__stop_at_time>0) && (MSG_get_clock() >= __stop_at_time)) {
374 DEBUG0("Let's stop here!");
377 while ((process = xbt_fifo_pop(msg_global->process_to_run))) {
378 DEBUG3("Scheduling %s(%d) on %s",
379 process->name,process->simdata->PID,
380 process->simdata->host->name);
381 msg_global->current_process = process;
383 xbt_context_schedule(process->simdata->context);
384 msg_global->current_process = NULL;
388 surf_action_t action = NULL;
389 surf_resource_t resource = NULL;
390 m_task_t task = NULL;
395 xbt_dynar_foreach(resource_list, i, resource) {
396 if(xbt_swag_size(resource->common_public->states.failed_action_set) ||
397 xbt_swag_size(resource->common_public->states.done_action_set))
398 state_modifications = 1;
401 if(!state_modifications) {
402 DEBUG1("%f : Calling surf_solve",MSG_get_clock());
403 elapsed_time = surf_solve();
404 DEBUG1("Elapsed_time %f",elapsed_time);
406 if (elapsed_time<0.0) {
407 /* fprintf(stderr, "We're done %g\n",elapsed_time); */
412 while (surf_timer_resource->extension_public->get(&fun,(void*)&arg)) {
413 DEBUG2("got %p %p", fun, arg);
414 if(fun==MSG_process_create_with_arguments) {
415 process_arg_t args = arg;
416 DEBUG2("Launching %s on %s", args->name, args->host->name);
417 process = MSG_process_create_with_arguments(args->name, args->code,
418 args->data, args->host,
419 args->argc,args->argv);
420 if(args->kill_time > MSG_get_clock()) {
421 surf_timer_resource->extension_public->set(args->kill_time,
422 (void*) &MSG_process_kill,
427 if(fun==MSG_process_kill) {
429 DEBUG3("Killing %s(%d) on %s", process->name, process->simdata->PID,
430 process->simdata->host->name);
431 MSG_process_kill(process);
435 xbt_dynar_foreach(resource_list, i, resource) {
437 xbt_swag_extract(resource->common_public->states.
438 failed_action_set))) {
442 DEBUG1("** %s failed **",task->name);
443 xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
444 DEBUG3("\t preparing to wake up %s(%d) on %s",
445 process->name,process->simdata->PID,
446 process->simdata->host->name);
447 xbt_fifo_unshift(msg_global->process_to_run, process);
453 xbt_swag_extract(resource->common_public->states.
458 DEBUG1("** %s done **",task->name);
459 xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
460 DEBUG3("\t preparing to wake up %s(%d) on %s",
461 process->name,process->simdata->PID,
462 process->simdata->host->name);
463 xbt_fifo_unshift(msg_global->process_to_run, process);
470 state_modifications = 0;
473 if (xbt_fifo_size(msg_global->process_list) == 0) {
474 INFO0("Congratulations ! Simulation terminated : all process are over");
477 INFO0("Oops ! Deadlock or code not perfectly clean.");
478 __MSG_display_process_status();
479 if(XBT_LOG_ISENABLED(msg, xbt_log_priority_debug) ||
480 XBT_LOG_ISENABLED(msg_kernel, xbt_log_priority_debug)) {
485 INFO0("Return a Warning.");
490 /** \ingroup msg_simulation
491 * \brief Kill all running process
493 * \param reset_PIDs should we reset the PID numbers. A negative
494 * number means no reset and a positive number will be used to set the PID
495 * of the next newly created process.
497 int MSG_process_killall(int reset_PIDs)
499 m_process_t p = NULL;
500 m_process_t self = MSG_process_self();
502 while((p=xbt_fifo_pop(msg_global->process_list))) {
503 if(p!=self) MSG_process_kill(p);
507 msg_global->PID = reset_PIDs;
508 msg_global->session++;
511 xbt_context_empty_trash();
517 return msg_global->PID;
520 /** \ingroup msg_simulation
521 * \brief Clean the MSG simulation
523 MSG_error_t MSG_clean(void)
525 xbt_fifo_item_t i = NULL;
527 m_process_t p = NULL;
530 while((p=xbt_fifo_pop(msg_global->process_list))) {
535 xbt_fifo_foreach(msg_global->host,i,h,m_host_t) {
536 __MSG_host_destroy(h);
538 xbt_fifo_free(msg_global->host);
539 xbt_fifo_free(msg_global->process_to_run);
540 xbt_fifo_free(msg_global->process_list);
541 xbt_dict_free(&(msg_global->registered_functions));
543 if(msg_global->paje_output) {
544 fclose(msg_global->paje_output);
545 msg_global->paje_output = NULL;
547 msg_config_finalize();
555 /** \ingroup msg_easier_life
556 * \brief A clock (in second).
558 double MSG_get_clock(void) {
559 return surf_get_clock();