Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Simplify the code of typed tasks in simdag by allocating the comm_ and comp_amount...
[simgrid.git] / src / simdag / sd_global.c
1 /* Copyright (c) 2007-2009 Da SimGrid Team.  All rights reserved.           */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "private.h"
7 #include "xbt/sysdep.h"
8 #include "xbt/dynar.h"
9 #include "surf/surf.h"
10 #include "xbt/ex.h"
11 #include "xbt/log.h"
12 #include "xbt/str.h"
13 #include "xbt/config.h"
14
15 XBT_LOG_NEW_CATEGORY(sd, "Logging specific to SimDag");
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_kernel, sd,
17                                 "Logging specific to SimDag (kernel)");
18
19 SD_global_t sd_global = NULL;
20
21 XBT_LOG_EXTERNAL_CATEGORY(sd_kernel);
22 XBT_LOG_EXTERNAL_CATEGORY(sd_task);
23 XBT_LOG_EXTERNAL_CATEGORY(sd_workstation);
24
25 /**
26  * \brief Initialises SD internal data
27  *
28  * This function must be called before any other SD function. Then you
29  * should call SD_create_environment().
30  *
31  * \param argc argument number
32  * \param argv argument list
33  * \see SD_create_environment(), SD_exit()
34  */
35 void SD_init(int *argc, char **argv)
36 {
37
38   s_SD_task_t task;
39
40   xbt_assert0(!SD_INITIALISED(), "SD_init() already called");
41
42   /* Connect our log channels: that must be done manually under windows */
43   XBT_LOG_CONNECT(sd_kernel, sd);
44   XBT_LOG_CONNECT(sd_task, sd);
45   XBT_LOG_CONNECT(sd_workstation, sd);
46
47
48   sd_global = xbt_new(s_SD_global_t, 1);
49   sd_global->workstations = xbt_dict_new();
50   sd_global->workstation_count = 0;
51   sd_global->workstation_list = NULL;
52   sd_global->links = xbt_dict_new();
53   sd_global->link_count = 0;
54   sd_global->link_list = NULL;
55   sd_global->recyclable_route = NULL;
56   sd_global->watch_point_reached = 0;
57
58   sd_global->not_scheduled_task_set =
59     xbt_swag_new(xbt_swag_offset(task, state_hookup));
60   sd_global->scheduled_task_set =
61     xbt_swag_new(xbt_swag_offset(task, state_hookup));
62   sd_global->ready_task_set =
63     xbt_swag_new(xbt_swag_offset(task, state_hookup));
64   sd_global->in_fifo_task_set =
65     xbt_swag_new(xbt_swag_offset(task, state_hookup));
66   sd_global->running_task_set =
67     xbt_swag_new(xbt_swag_offset(task, state_hookup));
68   sd_global->done_task_set =
69     xbt_swag_new(xbt_swag_offset(task, state_hookup));
70   sd_global->failed_task_set =
71     xbt_swag_new(xbt_swag_offset(task, state_hookup));
72   sd_global->task_number = 0;
73
74   surf_init(argc, argv);
75   xbt_cfg_set_string(_surf_cfg_set, "workstation_model", "ptask_L07");
76 }
77
78 /**
79  * \brief Reinits the application part of the simulation (experimental feature)
80  *
81  * This function allows you to run several simulations on the same platform
82  * by resetting the part describing the application.
83  *
84  * @warning: this function is still experimental and not perfect. For example,
85  * the simulation clock (and traces usage) is not reset. So, do not use it if
86  * you use traces in your simulation, and do not use absolute timing after using it.
87  * That being said, this function is still precious if you want to compare a bunch of
88  * heuristics on the same platforms.
89  */
90 void SD_application_reinit(void)
91 {
92
93   s_SD_task_t task;
94
95   if (SD_INITIALISED()) {
96     DEBUG0("Recreating the swags...");
97     xbt_swag_free(sd_global->not_scheduled_task_set);
98     xbt_swag_free(sd_global->scheduled_task_set);
99     xbt_swag_free(sd_global->ready_task_set);
100     xbt_swag_free(sd_global->in_fifo_task_set);
101     xbt_swag_free(sd_global->running_task_set);
102     xbt_swag_free(sd_global->done_task_set);
103     xbt_swag_free(sd_global->failed_task_set);
104
105     sd_global->not_scheduled_task_set =
106       xbt_swag_new(xbt_swag_offset(task, state_hookup));
107     sd_global->scheduled_task_set =
108       xbt_swag_new(xbt_swag_offset(task, state_hookup));
109     sd_global->ready_task_set =
110       xbt_swag_new(xbt_swag_offset(task, state_hookup));
111     sd_global->in_fifo_task_set =
112       xbt_swag_new(xbt_swag_offset(task, state_hookup));
113     sd_global->running_task_set =
114       xbt_swag_new(xbt_swag_offset(task, state_hookup));
115     sd_global->done_task_set =
116       xbt_swag_new(xbt_swag_offset(task, state_hookup));
117     sd_global->failed_task_set =
118       xbt_swag_new(xbt_swag_offset(task, state_hookup));
119     sd_global->task_number = 0;
120   } else {
121     WARN0("SD_application_reinit called before initialization of SimDag");
122     /* we cannot use exceptions here because xbt is not running! */
123   }
124
125 }
126
127 /**
128  * \brief Creates the environment
129  *
130  * The environment (i.e. the \ref SD_workstation_management "workstations" and the
131  * \ref SD_link_management "links") is created with the data stored in the given XML
132  * platform file.
133  *
134  * \param platform_file name of an XML file describing the environment to create
135  * \see SD_workstation_management, SD_link_management
136  *
137  * The XML file follows this DTD:
138  *
139  *     \include simgrid.dtd
140  *
141  * Here is a small example of such a platform:
142  *
143  *     \include small_platform.xml
144  */
145 void SD_create_environment(const char *platform_file)
146 {
147   xbt_dict_cursor_t cursor = NULL;
148   char *name = NULL;
149   void *surf_workstation = NULL;
150   void *surf_link = NULL;
151
152   SD_CHECK_INIT_DONE();
153
154   DEBUG0("SD_create_environment");
155
156   surf_config_models_setup(platform_file);
157
158   parse_platform_file(platform_file);
159
160   /* now let's create the SD wrappers for workstations and links */
161   xbt_dict_foreach(surf_model_resource_set(surf_workstation_model), cursor,
162                    name, surf_workstation) {
163     __SD_workstation_create(surf_workstation, NULL);
164   }
165
166   xbt_dict_foreach(surf_model_resource_set(surf_network_model), cursor, name, surf_link) {
167     __SD_link_create(surf_link, NULL);
168   }
169
170   DEBUG2("Workstation number: %d, link number: %d",
171          SD_workstation_get_number(), SD_link_get_number());
172 }
173
174 /**
175  * \brief Launches the simulation.
176  *
177  * The function will execute the \ref SD_READY ready tasks.
178  * The simulation will be stopped when its time reaches \a how_long,
179  * when a watch point is reached, or when no more task can be executed.
180  * Then you can call SD_simulate() again.
181  *
182  * \param how_long maximum duration of the simulation (a negative value means no time limit)
183  * \return a NULL-terminated array of \ref SD_task_t whose state has changed.
184  * \see SD_task_schedule(), SD_task_watch()
185  */
186 SD_task_t *SD_simulate(double how_long)
187 {
188   double total_time = 0.0;      /* we stop the simulation when total_time >= how_long */
189   double elapsed_time = 0.0;
190   SD_task_t task, task_safe, dst;
191   SD_dependency_t dependency;
192   surf_action_t action;
193   SD_task_t *res = NULL;
194   xbt_dynar_t changed_tasks = xbt_dynar_new(sizeof(SD_task_t), NULL);
195   unsigned int iter;
196   static int first_time = 1;
197
198   SD_CHECK_INIT_DONE();
199
200   INFO0("Starting simulation...");
201
202   if (first_time) {
203     surf_presolve();            /* Takes traces into account */
204     first_time = 0;
205   }
206
207   if (how_long > 0) {
208     surf_timer_model->extension.timer.set(surf_get_clock() + how_long,
209                                           NULL, NULL);
210   }
211   sd_global->watch_point_reached = 0;
212
213   /* explore the ready tasks */
214   xbt_swag_foreach_safe(task, task_safe, sd_global->ready_task_set) {
215     INFO1("Executing task '%s'", SD_task_get_name(task));
216     if (__SD_task_try_to_run(task) && !xbt_dynar_member(changed_tasks, &task))
217       xbt_dynar_push(changed_tasks, &task);
218   }
219
220   /* main loop */
221   elapsed_time = 0.0;
222   while (elapsed_time >= 0.0 &&
223          (how_long < 0.0 || total_time < how_long) &&
224          !sd_global->watch_point_reached) {
225     surf_model_t model = NULL;
226     /* dumb variables */
227     void *fun = NULL;
228     void *arg = NULL;
229
230
231     DEBUG1("Total time: %f", total_time);
232
233     elapsed_time = surf_solve();
234     DEBUG1("surf_solve() returns %f", elapsed_time);
235     if (elapsed_time > 0.0)
236       total_time += elapsed_time;
237
238     /* let's see which tasks are done */
239     xbt_dynar_foreach(model_list, iter, model) {
240       while ((action = xbt_swag_extract(model->states.done_action_set))) {
241         task = action->data;
242         INFO1("Task '%s' done", SD_task_get_name(task));
243         DEBUG0("Calling __SD_task_just_done");
244         __SD_task_just_done(task);
245         DEBUG1("__SD_task_just_done called on task '%s'",
246                SD_task_get_name(task));
247
248         /* the state has changed */
249         if (!xbt_dynar_member(changed_tasks, &task))
250           xbt_dynar_push(changed_tasks, &task);
251
252         /* remove the dependencies after this task */
253         while (xbt_dynar_length(task->tasks_after) > 0) {
254           xbt_dynar_get_cpy(task->tasks_after, 0, &dependency);
255           dst = dependency->dst;
256           SD_task_dependency_remove(task, dst);
257
258           /* is dst ready now? */
259           if (__SD_task_is_ready(dst) && !sd_global->watch_point_reached) {
260             INFO1("Executing task '%s'", SD_task_get_name(dst));
261             if (__SD_task_try_to_run(dst) &&
262                 !xbt_dynar_member(changed_tasks, &task))
263               xbt_dynar_push(changed_tasks, &task);
264           }
265         }
266       }
267
268       /* let's see which tasks have just failed */
269       while ((action = xbt_swag_extract(model->states.failed_action_set))) {
270         task = action->data;
271         INFO1("Task '%s' failed", SD_task_get_name(task));
272         __SD_task_set_state(task, SD_FAILED);
273         surf_workstation_model->action_unref(action);
274         task->surf_action = NULL;
275
276         if (!xbt_dynar_member(changed_tasks, &task))
277           xbt_dynar_push(changed_tasks, &task);
278       }
279     }
280
281     while (surf_timer_model->extension.timer.get(&fun, (void *) &arg)) {
282     }
283   }
284
285   res = xbt_new0(SD_task_t, (xbt_dynar_length(changed_tasks) + 1));
286
287   xbt_dynar_foreach(changed_tasks, iter, task) {
288     res[iter] = task;
289   }
290   xbt_dynar_free(&changed_tasks);
291
292   INFO0("Simulation finished");
293   DEBUG3("elapsed_time = %f, total_time = %f, watch_point_reached = %d",
294          elapsed_time, total_time, sd_global->watch_point_reached);
295   DEBUG1("current time = %f", surf_get_clock());
296
297   return res;
298 }
299
300 /**
301  * \brief Returns the current clock
302  *
303  * \return the current clock, in second
304  */
305 double SD_get_clock(void)
306 {
307   SD_CHECK_INIT_DONE();
308
309   return surf_get_clock();
310 }
311
312 /**
313  * \brief Destroys all SD internal data
314  *
315  * This function should be called when the simulation is over. Don't forget also to destroy
316  * the tasks.
317  *
318  * \see SD_init(), SD_task_destroy()
319  */
320 void SD_exit(void)
321 {
322   if (SD_INITIALISED()) {
323     DEBUG0("Destroying workstation and link dictionaries...");
324     xbt_dict_free(&sd_global->workstations);
325     xbt_dict_free(&sd_global->links);
326
327     DEBUG0("Destroying workstation and link arrays if necessary...");
328     if (sd_global->workstation_list != NULL)
329       xbt_free(sd_global->workstation_list);
330
331     if (sd_global->link_list != NULL)
332       xbt_free(sd_global->link_list);
333
334     if (sd_global->recyclable_route != NULL)
335       xbt_free(sd_global->recyclable_route);
336
337     DEBUG0("Destroying the swags...");
338     xbt_swag_free(sd_global->not_scheduled_task_set);
339     xbt_swag_free(sd_global->scheduled_task_set);
340     xbt_swag_free(sd_global->ready_task_set);
341     xbt_swag_free(sd_global->in_fifo_task_set);
342     xbt_swag_free(sd_global->running_task_set);
343     xbt_swag_free(sd_global->done_task_set);
344     xbt_swag_free(sd_global->failed_task_set);
345
346     xbt_free(sd_global);
347     sd_global = NULL;
348
349     DEBUG0("Exiting Surf...");
350     surf_exit();
351   } else {
352     WARN0("SD_exit() called, but SimDag is not running");
353     /* we cannot use exceptions here because xbt is not running! */
354   }
355 }