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"
13 #include "xbt/xbt_os_thread.h"
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
16 "Logging specific to SURF (kernel)");
18 /* Additional declarations for Windows portability. */
26 static const char *disk_drives_letter_table[MAX_DRIVE] = {
54 #endif /* #ifdef _XBT_WIN32 */
57 * Returns the initial path. On Windows the initial path is
58 * the current directory for the current process in the other
59 * case the function returns "./" that represents the current
60 * directory on Unix/Linux platforms.
63 const char *__surf_get_initial_path(void)
68 char current_directory[MAX_PATH + 1] = { 0 };
69 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
75 strncpy(root, current_directory, 3);
77 for (i = 0; i < MAX_DRIVE; i++) {
78 if (toupper(root[0]) == disk_drives_letter_table[i][0])
79 return disk_drives_letter_table[i];
88 /* The __surf_is_absolute_file_path() returns 1 if
89 * file_path is a absolute file path, in the other
90 * case the function returns 0.
92 int __surf_is_absolute_file_path(const char *file_path)
95 WIN32_FIND_DATA wfd = { 0 };
96 HANDLE hFile = FindFirstFile(file_path, &wfd);
98 if (INVALID_HANDLE_VALUE == hFile)
104 return (file_path[0] == '/');
110 xbt_dynar_t model_list = NULL;
111 tmgr_history_t history = NULL;
112 lmm_system_t maxmin_system = NULL;
113 xbt_dynar_t surf_path = NULL;
115 /* Don't forget to update the option description in smx_config when you change this */
116 s_surf_model_description_t surf_network_model_description[] = {
118 "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). ",
119 surf_network_model_init_LegrandVelho},
121 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
122 surf_network_model_init_Constant},
124 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
125 surf_network_model_init_SMPI},
127 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
128 surf_network_model_init_CM02},
131 "Network pseudo-model using the GTNets simulator instead of an analytic model",
132 surf_network_model_init_GTNETS},
136 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
137 surf_network_model_init_NS3},
140 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
141 surf_network_model_init_Reno},
143 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
144 surf_network_model_init_Reno2},
146 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
147 surf_network_model_init_Vegas},
148 {NULL, NULL, NULL} /* this array must be NULL terminated */
151 s_surf_model_description_t surf_cpu_model_description[] = {
153 "Simplistic CPU model (time=size/power).",
154 surf_cpu_model_init_Cas01},
155 {NULL, NULL, NULL} /* this array must be NULL terminated */
158 s_surf_model_description_t surf_workstation_model_description[] = {
160 "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
161 surf_workstation_model_init_current_default},
163 "Workstation model that is automatically chosen if you change the network and CPU models",
164 surf_workstation_model_init_compound},
165 {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
166 surf_workstation_model_init_ptask_L07},
167 {NULL, NULL, NULL} /* this array must be NULL terminated */
170 s_surf_model_description_t surf_optimization_mode_description[] = {
172 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
175 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
178 "Full update of remaining and variables. Slow but may be useful when debugging.",
180 {NULL, NULL, NULL} /* this array must be NULL terminated */
183 s_surf_model_description_t surf_storage_model_description[] = {
185 "Simplistic storage model.",
186 surf_storage_model_init_default},
187 {NULL, NULL, NULL} /* this array must be NULL terminated */
190 #ifdef CONTEXT_THREADS
191 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
194 static int surf_nthreads = 1; /* number of threads of the parmap (1 means no parallelism) */
195 static double *surf_mins = NULL; /* return value of share_resources for each model */
196 static int surf_min_index; /* current index in surf_mins */
197 static double min; /* duration determined by surf_solve */
199 static void surf_share_resources(surf_model_t model);
200 static void surf_update_actions_state(surf_model_t model);
202 /** Displays the long description of all registered models, and quit */
203 void model_help(const char *category, s_surf_model_description_t * table)
206 printf("Long description of the %s models accepted by this simulator:\n",
208 for (i = 0; table[i].name; i++)
209 printf(" %s: %s\n", table[i].name, table[i].description);
212 int find_model_description(s_surf_model_description_t * table,
216 char *name_list = NULL;
218 for (i = 0; table[i].name; i++)
219 if (!strcmp(name, table[i].name)) {
222 name_list = strdup(table[0].name);
223 for (i = 1; table[i].name; i++) {
225 xbt_realloc(name_list,
226 strlen(name_list) + strlen(table[i].name) + 3);
227 strcat(name_list, ", ");
228 strcat(name_list, table[i].name);
230 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
234 double generic_maxmin_share_resources(xbt_swag_t running_actions,
237 void (*solve) (lmm_system_t))
239 surf_action_t action = NULL;
242 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
246 xbt_swag_foreach(action, running_actions) {
247 value = lmm_variable_getvalue(VARIABLE(action));
248 if ((value > 0) || (action->max_duration >= 0))
256 if (action->remains > 0)
257 min = action->remains / value;
260 if ((action->max_duration >= 0) && (action->max_duration < min))
261 min = action->max_duration;
263 min = action->max_duration;
266 for (action = xbt_swag_getNext(action, running_actions->offset);
268 action = xbt_swag_getNext(action, running_actions->offset)) {
269 value = lmm_variable_getvalue(VARIABLE(action));
271 if (action->remains > 0)
272 value = action->remains / value;
277 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
280 if ((action->max_duration >= 0) && (action->max_duration < min)) {
281 min = action->max_duration;
282 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
285 XBT_DEBUG("min value : %f", min);
291 XBT_LOG_EXTERNAL_CATEGORY(surf_cpu);
292 XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
293 XBT_LOG_EXTERNAL_CATEGORY(surf_lagrange);
294 XBT_LOG_EXTERNAL_CATEGORY(surf_lagrange_dichotomy);
295 XBT_LOG_EXTERNAL_CATEGORY(surf_maxmin);
296 XBT_LOG_EXTERNAL_CATEGORY(surf_network);
297 XBT_LOG_EXTERNAL_CATEGORY(surf_trace);
298 XBT_LOG_EXTERNAL_CATEGORY(surf_parse);
299 XBT_LOG_EXTERNAL_CATEGORY(surf_timer);
300 XBT_LOG_EXTERNAL_CATEGORY(surf_workstation);
301 XBT_LOG_EXTERNAL_CATEGORY(surf_config);
302 XBT_LOG_EXTERNAL_CATEGORY(surf_route);
305 XBT_LOG_EXTERNAL_CATEGORY(surf_network_gtnets);
308 static XBT_INLINE void routing_asr_host_free(void *p)
310 network_element_t elm = p;
315 void surf_init(int *argc, char **argv)
317 XBT_DEBUG("Create all Libs");
318 host_lib = xbt_lib_new();
319 link_lib = xbt_lib_new();
320 as_router_lib = xbt_lib_new();
321 storage_lib = xbt_lib_new();
322 storage_type_lib = xbt_lib_new();
324 XBT_DEBUG("ADD ROUTING LEVEL");
325 ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,routing_asr_host_free);
326 ROUTING_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_host_free);
327 ROUTING_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,xbt_free);
328 ROUTING_STORAGE_HOST_LEVEL = xbt_lib_add_level(storage_lib,routing_storage_host_free);
329 ROUTING_STORAGE_TYPE_LEVEL = xbt_lib_add_level(storage_type_lib,routing_storage_type_free);
331 XBT_DEBUG("ADD SURF LEVELS");
332 SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
333 SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
334 SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_resource_free);
335 SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_resource_free);
337 /* Connect our log channels: that must be done manually under windows */
338 XBT_LOG_CONNECT(surf_cpu, surf);
339 XBT_LOG_CONNECT(surf_kernel, surf);
340 XBT_LOG_CONNECT(surf_lagrange, surf);
341 XBT_LOG_CONNECT(surf_lagrange_dichotomy, surf_lagrange);
342 XBT_LOG_CONNECT(surf_maxmin, surf);
343 XBT_LOG_CONNECT(surf_network, surf);
344 XBT_LOG_CONNECT(surf_trace, surf);
345 XBT_LOG_CONNECT(surf_parse, surf);
346 XBT_LOG_CONNECT(surf_timer, surf);
347 XBT_LOG_CONNECT(surf_workstation, surf);
348 XBT_LOG_CONNECT(surf_config, surf);
349 XBT_LOG_CONNECT(surf_route, surf);
352 XBT_LOG_CONNECT(surf_network_gtnets, surf);
355 xbt_init(argc, argv);
357 model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
359 history = tmgr_history_new();
361 surf_config_init(argc, argv);
368 # define FILE_DELIM "\\"
370 # define FILE_DELIM "/" /* FIXME: move to better location */
373 FILE *surf_fopen(const char *name, const char *mode)
376 char *path_elm = NULL;
382 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
383 return fopen(name, mode);
385 /* search relative files in the path */
386 xbt_dynar_foreach(surf_path, cpt, path_elm) {
387 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
388 file = fopen(buff, mode);
400 surf_model_t model = NULL;
402 surf_config_finalize();
404 xbt_dynar_foreach(model_list, iter, model)
405 model->model_private->finalize();
406 xbt_dynar_free(&model_list);
410 lmm_system_free(maxmin_system);
411 maxmin_system = NULL;
414 tmgr_history_free(history);
419 #ifdef CONTEXT_THREADS
420 xbt_parmap_destroy(surf_parmap);
425 xbt_dynar_free(&surf_path);
427 xbt_lib_free(&host_lib);
428 xbt_lib_free(&link_lib);
429 xbt_lib_free(&as_router_lib);
430 xbt_lib_free(&storage_lib);
431 xbt_lib_free(&storage_type_lib);
434 surf_parse_lex_destroy();
435 surf_parse_free_callbacks();
437 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
440 void surf_presolve(void)
442 double next_event_date = -1.0;
443 tmgr_trace_event_t event = NULL;
445 surf_resource_t resource = NULL;
446 surf_model_t model = NULL;
450 ("First Run! Let's \"purge\" events and put models in the right state");
451 while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
452 if (next_event_date > NOW)
455 tmgr_history_get_next_event_leq(history, next_event_date,
457 (void **) &resource))) {
458 resource->model->model_private->update_resource_state(resource,
463 xbt_dynar_foreach(model_list, iter, model)
464 model->model_private->update_actions_state(NOW, 0.0);
467 double surf_solve(double max_date)
469 min = -1.0; /* duration */
470 double next_event_date = -1.0;
471 double model_next_action_end = -1.0;
473 surf_resource_t resource = NULL;
474 surf_model_t model = NULL;
475 tmgr_trace_event_t event = NULL;
478 if (max_date != -1.0 && max_date != NOW) {
479 min = max_date - NOW;
482 XBT_DEBUG("Looking for next action end for all models except NS3");
484 if (surf_mins == NULL) {
485 surf_mins = xbt_new(double, xbt_dynar_length(model_list));
490 if (surf_get_nthreads() > 1) {
491 /* parallel version */
492 #ifdef CONTEXT_THREADS
493 xbt_parmap_apply(surf_parmap, (void_f_pvoid_t) surf_share_resources, model_list);
497 /* sequential version */
498 xbt_dynar_foreach(model_list, iter, model) {
499 surf_share_resources(model);
504 for (i = 0; i < xbt_dynar_length(model_list); i++) {
505 if ((min < 0.0 || surf_mins[i] < min)
506 && surf_mins[i] >= 0.0) {
511 XBT_DEBUG("Min for resources (remember that NS3 dont update that value) : %f", min);
513 XBT_DEBUG("Looking for next trace event");
516 XBT_DEBUG("Next TRACE event : %f", next_event_date);
518 next_event_date = tmgr_history_next_date(history);
520 if(surf_network_model->name && !strcmp(surf_network_model->name,"network NS3")){
521 if(next_event_date!=-1.0 && min!=-1.0) {
522 min = MIN(next_event_date - NOW, min);
524 min = MAX(next_event_date - NOW, min);
527 XBT_DEBUG("Run for NS3 at most %f", min);
528 // run until min or next flow
529 model_next_action_end = surf_network_model->model_private->share_resources(min);
531 XBT_DEBUG("Min for NS3 : %f", model_next_action_end);
532 if(model_next_action_end>=0.0)
533 min = model_next_action_end;
536 if (next_event_date == -1.0) {
537 XBT_DEBUG("no next TRACE event. Stop searching for it");
541 if ((min != -1.0) && (next_event_date > NOW + min)) break;
543 XBT_DEBUG("Updating models");
545 tmgr_history_get_next_event_leq(history, next_event_date,
547 (void **) &resource))) {
548 if (resource->model->model_private->resource_used(resource)) {
549 min = next_event_date - NOW;
551 ("This event will modify model state. Next event set to %f",
554 /* update state of model_obj according to new value. Does not touch lmm.
555 It will be modified if needed when updating actions */
556 XBT_DEBUG("Calling update_resource_state for resource %s with min %lf",
557 resource->model->name, min);
558 resource->model->model_private->update_resource_state(resource,
564 /* FIXME: Moved this test to here to avoid stopping simulation if there are actions running on cpus and all cpus are with availability = 0.
565 * This may cause an infinite loop if one cpu has a trace with periodicity = 0 and the other a trace with periodicity > 0.
566 * The options are: all traces with same periodicity(0 or >0) or we need to change the way how the events are managed */
568 XBT_DEBUG("No next event at all. Bail out now.");
572 XBT_DEBUG("Duration set to %f", min);
576 if (surf_get_nthreads() > 1) {
577 /* parallel version */
578 #ifdef CONTEXT_THREADS
579 xbt_parmap_apply(surf_parmap, (void_f_pvoid_t) surf_update_actions_state, model_list);
583 /* sequential version */
584 xbt_dynar_foreach(model_list, iter, model) {
585 surf_update_actions_state(model);
590 TRACE_paje_dump_buffer (0);
596 XBT_INLINE double surf_get_clock(void)
601 static void surf_share_resources(surf_model_t model)
603 double next_action_end = -1.0;
604 int i = __sync_fetch_and_add(&surf_min_index, 1);
605 if (strcmp(model->name,"network NS3")) {
606 XBT_DEBUG("Running for Resource [%s]", model->name);
607 next_action_end = model->model_private->share_resources(NOW);
608 XBT_DEBUG("Resource [%s] : next action end = %f",
609 model->name, next_action_end);
611 surf_mins[i] = next_action_end;
614 static void surf_update_actions_state(surf_model_t model)
616 model->model_private->update_actions_state(NOW, min);
620 * \brief Returns the number of parallel threads used to update the models.
621 * \return the number of threads (1 means no parallelism)
623 int surf_get_nthreads(void) {
624 return surf_nthreads;
628 * \brief Sets the number of parallel threads used to update the models.
630 * A value of 1 means no parallelism.
632 * \param nb_threads the number of threads to use
634 void surf_set_nthreads(int nthreads) {
637 nthreads = xbt_os_get_numcores();
638 XBT_INFO("Auto-setting surf/nthreads to %d",nthreads);
641 #ifdef CONTEXT_THREADS
642 xbt_parmap_destroy(surf_parmap);
647 #ifdef CONTEXT_THREADS
648 surf_parmap = xbt_parmap_new(nthreads, XBT_PARMAP_DEFAULT);
650 THROWF(arg_error, 0, "Cannot activate parallel threads in Surf: your architecture does not support threads");
654 surf_nthreads = nthreads;