1 /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011. The SimGrid Team.
2 * All rights reserved. */
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. */
9 #include "surf_private.h"
10 #include "xbt/module.h"
12 #include "surf/surf_resource.h"
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
15 "Logging specific to SURF (kernel)");
17 /* Additional declarations for Windows portability. */
25 static const char *disk_drives_letter_table[MAX_DRIVE] = {
53 #endif /* #ifdef _XBT_WIN32 */
56 * Returns the initial path. On Windows the initial path is
57 * the current directory for the current process in the other
58 * case the function returns "./" that represents the current
59 * directory on Unix/Linux platforms.
62 const char *__surf_get_initial_path(void)
67 char current_directory[MAX_PATH + 1] = { 0 };
68 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
74 strncpy(root, current_directory, 3);
76 for (i = 0; i < MAX_DRIVE; i++) {
77 if (toupper(root[0]) == disk_drives_letter_table[i][0])
78 return disk_drives_letter_table[i];
87 /* The __surf_is_absolute_file_path() returns 1 if
88 * file_path is a absolute file path, in the other
89 * case the function returns 0.
91 int __surf_is_absolute_file_path(const char *file_path)
94 WIN32_FIND_DATA wfd = { 0 };
95 HANDLE hFile = FindFirstFile(file_path, &wfd);
97 if (INVALID_HANDLE_VALUE == hFile)
103 return (file_path[0] == '/');
109 xbt_dynar_t model_list = NULL;
110 tmgr_history_t history = NULL;
111 lmm_system_t maxmin_system = NULL;
112 xbt_dynar_t surf_path = NULL;
114 /* Don't forget to update the option description in smx_config when you change this */
115 s_surf_model_description_t surf_network_model_description[] = {
117 "Realistic network analytic model (slow-start modeled by multiplying latency by 10.4, bandwidth by .92; bottleneck sharing uses a payload of S=8775 for evaluating RTT). ",
118 surf_network_model_init_LegrandVelho},
120 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
121 surf_network_model_init_Constant},
123 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
124 surf_network_model_init_SMPI},
126 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
127 surf_network_model_init_CM02},
130 "Network pseudo-model using the GTNets simulator instead of an analytic model",
131 surf_network_model_init_GTNETS},
135 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
136 surf_network_model_init_NS3},
139 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
140 surf_network_model_init_Reno},
142 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
143 surf_network_model_init_Reno2},
145 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
146 surf_network_model_init_Vegas},
147 {NULL, NULL, NULL} /* this array must be NULL terminated */
150 s_surf_model_description_t surf_cpu_model_description[] = {
152 "Simplistic CPU model (time=size/power).",
153 surf_cpu_model_init_Cas01},
154 {NULL, NULL, NULL} /* this array must be NULL terminated */
157 s_surf_model_description_t surf_workstation_model_description[] = {
159 "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
160 surf_workstation_model_init_current_default},
162 "Workstation model that is automatically chosen if you change the network and CPU models",
163 surf_workstation_model_init_compound},
164 {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
165 surf_workstation_model_init_ptask_L07},
166 {NULL, NULL, NULL} /* this array must be NULL terminated */
169 s_surf_model_description_t surf_optimization_mode_description[] = {
171 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
174 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
177 "Full update of remaining and variables. Slow but may be useful when debugging.",
179 {NULL, NULL, NULL} /* this array must be NULL terminated */
182 #ifdef CONTEXT_THREADS
183 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
186 static int surf_nthreads = 1; /* number of threads of the parmap (1 means no parallelism) */
187 static double *surf_mins = NULL; /* return value of share_resources for each model */
188 static int surf_min_index; /* current index in surf_mins */
189 static double min; /* duration determined by surf_solve */
191 static void surf_share_resources(surf_model_t model);
192 static void surf_update_actions_state(surf_model_t model);
194 /** Displays the long description of all registered models, and quit */
195 void model_help(const char *category, s_surf_model_description_t * table)
198 printf("Long description of the %s models accepted by this simulator:\n",
200 for (i = 0; table[i].name; i++)
201 printf(" %s: %s\n", table[i].name, table[i].description);
204 int find_model_description(s_surf_model_description_t * table,
208 char *name_list = NULL;
210 for (i = 0; table[i].name; i++)
211 if (!strcmp(name, table[i].name)) {
214 name_list = strdup(table[0].name);
215 for (i = 1; table[i].name; i++) {
217 xbt_realloc(name_list,
218 strlen(name_list) + strlen(table[i].name) + 3);
219 strcat(name_list, ", ");
220 strcat(name_list, table[i].name);
222 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
226 double generic_maxmin_share_resources(xbt_swag_t running_actions,
229 void (*solve) (lmm_system_t))
231 surf_action_t action = NULL;
234 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
238 xbt_swag_foreach(action, running_actions) {
239 value = lmm_variable_getvalue(VARIABLE(action));
240 if ((value > 0) || (action->max_duration >= 0))
248 if (action->remains > 0)
249 min = action->remains / value;
252 if ((action->max_duration >= 0) && (action->max_duration < min))
253 min = action->max_duration;
255 min = action->max_duration;
258 for (action = xbt_swag_getNext(action, running_actions->offset);
260 action = xbt_swag_getNext(action, running_actions->offset)) {
261 value = lmm_variable_getvalue(VARIABLE(action));
263 if (action->remains > 0)
264 value = action->remains / value;
269 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
272 if ((action->max_duration >= 0) && (action->max_duration < min)) {
273 min = action->max_duration;
274 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
277 XBT_DEBUG("min value : %f", min);
283 XBT_LOG_EXTERNAL_CATEGORY(surf_cpu);
284 XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
285 XBT_LOG_EXTERNAL_CATEGORY(surf_lagrange);
286 XBT_LOG_EXTERNAL_CATEGORY(surf_lagrange_dichotomy);
287 XBT_LOG_EXTERNAL_CATEGORY(surf_maxmin);
288 XBT_LOG_EXTERNAL_CATEGORY(surf_network);
289 XBT_LOG_EXTERNAL_CATEGORY(surf_trace);
290 XBT_LOG_EXTERNAL_CATEGORY(surf_parse);
291 XBT_LOG_EXTERNAL_CATEGORY(surf_timer);
292 XBT_LOG_EXTERNAL_CATEGORY(surf_workstation);
293 XBT_LOG_EXTERNAL_CATEGORY(surf_config);
294 XBT_LOG_EXTERNAL_CATEGORY(surf_route);
297 XBT_LOG_EXTERNAL_CATEGORY(surf_network_gtnets);
300 void surf_init(int *argc, char **argv)
302 XBT_DEBUG("Create all Libs");
303 host_lib = xbt_lib_new();
304 link_lib = xbt_lib_new();
305 as_router_lib = xbt_lib_new();
307 XBT_DEBUG("ADD ROUTING LEVEL");
308 ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,xbt_free);
309 ROUTING_ASR_LEVEL = xbt_lib_add_level(as_router_lib,xbt_free);
311 XBT_DEBUG("ADD SURF LEVELS");
312 SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
313 SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
314 SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_resource_free);
316 /* Connect our log channels: that must be done manually under windows */
317 XBT_LOG_CONNECT(surf_cpu, surf);
318 XBT_LOG_CONNECT(surf_kernel, surf);
319 XBT_LOG_CONNECT(surf_lagrange, surf);
320 XBT_LOG_CONNECT(surf_lagrange_dichotomy, surf_lagrange);
321 XBT_LOG_CONNECT(surf_maxmin, surf);
322 XBT_LOG_CONNECT(surf_network, surf);
323 XBT_LOG_CONNECT(surf_trace, surf);
324 XBT_LOG_CONNECT(surf_parse, surf);
325 XBT_LOG_CONNECT(surf_timer, surf);
326 XBT_LOG_CONNECT(surf_workstation, surf);
327 XBT_LOG_CONNECT(surf_config, surf);
328 XBT_LOG_CONNECT(surf_route, surf);
331 XBT_LOG_CONNECT(surf_network_gtnets, surf);
334 xbt_init(argc, argv);
336 model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
338 history = tmgr_history_new();
340 surf_config_init(argc, argv);
347 # define FILE_DELIM "\\"
349 # define FILE_DELIM "/" /* FIXME: move to better location */
352 FILE *surf_fopen(const char *name, const char *mode)
355 char *path_elm = NULL;
361 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
362 return fopen(name, mode);
364 /* search relative files in the path */
365 xbt_dynar_foreach(surf_path, cpt, path_elm) {
366 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
367 file = fopen(buff, mode);
379 surf_model_t model = NULL;
381 surf_config_finalize();
383 xbt_dynar_foreach(model_list, iter, model)
384 model->model_private->finalize();
385 xbt_dynar_free(&model_list);
389 lmm_system_free(maxmin_system);
390 maxmin_system = NULL;
393 tmgr_history_free(history);
398 #ifdef CONTEXT_THREADS
399 xbt_parmap_destroy(surf_parmap);
403 xbt_dynar_free(&surf_path);
405 xbt_lib_free(&host_lib);
406 xbt_lib_free(&link_lib);
407 xbt_lib_free(&as_router_lib);
411 surf_parse_lex_destroy();
412 surf_parse_free_callbacks();
414 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
417 void surf_presolve(void)
419 double next_event_date = -1.0;
420 tmgr_trace_event_t event = NULL;
422 surf_resource_t resource = NULL;
423 surf_model_t model = NULL;
427 ("First Run! Let's \"purge\" events and put models in the right state");
428 while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
429 if (next_event_date > NOW)
432 tmgr_history_get_next_event_leq(history, next_event_date,
434 (void **) &resource))) {
435 resource->model->model_private->update_resource_state(resource,
440 xbt_dynar_foreach(model_list, iter, model)
441 model->model_private->update_actions_state(NOW, 0.0);
444 double surf_solve(double max_date)
446 min = -1.0; /* duration */
447 double next_event_date = -1.0;
448 double model_next_action_end = -1.0;
450 surf_resource_t resource = NULL;
451 surf_model_t model = NULL;
452 tmgr_trace_event_t event = NULL;
455 if (max_date != -1.0 && max_date != NOW) {
456 min = max_date - NOW;
459 XBT_DEBUG("Looking for next action end for all models except NS3");
461 if (surf_mins == NULL) {
462 surf_mins = xbt_new(double, xbt_dynar_length(model_list));
466 if (surf_get_nthreads() > 1) {
467 /* parallel version */
468 xbt_parmap_apply(surf_parmap, (void_f_pvoid_t) surf_share_resources, model_list);
471 /* sequential version */
472 xbt_dynar_foreach(model_list, iter, model) {
473 surf_share_resources(model);
478 for (i = 0; i < xbt_dynar_length(model_list); i++) {
479 if ((min < 0.0 || surf_mins[i] < min)
480 && surf_mins[i] >= 0.0) {
485 XBT_DEBUG("Min for resources (remember that NS3 dont update that value) : %f", min);
487 XBT_DEBUG("Looking for next trace event");
490 XBT_DEBUG("Next TRACE event : %f", next_event_date);
492 next_event_date = tmgr_history_next_date(history);
494 if(surf_network_model->name && !strcmp(surf_network_model->name,"network NS3")){
495 if(next_event_date!=-1.0 && min!=-1.0) {
496 min = MIN(next_event_date - NOW, min);
498 min = MAX(next_event_date - NOW, min);
501 XBT_DEBUG("Run for NS3 at most %f", min);
502 // run until min or next flow
503 model_next_action_end = surf_network_model->model_private->share_resources(min);
505 XBT_DEBUG("Min for NS3 : %f", model_next_action_end);
506 if(model_next_action_end>=0.0)
507 min = model_next_action_end;
510 if (next_event_date == -1.0) {
511 XBT_DEBUG("no next TRACE event. Stop searching for it");
515 if ((min != -1.0) && (next_event_date > NOW + min)) break;
517 XBT_DEBUG("Updating models");
519 tmgr_history_get_next_event_leq(history, next_event_date,
521 (void **) &resource))) {
522 if (resource->model->model_private->resource_used(resource)) {
523 min = next_event_date - NOW;
525 ("This event will modify model state. Next event set to %f",
528 /* update state of model_obj according to new value. Does not touch lmm.
529 It will be modified if needed when updating actions */
530 XBT_DEBUG("Calling update_resource_state for resource %s with min %lf",
531 resource->model->name, min);
532 resource->model->model_private->update_resource_state(resource,
538 /* FIXME: Moved this test to here to avoid stopping simulation if there are actions running on cpus and all cpus are with availability = 0.
539 * This may cause an infinite loop if one cpu has a trace with periodicity = 0 and the other a trace with periodicity > 0.
540 * The options are: all traces with same periodicity(0 or >0) or we need to change the way how the events are managed */
542 XBT_DEBUG("No next event at all. Bail out now.");
546 XBT_DEBUG("Duration set to %f", min);
550 if (surf_get_nthreads() > 1) {
551 /* parallel version */
552 xbt_parmap_apply(surf_parmap, (void_f_pvoid_t) surf_update_actions_state, model_list);
555 /* sequential version */
556 xbt_dynar_foreach(model_list, iter, model) {
557 surf_update_actions_state(model);
562 TRACE_paje_dump_buffer (0);
568 XBT_INLINE double surf_get_clock(void)
573 static void surf_share_resources(surf_model_t model)
575 if (strcmp(model->name,"network NS3")) {
576 XBT_DEBUG("Running for Resource [%s]", model->name);
577 double next_action_end = model->model_private->share_resources(NOW);
578 XBT_DEBUG("Resource [%s] : next action end = %f",
579 model->name, next_action_end);
580 int i = __sync_fetch_and_add(&surf_min_index, 1);
581 surf_mins[i] = next_action_end;
585 static void surf_update_actions_state(surf_model_t model)
587 model->model_private->update_actions_state(NOW, min);
591 * \brief Returns the number of parallel threads used to update the models.
592 * \return the number of threads (1 means no parallelism)
594 int surf_get_nthreads(void) {
595 return surf_nthreads;
599 * \brief Sets the number of parallel threads used to update the models.
601 * A value of 1 means no parallelism.
603 * \param nb_threads the number of threads to use
605 void surf_set_nthreads(int nthreads) {
607 xbt_assert(nthreads > 0, "Invalid number of parallel threads: %d", nthreads);
609 #ifdef CONTEXT_THREADS
610 xbt_parmap_destroy(surf_parmap);
615 #ifdef CONTEXT_THREADS
616 surf_parmap = xbt_parmap_new(nthreads, XBT_PARMAP_DEFAULT);
618 THROWF(arg_error, 0, "Cannot activate parallel threads in Surf: your architecture does not support threads");
622 surf_nthreads = nthreads;