Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ddaddf77f2522b7d6ccd06678f8ebe55c343f348
[simgrid.git] / src / simdag / sd_global.cpp
1 /* Copyright (c) 2006-2016. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "src/surf/surf_interface.hpp"
8 #include "src/simdag/simdag_private.h"
9 #include "instr/instr_interface.h"
10 #include "xbt/sysdep.h"
11 #include "xbt/dynar.h"
12 #include "surf/surf.h"
13 #include "simgrid/sg_config.h"
14 #include "simgrid/host.h"
15 #include "xbt/ex.h"
16 #include "xbt/log.h"
17 #include "xbt/str.h"
18 #include "xbt/config.h"
19 #include "surf/surfxml_parse.h"
20 #ifdef HAVE_LUA
21 #include <lua.h>
22 #include <lauxlib.h>
23 #include <lualib.h>
24 #endif
25
26 #ifdef HAVE_JEDULE
27 #include "instr/jedule/jedule_sd_binding.h"
28 #endif
29
30 XBT_LOG_NEW_CATEGORY(sd, "Logging specific to SimDag");
31 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_kernel, sd,
32                                 "Logging specific to SimDag (kernel)");
33
34 SD_global_t sd_global = NULL;
35
36 /**
37  * \brief Initializes SD internal data
38  *
39  * This function must be called before any other SD function. Then you
40  * should call SD_create_environment().
41  *
42  * \param argc argument number
43  * \param argv argument list
44  * \see SD_create_environment(), SD_exit()
45  */
46 void SD_init(int *argc, char **argv)
47 {
48   TRACE_global_init(argc, argv);
49
50   s_SD_task_t task;
51
52   xbt_assert(sd_global == NULL, "SD_init() already called");
53
54   sd_global = xbt_new(s_SD_global_t, 1);
55   sd_global->workstation_list = NULL;
56   sd_global->link_list = NULL;
57   sd_global->recyclable_route = NULL;
58   sd_global->watch_point_reached = 0;
59
60   sd_global->task_mallocator=xbt_mallocator_new(65536, SD_task_new_f,
61                                                 SD_task_free_f,
62                                                 SD_task_recycle_f);
63
64   sd_global->initial_task_set = xbt_dynar_new(sizeof(SD_task_t), NULL);
65   sd_global->executable_task_set = xbt_dynar_new(sizeof(SD_task_t), NULL);
66   sd_global->completed_task_set = xbt_dynar_new(sizeof(SD_task_t), NULL);
67
68   sd_global->return_set =
69       xbt_swag_new(xbt_swag_offset(task, return_hookup));
70   sd_global->task_number = 0;
71
72   surf_init(argc, argv);
73
74   xbt_cfg_setdefault_string(_sg_cfg_set, "host/model",
75                             "ptask_L07");
76
77 #ifdef HAVE_JEDULE
78   jedule_sd_init();
79 #endif
80
81   XBT_DEBUG("ADD SD LEVELS");
82   SD_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,__SD_storage_destroy);
83
84   if (_sg_cfg_exit_asap) {
85     SD_exit();
86     exit(0);
87   }
88 }
89
90 /** \brief set a configuration variable
91  *
92  * Do --help on any simgrid binary to see the list of currently existing
93  * configuration variables, and see Section @ref options.
94  *
95  * Example:
96  * SD_config("host/model","default");
97  */
98 void SD_config(const char *key, const char *value){
99   xbt_assert(sd_global,"ERROR: Please call SD_init() before using SD_config()");
100   xbt_cfg_set_as_string(_sg_cfg_set, key, value);
101 }
102
103
104 /**
105  * \brief Reinits the application part of the simulation (experimental feature)
106  *
107  * This function allows you to run several simulations on the same platform
108  * by resetting the part describing the application.
109  *
110  * @warning: this function is still experimental and not perfect. For example,
111  * the simulation clock (and traces usage) is not reset. So, do not use it if
112  * you use traces in your simulation, and do not use absolute timing after
113  * using it.
114  * That being said, this function is still precious if you want to compare a
115  * bunch of heuristics on the same platforms.
116  */
117 void SD_application_reinit(void)
118 {
119
120 //  s_SD_task_t task;
121
122 //  SD_task_t done_task, next_done_task;
123   xbt_die("This function is not working since the C++ links and others. Please report the problem if you really need that function.");
124
125    XBT_DEBUG("Recreating the swags...");
126
127 //  xbt_swag_foreach_safe(done_task, next_done_task, sd_global->done_task_set){
128 //    if (xbt_dynar_is_empty(done_task->tasks_before)){
129 //      __SD_task_set_state(done_task, SD_SCHEDULABLE);
130 //    } else{
131 //      __SD_task_set_state(done_task, SD_NOT_SCHEDULED);
132 //      done_task->unsatisfied_dependencies =
133 //        xbt_dynar_length(done_task->tasks_before);
134 //      done_task->is_not_ready = done_task->unsatisfied_dependencies;
135 //    }
136 //    free(done_task->workstation_list);
137 //    done_task->workstation_list = NULL;
138 //    done_task->workstation_nb = 0;
139 //  }
140
141   sd_global->task_number = 0;
142
143
144 #ifdef HAVE_JEDULE
145   jedule_sd_dump();
146   jedule_sd_cleanup();
147   jedule_sd_init();
148 #endif
149 }
150
151 /**
152  * \brief Creates the environment
153  *
154  * The environment (i.e. the \ref SD_workstation_management "workstations"
155  * and the \ref SD_link_management "links") is created with the data stored
156  * in the given XML platform file.
157  *
158  * \param platform_file name of an XML file describing the environment to create
159  * \see SD_workstation_management, SD_link_management
160  *
161  * The XML file follows this DTD:
162  *
163  *     \include simgrid.dtd
164  *
165  * Here is a small example of such a platform:
166  *
167  *     \include small_platform.xml
168  */
169 void SD_create_environment(const char *platform_file)
170 {
171   xbt_lib_cursor_t cursor = NULL;
172   char *name = NULL;
173   void **surf_storage = NULL;
174
175   parse_platform_file(platform_file);
176
177   /* now let's create the SD wrappers for workstations, storages and links */
178   {
179     xbt_dict_cursor_t cursor = NULL;
180     simgrid_Host* host = NULL;
181     xbt_dict_foreach(host_list, cursor, name, host){
182         __SD_workstation_create((const char*)name);
183     }
184   }
185
186   xbt_lib_foreach(storage_lib, cursor, name, surf_storage) {
187   if(surf_storage[SURF_STORAGE_LEVEL])
188     __SD_storage_create(surf_storage[SURF_STORAGE_LEVEL], NULL);
189   }
190
191
192   XBT_DEBUG("Workstation number: %d, link number: %d",
193          SD_workstation_get_number(), SD_link_get_number());
194 #ifdef HAVE_JEDULE
195   jedule_setup_platform();
196 #endif
197 }
198
199 /**
200  * \brief Launches the simulation.
201  *
202  * The function will execute the \ref SD_RUNNABLE runnable tasks.
203  * If \a how_long is positive, then the simulation will be stopped either
204  * when time reaches \a how_long or when a watch point is reached.
205  * A non-positive value for \a how_long means no time limit, in which case
206  * the simulation will be stopped either when a watch point is reached or
207  * when no more task can be executed.
208  * Then you can call SD_simulate() again.
209  *
210  * \param how_long maximum duration of the simulation (a negative value means
211  * no time limit)
212  * \return a dynar of \ref SD_task_t whose state has changed.
213  * \see SD_task_schedule(), SD_task_watch()
214  */
215
216 xbt_dynar_t SD_simulate(double how_long) {
217   xbt_dynar_t changed_tasks = xbt_dynar_new(sizeof(SD_task_t), NULL);
218   SD_task_t task;
219
220   SD_simulate_swag(how_long);
221   while( (task = (SD_task_t)xbt_swag_extract(sd_global->return_set)) != NULL) {
222     xbt_dynar_push(changed_tasks, &task);
223   }
224
225   return changed_tasks;
226 }
227
228 xbt_swag_t SD_simulate_swag(double how_long) {
229   /* we stop the simulation when total_time >= how_long */
230   double total_time = 0.0;
231   double elapsed_time = 0.0;
232   SD_task_t task, dst;
233   SD_dependency_t dependency;
234   surf_action_t action;
235   unsigned int iter, depcnt;
236   static int first_time = 1;
237
238   if (first_time) {
239     XBT_VERB("Starting simulation...");
240
241     surf_presolve();            /* Takes traces into account */
242     first_time = 0;
243   }
244
245   XBT_VERB("Run simulation for %f seconds", how_long);
246   sd_global->watch_point_reached = 0;
247
248   xbt_swag_reset(sd_global->return_set);
249
250   /* explore the runnable tasks */
251   xbt_dynar_foreach(sd_global->executable_task_set , iter, task) {
252     XBT_VERB("Executing task '%s'", SD_task_get_name(task));
253     if (__SD_task_try_to_run(task)){
254       xbt_swag_insert(task,sd_global->return_set);
255       iter--;
256     }
257   }
258
259   /* main loop */
260   elapsed_time = 0.0;
261   while (elapsed_time >= 0.0 &&
262          (how_long < 0.0 || 0.00001 < (how_long -total_time)) &&
263          !sd_global->watch_point_reached) {
264     surf_model_t model = NULL;
265     /* dumb variables */
266
267
268     XBT_DEBUG("Total time: %f", total_time);
269
270     elapsed_time = surf_solve(how_long > 0 ? surf_get_clock() + how_long - total_time: -1.0);
271     XBT_DEBUG("surf_solve() returns %f", elapsed_time);
272     if (elapsed_time > 0.0)
273       total_time += elapsed_time;
274
275     /* let's see which tasks are done */
276     xbt_dynar_foreach(all_existing_models, iter, model) {
277       while ((action = surf_model_extract_done_action_set(model))) {
278         task = (SD_task_t) action->getData();
279         task->start_time = task->surf_action->getStartTime();
280
281         task->finish_time = surf_get_clock();
282         XBT_VERB("Task '%s' done", SD_task_get_name(task));
283         XBT_DEBUG("Calling __SD_task_just_done");
284         __SD_task_just_done(task);
285         XBT_DEBUG("__SD_task_just_done called on task '%s'",
286                SD_task_get_name(task));
287
288         /* the state has changed */
289         XBT_INFO("%d",xbt_swag_belongs(task, sd_global->return_set));
290         xbt_swag_insert(task,sd_global->return_set);
291
292         /* remove the dependencies after this task */
293         xbt_dynar_foreach(task->tasks_after, depcnt, dependency) {
294           dst = dependency->dst;
295           if (dst->unsatisfied_dependencies > 0)
296             dst->unsatisfied_dependencies--;
297           if (dst->is_not_ready > 0)
298             dst->is_not_ready--;
299
300           XBT_DEBUG("Released a dependency on %s: %d remain(s). Became schedulable if %d=0",
301              SD_task_get_name(dst), dst->unsatisfied_dependencies,
302              dst->is_not_ready);
303
304           if (!(dst->unsatisfied_dependencies)) {
305             if (SD_task_get_state(dst) == SD_SCHEDULED)
306               SD_task_set_state(dst, SD_RUNNABLE);
307             else
308               SD_task_set_state(dst, SD_SCHEDULABLE);
309           }
310
311           if (SD_task_get_state(dst) == SD_NOT_SCHEDULED &&
312               !(dst->is_not_ready)) {
313             SD_task_set_state(dst, SD_SCHEDULABLE);
314           }
315
316           if (SD_task_get_kind(dst) == SD_TASK_COMM_E2E) {
317             SD_dependency_t comm_dep;
318             SD_task_t comm_dst;
319             xbt_dynar_get_cpy(dst->tasks_after, 0, &comm_dep);
320             comm_dst = comm_dep->dst;
321             if (SD_task_get_state(comm_dst) == SD_NOT_SCHEDULED &&
322                 comm_dst->is_not_ready > 0) {
323               comm_dst->is_not_ready--;
324
325             XBT_DEBUG("%s is a transfer, %s may be ready now if %d=0",
326                SD_task_get_name(dst), SD_task_get_name(comm_dst),
327                comm_dst->is_not_ready);
328
329               if (!(comm_dst->is_not_ready)) {
330                 SD_task_set_state(comm_dst, SD_SCHEDULABLE);
331               }
332             }
333           }
334
335           /* is dst runnable now? */
336           if (SD_task_get_state(dst) == SD_RUNNABLE
337               && !sd_global->watch_point_reached) {
338             XBT_VERB("Executing task '%s'", SD_task_get_name(dst));
339             if (__SD_task_try_to_run(dst))
340               xbt_swag_insert(dst,sd_global->return_set);
341           }
342         }
343       }
344
345       /* let's see which tasks have just failed */
346       while ((action = surf_model_extract_failed_action_set(model))) {
347         task = (SD_task_t) action->getData();
348         task->start_time = surf_action_get_start_time(task->surf_action);
349         task->finish_time = surf_get_clock();
350         XBT_VERB("Task '%s' failed", SD_task_get_name(task));
351         SD_task_set_state(task, SD_FAILED);
352         action->unref();
353         task->surf_action = NULL;
354
355         xbt_swag_insert(task,sd_global->return_set);
356       }
357     }
358   }
359
360   if (!sd_global->watch_point_reached && how_long<0){
361     if ((int) xbt_dynar_length(sd_global->completed_task_set) <
362          sd_global->task_number){
363         XBT_WARN("Simulation is finished but %d tasks are still not done",
364             (sd_global->task_number -
365              (int) xbt_dynar_length(sd_global->completed_task_set)));
366         static const char* state_names[] =
367               { "SD_NOT_SCHEDULED", "SD_SCHEDULABLE", "SD_SCHEDULED",
368                 "SD_RUNNABLE", "SD_IN_INFO", "SD_RUNNING", "SD_DONE",
369                 "SD_FAILED" };
370         xbt_dynar_foreach(sd_global->initial_task_set, iter, task){
371           XBT_WARN("%s is in %s state", SD_task_get_name(task),
372                    state_names[SD_task_get_state(task)]);
373         }
374     }
375   }
376
377   XBT_DEBUG("elapsed_time = %f, total_time = %f, watch_point_reached = %d",
378          elapsed_time, total_time, sd_global->watch_point_reached);
379   XBT_DEBUG("current time = %f", surf_get_clock());
380
381   return sd_global->return_set;
382 }
383
384 /**
385  * \brief Returns the current clock
386  *
387  * \return the current clock, in second
388  */
389 double SD_get_clock(void) {
390   return surf_get_clock();
391 }
392
393 /**
394  * \brief Destroys all SD internal data
395  *
396  * This function should be called when the simulation is over. Don't forget
397  * to destroy too.
398  *
399  * \see SD_init(), SD_task_destroy()
400  */
401 void SD_exit(void)
402 {
403   TRACE_surf_resource_utilization_release();
404
405   xbt_mallocator_free(sd_global->task_mallocator);
406
407   XBT_DEBUG("Destroying workstation and link arrays...");
408   xbt_free(sd_global->workstation_list);
409   xbt_free(sd_global->link_list);
410   xbt_free(sd_global->recyclable_route);
411
412   XBT_DEBUG("Destroying the dynars and swags...");
413   xbt_dynar_free_container(&(sd_global->initial_task_set));
414   xbt_dynar_free_container(&(sd_global->executable_task_set));
415   xbt_dynar_free_container(&(sd_global->completed_task_set));
416   xbt_swag_free(sd_global->return_set);
417
418   TRACE_end();
419
420   xbt_free(sd_global);
421   sd_global = NULL;
422
423 #ifdef HAVE_JEDULE
424   jedule_sd_dump();
425   jedule_sd_cleanup();
426   jedule_sd_exit();
427 #endif
428
429   XBT_DEBUG("Exiting Surf...");
430   surf_exit();
431 }