3 /* Copyright (c) 2007 Arnaud Legrand, Bruno Donnassolo.
4 All rights reserved. */
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. */
10 #include "xbt/sysdep.h"
12 #include "xbt/ex.h" /* ex_backtrace_display */
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_kernel, simix,
14 "Logging specific to SIMIX (kernel)");
16 //int __stop_at_time = -1.0 ;
18 SIMIX_Global_t simix_global = NULL;
20 /* static void MarkAsFailed(m_task_t t, TBX_HashTable_t failedProcessList); */
21 /* static xbt_fifo_t SIMIX_buildFailedHostList(double a, double b); */
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
30 /********************************* SIMIX **************************************/
32 /** \ingroup msg_simulation
33 * \brief Initialize some SIMIX internal data.
35 void SIMIX_global_init_args(int *argc, char **argv)
37 SIMIX_global_init(argc,argv);
40 /** \ingroup msg_simulation
41 * \brief Initialize some SIMIX internal data.
43 void SIMIX_global_init(int *argc, char **argv)
48 surf_init(argc, argv); /* Initialize some common structures. Warning, it sets msg_global=NULL */
50 simix_global = xbt_new0(s_SIMIX_Global_t,1);
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();
61 void __SIMIX_display_process_status(void)
63 smx_process_t process = NULL;
64 //xbt_fifo_item_t item = NULL;
66 int nbprocess=xbt_swag_size(simix_global->process_list);
68 INFO1("SIMIX: %d processes are still running, waiting for something.",
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;
77 asprintf(&who,"SIMIX: %s on %s: %s",
79 p_simdata->host->name,
80 (process->simdata->blocked)?"[blocked] "
81 :((process->simdata->suspended)?"[suspended] ":""));
87 /* FIXME: Yeah, I'll do it in a portable maner one day [Mt] */
90 static void _XBT_CALL inthandler(int ignored)
92 INFO0("CTRL-C pressed. Displaying status and bailing out");
93 __SIMIX_display_process_status();
97 /** \ingroup msg_simulation
98 * \brief Launch the SIMIX simulation
100 SIMIX_error_t SIMIX_main(void)
102 smx_process_t process = NULL;
104 double elapsed_time = 0.0;
105 int state_modifications = 1;
107 /* Prepare to display some more info when dying on Ctrl-C pressing */
108 signal(SIGINT,inthandler);
110 /* Clean IO before the run */
114 surf_solve(); /* Takes traces into account. Returns 0.0 */
115 /* xbt_fifo_size(msg_global->process_to_run) */
117 xbt_context_empty_trash();
118 if(xbt_swag_size(simix_global->process_to_run) && (elapsed_time>0)) {
119 DEBUG0("**************************************************");
122 if((__stop_at_time>0) && (SIMIX_get_clock() >= __stop_at_time)) {
123 DEBUG0("Let's stop here!");
126 while ((process = xbt_swag_extract(simix_global->process_to_run))) {
127 DEBUG2("Scheduling %s on %s",
129 process->simdata->host->name);
130 simix_global->current_process = process;
132 xbt_context_schedule(process->simdata->context);
133 simix_global->current_process = NULL;
137 surf_action_t action = NULL;
138 surf_resource_t resource = NULL;
139 //m_task_t task = NULL;
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;
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);
155 if (elapsed_time<0.0) {
156 /* fprintf(stderr, "We're done %g\n",elapsed_time); */
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,
176 if(fun==SIMIX_process_kill) {
178 DEBUG2("Killing %s on %s", process->name,
179 process->simdata->host->name);
180 SIMIX_process_kill(process);
184 xbt_dynar_foreach(resource_list, i, resource) {
186 xbt_swag_extract(resource->common_public->states.
187 failed_action_set))) {
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);
203 xbt_swag_extract(resource->common_public->states.
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);
221 state_modifications = 0;
224 if (xbt_swag_size(simix_global->process_list) == 0) {
225 INFO0("Congratulations ! Simulation terminated : all processes are over");
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)) {
236 INFO0("Return a Warning.");
237 return SIMIX_WARNING;
241 /** \ingroup msg_simulation
242 * \brief Kill all running process
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.
248 void SIMIX_process_killall()
250 smx_process_t p = NULL;
251 smx_process_t self = SIMIX_process_self();
253 while((p=xbt_swag_extract(simix_global->process_list))) {
254 if(p!=self) SIMIX_process_kill(p);
257 xbt_context_empty_trash();
266 /** \ingroup msg_simulation
267 * \brief Clean the SIMIX simulation
269 SIMIX_error_t SIMIX_clean(void)
271 xbt_fifo_item_t i = NULL;
273 smx_process_t p = NULL;
276 while((p=xbt_swag_extract(simix_global->process_list))) {
277 SIMIX_process_kill(p);
281 xbt_fifo_foreach(simix_global->host,i,h,smx_host_t) {
282 __SIMIX_host_destroy(h);
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));
289 simix_config_finalize();
297 /** \ingroup msg_easier_life
298 * \brief A clock (in second).
300 double SIMIX_get_clock(void) {
301 return surf_get_clock();