Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
e876a9a0875f71b2107c0a7526a9c3917ed4cc41
[simgrid.git] / src / simix / smx_global.c
1 /*      $Id$     */
2
3 /* Copyright (c) 2007 Arnaud Legrand, Bruno Donnassolo.
4    All rights reserved.                                          */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #include "private.h"
10 #include "xbt/sysdep.h"
11 #include "xbt/log.h"
12 #include "xbt/ex.h" /* ex_backtrace_display */
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_kernel, simix,
14                                 "Logging specific to SIMIX (kernel)");
15
16 //int __stop_at_time = -1.0 ;
17
18 SIMIX_Global_t simix_global = NULL;
19
20 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList); */
21 /* static xbt_fifo_t SIMIX_buildFailedHostList(double a, double b); */
22
23 /** \defgroup msg_simulation   SIMIX simulation Functions
24  *  \brief This section describes the functions you need to know to
25  *  set up a simulation. You should have a look at \ref SIMIX_examples 
26  *  to have an overview of their usage.
27  *    \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Simulation functions" --> \endhtmlonly
28  */
29
30 /********************************* SIMIX **************************************/
31
32 /** \ingroup msg_simulation
33  * \brief Initialize some SIMIX internal data.
34  */
35 void SIMIX_global_init_args(int *argc, char **argv)
36 {
37   SIMIX_global_init(argc,argv);
38 }
39
40 /** \ingroup msg_simulation
41  * \brief Initialize some SIMIX internal data.
42  */
43 void SIMIX_global_init(int *argc, char **argv)
44 {
45         s_smx_process_t proc;
46
47   if (!simix_global) {
48     surf_init(argc, argv);      /* Initialize some common structures. Warning, it sets msg_global=NULL */
49      
50     simix_global = xbt_new0(s_SIMIX_Global_t,1);
51
52     xbt_context_init();
53     simix_global->host = xbt_fifo_new();
54     simix_global->process_to_run = xbt_swag_new(xbt_swag_offset(proc,process_hookup));
55     simix_global->process_list = xbt_swag_new(xbt_swag_offset(proc,process_hookup));
56     simix_global->current_process = NULL;
57     simix_global->registered_functions = xbt_dict_new();
58   }
59 }
60
61 void __SIMIX_display_process_status(void)
62 {
63    smx_process_t process = NULL;
64    //xbt_fifo_item_t item = NULL;
65    //int i;
66    int nbprocess=xbt_swag_size(simix_global->process_list);
67    
68    INFO1("SIMIX: %d processes are still running, waiting for something.",
69          nbprocess);
70    /*  List the process and their state */
71    INFO0("SIMIX: <process>(<pid>) on <host>: <status>.");
72    xbt_swag_foreach(process, simix_global->process_list) {
73       simdata_process_t p_simdata = (simdata_process_t) process->simdata;
74      // simdata_host_t h_simdata=(simdata_host_t)p_simdata->host->simdata;
75       char *who;
76         
77       asprintf(&who,"SIMIX:  %s on %s: %s",
78                process->name,
79                                  p_simdata->host->name,
80                (process->simdata->blocked)?"[blocked] "
81                :((process->simdata->suspended)?"[suspended] ":""));
82       
83       free(who);
84    }
85 }
86
87 /* FIXME: Yeah, I'll do it in a portable maner one day [Mt] */
88 #include <signal.h>
89
90 static void _XBT_CALL inthandler(int ignored)
91 {
92    INFO0("CTRL-C pressed. Displaying status and bailing out");
93    __SIMIX_display_process_status();
94    exit(1);
95 }
96
97 /** \ingroup msg_simulation
98  * \brief Launch the SIMIX simulation
99  */
100 SIMIX_error_t SIMIX_main(void)
101 {
102   smx_process_t process = NULL;
103   int i;
104   double elapsed_time = 0.0;
105   int state_modifications = 1;
106    
107   /* Prepare to display some more info when dying on Ctrl-C pressing */
108   signal(SIGINT,inthandler);
109    
110   /* Clean IO before the run */
111   fflush(stdout);
112   fflush(stderr);
113
114   surf_solve(); /* Takes traces into account. Returns 0.0 */
115 /* xbt_fifo_size(msg_global->process_to_run) */
116   while (1) {
117     xbt_context_empty_trash();
118     if(xbt_swag_size(simix_global->process_to_run) && (elapsed_time>0)) {
119       DEBUG0("**************************************************");
120     }
121     /*
122     if((__stop_at_time>0) && (SIMIX_get_clock() >= __stop_at_time)) {
123       DEBUG0("Let's stop here!");
124     }*/
125
126     while ((process = xbt_swag_extract(simix_global->process_to_run))) {
127       DEBUG2("Scheduling %s on %s",          
128              process->name,
129              process->simdata->host->name);
130       simix_global->current_process = process;
131 /*       fflush(NULL); */
132       xbt_context_schedule(process->simdata->context);
133       simix_global->current_process = NULL;
134     }
135     
136     {
137       surf_action_t action = NULL;
138       surf_resource_t resource = NULL;
139       //m_task_t task = NULL;
140
141       void *fun = NULL;
142       void *arg = NULL;
143
144       xbt_dynar_foreach(resource_list, i, resource) {
145         if(xbt_swag_size(resource->common_public->states.failed_action_set) ||
146            xbt_swag_size(resource->common_public->states.done_action_set))
147           state_modifications = 1;
148       }
149       
150       if(!state_modifications) {
151         DEBUG1("%f : Calling surf_solve",SIMIX_get_clock());
152         elapsed_time = surf_solve();
153         DEBUG1("Elapsed_time %f",elapsed_time);
154         
155         if (elapsed_time<0.0) {
156           /*       fprintf(stderr, "We're done %g\n",elapsed_time); */
157           break;
158         }
159       }
160
161       while (surf_timer_resource->extension_public->get(&fun,(void*)&arg)) {
162         DEBUG2("got %p %p", fun, arg);
163         if(fun==SIMIX_process_create_with_arguments) {
164           process_arg_t args = arg;
165           DEBUG2("Launching %s on %s", args->name, args->host->name);
166           process = SIMIX_process_create_with_arguments(args->name, args->code, 
167                                                       args->data, args->host,
168                                                       args->argc,args->argv);
169           if(args->kill_time > SIMIX_get_clock()) {
170             surf_timer_resource->extension_public->set(args->kill_time, 
171                                                        (void*) &SIMIX_process_kill,
172                                                        (void*) process);
173           }
174           xbt_free(args);
175         }
176         if(fun==SIMIX_process_kill) {
177           process = arg;
178           DEBUG2("Killing %s on %s", process->name, 
179                  process->simdata->host->name);
180           SIMIX_process_kill(process);
181         }
182       }
183       
184       xbt_dynar_foreach(resource_list, i, resource) {
185         while ((action =
186                 xbt_swag_extract(resource->common_public->states.
187                                  failed_action_set))) {
188                                  /*
189           task = action->data;
190           if(task) {
191             int _cursor;
192             DEBUG1("** %s failed **",task->name);
193             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
194               DEBUG3("\t preparing to wake up %s(%d) on %s",         
195                      process->name,process->simdata->PID,
196                      process->simdata->host->name);
197               xbt_fifo_unshift(msg_global->process_to_run, process);
198             }
199             process=NULL;
200           }*/
201         }
202         while ((action =
203                 xbt_swag_extract(resource->common_public->states.
204                                  done_action_set))) {
205           /*
206                 task = action->data;
207           if(task) {
208             int _cursor;
209             DEBUG1("** %s done **",task->name);
210             xbt_dynar_foreach(task->simdata->sleeping,_cursor,process) {
211               DEBUG3("\t preparing to wake up %s(%d) on %s",         
212                      process->name,process->simdata->PID,
213                      process->simdata->host->name);
214               xbt_fifo_unshift(msg_global->process_to_run, process);
215             }
216             process=NULL;
217           }*/
218         }
219       }
220     }
221     state_modifications = 0;
222   }
223
224   if (xbt_swag_size(simix_global->process_list) == 0) {
225     INFO0("Congratulations ! Simulation terminated : all processes are over");
226     return SIMIX_OK;
227   } else {
228     INFO0("Oops ! Deadlock or code not perfectly clean.");
229     __SIMIX_display_process_status();
230     if(XBT_LOG_ISENABLED(simix, xbt_log_priority_debug) ||
231        XBT_LOG_ISENABLED(simix_kernel, xbt_log_priority_debug)) {
232       DEBUG0("Aborting!");
233       xbt_abort();
234     }
235
236     INFO0("Return a Warning.");
237     return SIMIX_WARNING;
238   }
239 }
240
241 /** \ingroup msg_simulation
242  * \brief Kill all running process
243
244  * \param reset_PIDs should we reset the PID numbers. A negative
245  *   number means no reset and a positive number will be used to set the PID
246  *   of the next newly created process.
247  */
248 void SIMIX_process_killall()
249 {
250   smx_process_t p = NULL;
251   smx_process_t self = SIMIX_process_self();
252
253   while((p=xbt_swag_extract(simix_global->process_list))) {
254     if(p!=self) SIMIX_process_kill(p);
255   }
256
257   xbt_context_empty_trash();
258
259   if(self) {
260     xbt_context_yield();
261   }
262
263   return;
264 }
265
266 /** \ingroup msg_simulation
267  * \brief Clean the SIMIX simulation
268  */
269 SIMIX_error_t SIMIX_clean(void)
270 {
271   xbt_fifo_item_t i = NULL;
272   smx_host_t h = NULL;
273   smx_process_t p = NULL;
274
275
276   while((p=xbt_swag_extract(simix_global->process_list))) {
277     SIMIX_process_kill(p);
278   }
279   xbt_context_exit();
280
281   xbt_fifo_foreach(simix_global->host,i,h,smx_host_t) {
282     __SIMIX_host_destroy(h);
283   }
284   xbt_fifo_free(simix_global->host);
285   xbt_swag_free(simix_global->process_to_run);
286   xbt_swag_free(simix_global->process_list);
287   xbt_dict_free(&(simix_global->registered_functions));
288
289   simix_config_finalize();
290   free(simix_global);
291   surf_exit();
292
293   return SIMIX_OK;
294 }
295
296
297 /** \ingroup msg_easier_life
298  * \brief A clock (in second).
299  */
300 double SIMIX_get_clock(void) {
301   return surf_get_clock();
302 }