Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Declare all variables at the begining for ANSI C standard compatibility.
[simgrid.git] / src / simdag / sd_global.c
1 #include "private.h"
2 #include "xbt/sysdep.h"
3 #include "xbt/dynar.h"
4 #include "surf/surf.h"
5
6 XBT_LOG_NEW_CATEGORY(sd,"Logging specific to SimDag");
7 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_kernel,sd,
8                                 "Logging specific to SimDag (kernel)");
9
10 SD_global_t sd_global = NULL;
11
12 /**
13  * \brief Initialises SD internal data
14  *
15  * This function must be called before any other SD function. Then you
16  * should call SD_create_environment().
17  *
18  * \param argc argument number
19  * \param argv argument list
20  * \see SD_create_environment(), SD_exit()
21  */
22 void SD_init(int *argc, char **argv) {
23
24   s_SD_task_t task;
25   
26   if (SD_INITIALISED()) {
27     xbt_assert0(0, "SD_init() already called");
28   }
29
30   sd_global = xbt_new(s_SD_global_t, 1);
31   sd_global->workstations = xbt_dict_new();
32   sd_global->workstation_count = 0;
33   sd_global->workstation_list = NULL;
34   sd_global->links = xbt_dict_new();
35   sd_global->link_count = 0;
36   sd_global->link_list = NULL;
37   sd_global->recyclable_route = NULL;
38   sd_global->watch_point_reached = 0;
39
40   sd_global->not_scheduled_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
41   sd_global->scheduled_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
42   sd_global->ready_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
43   sd_global->in_fifo_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
44   sd_global->running_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
45   sd_global->done_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
46   sd_global->failed_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
47   sd_global->task_number = 0;
48
49   surf_init(argc, argv);
50 }
51
52 /**
53  * \brief Creates the environment
54  *
55  * The environment (i.e. the \ref SD_workstation_management "workstations" and the
56  * \ref SD_link_management "links") is created with the data stored in the given XML
57  * platform file.
58  *
59  * \param platform_file name of an XML file describing the environment to create
60  * \see SD_workstation_management, SD_link_management
61  *
62  * The XML file follows this DTD:
63  *
64  *     \include surfxml.dtd
65  *
66  * Here is a small example of such a platform: 
67  *
68  *     \include small_platform.xml
69  */
70 void SD_create_environment(const char *platform_file) {
71   xbt_dict_cursor_t cursor = NULL;
72   char *name = NULL;
73   void *surf_workstation = NULL;
74   void *surf_link = NULL;
75
76   SD_CHECK_INIT_DONE();
77
78   DEBUG0("SD_create_environment");
79
80   surf_timer_resource_init(platform_file);  /* tell Surf to create the environnement */
81
82   DEBUG0("Calling surf_workstation_resource_init");
83   surf_workstation_resource_init_KCCFLN05(platform_file);
84   /*  surf_workstation_resource_init_CLM03(platform_file); */
85
86   /* now let's create the SD wrappers for workstations and links */
87   DEBUG0("Creating SimDags hosts and links");
88   xbt_dict_foreach(workstation_set, cursor, name, surf_workstation) {
89     __SD_workstation_create(surf_workstation, NULL);
90   }
91
92   xbt_dict_foreach(network_link_set, cursor, name, surf_link) {
93     __SD_link_create(surf_link, NULL);
94   }
95
96   DEBUG2("Workstation number: %d, link number: %d", SD_workstation_get_number(), SD_link_get_number());
97 }
98
99 /**
100  * \brief Launches the simulation.
101  *
102  * The function will execute the \ref SD_READY ready tasks.
103  * The simulation will be stopped when its time reaches \a how_long,
104  * when a watch point is reached, or when no more task can be executed.
105  * Then you can call SD_simulate() again.
106  * 
107  * \param how_long maximum duration of the simulation (a negative value means no time limit)
108  * \return a NULL-terminated array of \ref SD_task_t whose state has changed.
109  * \see SD_task_schedule(), SD_task_watch()
110  */
111 SD_task_t* SD_simulate(double how_long)
112 {
113   double total_time = 0.0; /* we stop the simulation when total_time >= how_long */
114   double elapsed_time = 0.0;
115   SD_task_t task, dst;
116   SD_dependency_t dependency;
117   surf_action_t action;
118   SD_task_t *changed_tasks = NULL;
119   int changed_task_number = 0;
120   int changed_task_capacity = sd_global->task_number + 1;
121   int i;
122   static int first_time = 1;
123
124   SD_CHECK_INIT_DONE();
125
126   INFO0("Starting simulation...");
127
128   /* create the array that will be returned */
129   changed_tasks = xbt_new(SD_task_t, changed_task_capacity);
130   changed_tasks[0] = NULL;
131
132   if (first_time) {
133     surf_solve(); /* Takes traces into account. Returns 0.0 */
134     first_time = 0;
135   }
136
137   sd_global->watch_point_reached = 0;
138
139   /* explore the ready tasks */
140   xbt_swag_foreach(task, sd_global->ready_task_set) {
141     INFO1("Executing task '%s'", SD_task_get_name(task));
142     if ((task->state_changed = __SD_task_try_to_run(task))) {
143       changed_tasks[changed_task_number++] = task; /* replace NULL by the task */
144       /*
145       if (changed_task_number == changed_task_capacity) {
146         changed_task_capacity *= 2;
147         changed_tasks = xbt_realloc(changed_tasks, sizeof(SD_task_t) * changed_task_capacity);
148       }
149       */
150       changed_tasks[changed_task_number] = NULL;
151     }
152   }
153
154   /* main loop */
155   elapsed_time = 0.0;
156   while (elapsed_time >= 0.0 &&
157          (how_long < 0.0 || total_time < how_long) &&
158          !sd_global->watch_point_reached) {
159
160     DEBUG1("Total time: %f", total_time);
161
162     elapsed_time = surf_solve();
163     DEBUG1("surf_solve() returns %f", elapsed_time);
164     if (elapsed_time > 0.0)
165       total_time += elapsed_time;
166
167     /* let's see which tasks are done */
168     while ((action = xbt_swag_extract(surf_workstation_resource->common_public->states.done_action_set))) {
169       task = action->data;
170       INFO1("Task '%s' done", SD_task_get_name(task));
171       DEBUG0("Calling __SD_task_just_done");
172       __SD_task_just_done(task);
173       DEBUG1("__SD_task_just_done called on task '%s'", SD_task_get_name(task));
174
175       /* the state has changed */
176       if (!task->state_changed) {
177         task->state_changed = 1;
178         changed_tasks[changed_task_number++] = task;
179         /*
180         if (changed_task_number == changed_task_capacity) {
181           changed_task_capacity *= 2;
182           changed_tasks = xbt_realloc(changed_tasks, sizeof(SD_task_t) * changed_task_capacity);
183         }
184         */
185         changed_tasks[changed_task_number] = NULL;
186       }
187
188       /* remove the dependencies after this task */
189       while (xbt_dynar_length(task->tasks_after) > 0) {
190         xbt_dynar_get_cpy(task->tasks_after, 0, &dependency);
191         dst = dependency->dst;
192         SD_task_dependency_remove(task, dst);
193         
194         /* is dst ready now? */
195         if (__SD_task_is_ready(dst) && !sd_global->watch_point_reached) {
196           INFO1("Executing task '%s'", SD_task_get_name(dst));
197           if (__SD_task_try_to_run(dst)) {
198             changed_tasks[changed_task_number++] = dst;
199             /*
200             if (changed_task_number == changed_task_capacity) {
201               changed_task_capacity *= 2;
202               changed_tasks = xbt_realloc(changed_tasks, sizeof(SD_task_t) * changed_task_capacity);
203             }
204             */
205             changed_tasks[changed_task_number] = NULL;
206           }
207         }
208       }
209     }
210
211     /* let's see which tasks have just failed */
212     while ((action = xbt_swag_extract(surf_workstation_resource->common_public->states.failed_action_set))) {
213       task = action->data;
214       INFO1("Task '%s' failed", SD_task_get_name(task));
215       __SD_task_set_state(task, SD_FAILED);
216       surf_workstation_resource->common_public->action_free(action);
217       task->surf_action = NULL;
218
219       if (!task->state_changed) {
220         task->state_changed = 1;
221         changed_tasks[changed_task_number++] = task;
222         /*
223         if (changed_task_number == changed_task_capacity) {
224           changed_task_capacity *= 2;
225           changed_tasks = xbt_realloc(changed_tasks, sizeof(SD_task_t) * changed_task_capacity);
226         }
227         */
228         changed_tasks[changed_task_number] = NULL;
229       }
230     }
231   }
232
233   /* we must reset every task->state_changed */
234   i = 0;
235   while (changed_tasks[i] != NULL) {
236     changed_tasks[i]->state_changed = 0;
237     i++;
238   }
239
240   INFO0("Simulation finished");
241   DEBUG3("elapsed_time = %f, total_time = %f, watch_point_reached = %d", elapsed_time, total_time, sd_global->watch_point_reached);
242   DEBUG1("current time = %f", surf_get_clock());
243
244   return changed_tasks;
245 }
246
247 /**
248  * \brief Returns the current clock
249  *
250  * \return the current clock, in second
251  */
252 double SD_get_clock(void) {
253   SD_CHECK_INIT_DONE();
254
255   return surf_get_clock();
256 }
257
258 /**
259  * \brief Destroys all SD internal data
260  *
261  * This function should be called when the simulation is over. Don't forget also to destroy
262  * the tasks.
263  *
264  * \see SD_init(), SD_task_destroy()
265  */
266 void SD_exit(void) {
267   if (SD_INITIALISED()) {
268     DEBUG0("Destroying workstation and link dictionaries...");
269     xbt_dict_free(&sd_global->workstations);
270     xbt_dict_free(&sd_global->links);
271
272     DEBUG0("Destroying workstation and link arrays if necessary...");
273     if (sd_global->workstation_list != NULL)
274       xbt_free(sd_global->workstation_list);
275
276     if (sd_global->link_list != NULL)
277       xbt_free(sd_global->link_list);
278
279     if (sd_global->recyclable_route != NULL)
280       xbt_free(sd_global->recyclable_route);
281
282     DEBUG0("Destroying the swags...");
283     xbt_swag_free(sd_global->not_scheduled_task_set);
284     xbt_swag_free(sd_global->scheduled_task_set);
285     xbt_swag_free(sd_global->ready_task_set);
286     xbt_swag_free(sd_global->in_fifo_task_set);
287     xbt_swag_free(sd_global->running_task_set);
288     xbt_swag_free(sd_global->done_task_set);
289     xbt_swag_free(sd_global->failed_task_set);
290
291     xbt_free(sd_global);
292     sd_global = NULL;
293
294     DEBUG0("Exiting Surf...");
295     surf_exit();
296   }
297   else {
298     fprintf(stderr, "Warning: SD_exit() called while SimDag was not running\n");
299     /* we cannot use exceptions here because xbt is not running! */
300   }
301 }