1 /* Copyright (c) 2004-2013. 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. */
7 #include "surf_private.h"
8 #include "xbt/module.h"
10 #include "simix/smx_host_private.h"
11 #include "surf/surf_resource.h"
12 #include "xbt/xbt_os_thread.h"
13 #include "simgrid/sg_config.h"
17 XBT_LOG_NEW_CATEGORY(surf, "All SURF categories");
18 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
19 "Logging specific to SURF (kernel)");
21 /* Additional declarations for Windows portability. */
29 static const char *disk_drives_letter_table[MAX_DRIVE] = {
57 #endif /* #ifdef _XBT_WIN32 */
60 * Returns the initial path. On Windows the initial path is
61 * the current directory for the current process in the other
62 * case the function returns "./" that represents the current
63 * directory on Unix/Linux platforms.
66 const char *__surf_get_initial_path(void)
71 char current_directory[MAX_PATH + 1] = { 0 };
72 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
78 strncpy(root, current_directory, 3);
80 for (i = 0; i < MAX_DRIVE; i++) {
81 if (toupper(root[0]) == disk_drives_letter_table[i][0])
82 return disk_drives_letter_table[i];
91 /* The __surf_is_absolute_file_path() returns 1 if
92 * file_path is a absolute file path, in the other
93 * case the function returns 0.
95 int __surf_is_absolute_file_path(const char *file_path)
98 WIN32_FIND_DATA wfd = { 0 };
99 HANDLE hFile = FindFirstFile(file_path, &wfd);
101 if (INVALID_HANDLE_VALUE == hFile)
107 return (file_path[0] == '/');
113 xbt_dynar_t model_list = NULL;
114 tmgr_history_t history = NULL;
115 lmm_system_t maxmin_system = NULL;
116 xbt_dynar_t surf_path = NULL;
117 xbt_dynar_t host_that_restart = NULL;
118 xbt_dict_t watched_hosts_lib;
120 /* Don't forget to update the option description in smx_config when you change this */
121 s_surf_model_description_t surf_network_model_description[] = {
123 "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). ",
124 surf_network_model_init_LegrandVelho},
126 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
127 surf_network_model_init_Constant},
129 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
130 surf_network_model_init_SMPI},
132 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
133 surf_network_model_init_CM02},
136 "Network pseudo-model using the GTNets simulator instead of an analytic model",
137 surf_network_model_init_GTNETS},
141 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
142 surf_network_model_init_NS3},
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_Reno},
148 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
149 surf_network_model_init_Reno2},
151 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
152 surf_network_model_init_Vegas},
153 {NULL, NULL, NULL} /* this array must be NULL terminated */
156 s_surf_model_description_t surf_cpu_model_description[] = {
158 "Simplistic CPU model (time=size/power).",
159 surf_cpu_model_init_Cas01},
160 {NULL, NULL, NULL} /* this array must be NULL terminated */
163 s_surf_model_description_t surf_workstation_model_description[] = {
165 "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
166 surf_workstation_model_init_current_default},
168 "Workstation model that is automatically chosen if you change the network and CPU models",
169 surf_workstation_model_init_compound},
170 {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
171 surf_workstation_model_init_ptask_L07},
172 {NULL, NULL, NULL} /* this array must be NULL terminated */
175 s_surf_model_description_t surf_optimization_mode_description[] = {
177 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
180 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
183 "Full update of remaining and variables. Slow but may be useful when debugging.",
185 {NULL, NULL, NULL} /* this array must be NULL terminated */
188 s_surf_model_description_t surf_storage_model_description[] = {
190 "Simplistic storage model.",
191 surf_storage_model_init_default},
192 {NULL, NULL, NULL} /* this array must be NULL terminated */
195 /* ********************************************************************* */
196 /* TUTORIAL: New model */
197 s_surf_model_description_t surf_new_model_description[] = {
200 surf_new_model_init_default},
201 {NULL, NULL, NULL} /* this array must be NULL terminated */
203 /* ********************************************************************* */
205 #ifdef CONTEXT_THREADS
206 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
209 static double *surf_mins = NULL; /* return value of share_resources for each model */
210 static int surf_min_index; /* current index in surf_mins */
211 static double min; /* duration determined by surf_solve */
213 static void surf_share_resources(surf_model_t model);
214 static void surf_update_actions_state(surf_model_t model);
216 /** Displays the long description of all registered models, and quit */
217 void model_help(const char *category, s_surf_model_description_t * table)
220 printf("Long description of the %s models accepted by this simulator:\n",
222 for (i = 0; table[i].name; i++)
223 printf(" %s: %s\n", table[i].name, table[i].description);
226 int find_model_description(s_surf_model_description_t * table,
230 char *name_list = NULL;
232 for (i = 0; table[i].name; i++)
233 if (!strcmp(name, table[i].name)) {
236 name_list = strdup(table[0].name);
237 for (i = 1; table[i].name; i++) {
239 xbt_realloc(name_list,
240 strlen(name_list) + strlen(table[i].name) + 3);
241 strcat(name_list, ", ");
242 strcat(name_list, table[i].name);
244 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
248 double generic_maxmin_share_resources(xbt_swag_t running_actions,
251 void (*solve) (lmm_system_t))
253 surf_action_t action = NULL;
256 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
260 xbt_swag_foreach(action, running_actions) {
261 value = lmm_variable_getvalue(VARIABLE(action));
262 if ((value > 0) || (action->max_duration >= 0))
270 if (action->remains > 0)
271 min = action->remains / value;
274 if ((action->max_duration >= 0) && (action->max_duration < min))
275 min = action->max_duration;
277 min = action->max_duration;
280 for (action = xbt_swag_getNext(action, running_actions->offset);
282 action = xbt_swag_getNext(action, running_actions->offset)) {
283 value = lmm_variable_getvalue(VARIABLE(action));
285 if (action->remains > 0)
286 value = action->remains / value;
291 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
294 if ((action->max_duration >= 0) && (action->max_duration < min)) {
295 min = action->max_duration;
296 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
299 XBT_DEBUG("min value : %f", min);
305 double generic_share_resources_lazy(double now, surf_model_t model)
307 surf_action_lmm_t action = NULL;
312 ("Before share resources, the size of modified actions set is %d",
313 xbt_swag_size(model->model_private->modified_set));
315 lmm_solve(model->model_private->maxmin_system);
318 ("After share resources, The size of modified actions set is %d",
319 xbt_swag_size(model->model_private->modified_set));
321 while((action = xbt_swag_extract(model->model_private->modified_set))) {
322 int max_dur_flag = 0;
324 if (action->generic_action.state_set !=
325 model->states.running_action_set)
328 /* bogus priority, skip it */
329 if (action->generic_action.priority <= 0)
332 generic_update_action_remaining_lazy(action,now);
335 value = lmm_variable_getvalue(action->variable);
337 if (action->generic_action.remains > 0) {
338 value = action->generic_action.remains / value;
346 if ((action->generic_action.max_duration != NO_MAX_DURATION)
348 || action->generic_action.start +
349 action->generic_action.max_duration < min)) {
350 min = action->generic_action.start +
351 action->generic_action.max_duration;
355 XBT_DEBUG("Action(%p) Start %f Finish %f Max_duration %f", action,
356 action->generic_action.start, now + value,
357 action->generic_action.max_duration);
360 surf_action_lmm_heap_remove(model->model_private->action_heap,action);
361 surf_action_lmm_heap_insert(model->model_private->action_heap,action, min, max_dur_flag ? MAX_DURATION : NORMAL);
362 XBT_DEBUG("Insert at heap action(%p) min %f now %f", action, min,
364 } else DIE_IMPOSSIBLE;
367 //hereafter must have already the min value for this resource model
368 if (xbt_heap_size(model->model_private->action_heap) > 0)
369 min = xbt_heap_maxkey(model->model_private->action_heap) - now;
373 XBT_DEBUG("The minimum with the HEAP %f", min);
377 static XBT_INLINE void routing_asr_host_free(void *p)
379 sg_routing_edge_t elm = p;
384 static XBT_INLINE void routing_asr_prop_free(void *p)
390 void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
391 *ver_major = SIMGRID_VERSION_MAJOR;
392 *ver_minor = SIMGRID_VERSION_MINOR;
393 *ver_patch = SIMGRID_VERSION_PATCH;
396 void surf_init(int *argc, char **argv)
398 XBT_DEBUG("Create all Libs");
399 host_lib = xbt_lib_new();
400 link_lib = xbt_lib_new();
401 as_router_lib = xbt_lib_new();
402 storage_lib = xbt_lib_new();
403 storage_type_lib = xbt_lib_new();
404 watched_hosts_lib = xbt_dict_new_homogeneous(NULL);
406 XBT_DEBUG("Add routing levels");
407 ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,routing_asr_host_free);
408 ROUTING_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_host_free);
409 ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
411 XBT_DEBUG("Add SURF levels");
412 SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
413 SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
414 SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_resource_free);
416 xbt_init(argc, argv);
418 model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
420 history = tmgr_history_new();
423 TRACE_add_start_function(TRACE_surf_alloc);
424 TRACE_add_end_function(TRACE_surf_release);
427 sg_config_init(argc, argv);
435 # define FILE_DELIM "\\"
437 # define FILE_DELIM "/" /* FIXME: move to better location */
440 FILE *surf_fopen(const char *name, const char *mode)
443 char *path_elm = NULL;
449 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
450 return fopen(name, mode);
452 /* search relative files in the path */
453 xbt_dynar_foreach(surf_path, cpt, path_elm) {
454 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
455 file = fopen(buff, mode);
467 surf_model_t model = NULL;
470 TRACE_end(); /* Just in case it was not called by the upper
471 * layer (or there is no upper layer) */
474 sg_config_finalize();
476 xbt_dynar_foreach(model_list, iter, model)
477 model->model_private->finalize();
478 xbt_dynar_free(&model_list);
482 lmm_system_free(maxmin_system);
483 maxmin_system = NULL;
486 tmgr_history_free(history);
491 #ifdef CONTEXT_THREADS
492 xbt_parmap_destroy(surf_parmap);
496 xbt_dynar_free(&host_that_restart);
497 xbt_dynar_free(&surf_path);
499 xbt_lib_free(&host_lib);
500 xbt_lib_free(&link_lib);
501 xbt_lib_free(&as_router_lib);
502 xbt_lib_free(&storage_lib);
503 xbt_lib_free(&storage_type_lib);
505 xbt_dict_free(&watched_hosts_lib);
508 surf_parse_lex_destroy();
509 surf_parse_free_callbacks();
511 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
514 void surf_presolve(void)
516 double next_event_date = -1.0;
517 tmgr_trace_event_t event = NULL;
519 surf_resource_t resource = NULL;
520 surf_model_t model = NULL;
524 ("First Run! Let's \"purge\" events and put models in the right state");
525 while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
526 if (next_event_date > NOW)
529 tmgr_history_get_next_event_leq(history, next_event_date,
531 (void **) &resource))) {
533 resource->model->model_private->update_resource_state(resource,
539 xbt_dynar_foreach(model_list, iter, model)
540 model->model_private->update_actions_state(NOW, 0.0);
543 double surf_solve(double max_date)
545 min = -1.0; /* duration */
546 double next_event_date = -1.0;
547 double model_next_action_end = -1.0;
549 surf_resource_t resource = NULL;
550 surf_model_t model = NULL;
551 tmgr_trace_event_t event = NULL;
554 if(!host_that_restart)
555 host_that_restart = xbt_dynar_new(sizeof(char*), NULL);
557 if (max_date != -1.0 && max_date != NOW) {
558 min = max_date - NOW;
561 XBT_DEBUG("Looking for next action end for all models except NS3");
563 if (surf_mins == NULL) {
564 surf_mins = xbt_new(double, xbt_dynar_length(model_list));
568 /* sequential version */
569 xbt_dynar_foreach(model_list, iter, model) {
570 surf_share_resources(model);
574 for (i = 0; i < xbt_dynar_length(model_list); i++) {
575 if ((min < 0.0 || surf_mins[i] < min)
576 && surf_mins[i] >= 0.0) {
581 XBT_DEBUG("Min for resources (remember that NS3 don't update that value) : %f", min);
583 XBT_DEBUG("Looking for next trace event");
586 XBT_DEBUG("Next TRACE event : %f", next_event_date);
588 next_event_date = tmgr_history_next_date(history);
590 if(surf_network_model->name && !strcmp(surf_network_model->name,"network NS3")){
591 if(next_event_date!=-1.0 && min!=-1.0) {
592 min = MIN(next_event_date - NOW, min);
594 min = MAX(next_event_date - NOW, min);
597 XBT_DEBUG("Run for network at most %f", min);
598 // run until min or next flow
599 model_next_action_end = surf_network_model->model_private->share_resources(min);
601 XBT_DEBUG("Min for network : %f", model_next_action_end);
602 if(model_next_action_end>=0.0)
603 min = model_next_action_end;
606 if (next_event_date < 0.0) {
607 XBT_DEBUG("no next TRACE event. Stop searching for it");
611 if ((min == -1.0) || (next_event_date > NOW + min)) break;
613 XBT_DEBUG("Updating models (min = %g, NOW = %g, next_event_date = %g)",min, NOW, next_event_date);
615 tmgr_history_get_next_event_leq(history, next_event_date,
617 (void **) &resource))) {
618 if (resource->model->model_private->resource_used(resource) ||
619 xbt_dict_get_or_null(watched_hosts_lib,resource->name)
621 min = next_event_date - NOW;
623 ("This event will modify model state. Next event set to %f",
626 /* update state of model_obj according to new value. Does not touch lmm.
627 It will be modified if needed when updating actions */
628 XBT_DEBUG("Calling update_resource_state for resource %s with min %f",
629 resource->name, min);
631 resource->model->model_private->update_resource_state(resource,
637 /* FIXME: Moved this test to here to avoid stopping simulation if there are actions running on cpus and all cpus are with availability = 0.
638 * This may cause an infinite loop if one cpu has a trace with periodicity = 0 and the other a trace with periodicity > 0.
639 * The options are: all traces with same periodicity(0 or >0) or we need to change the way how the events are managed */
641 XBT_DEBUG("No next event at all. Bail out now.");
645 XBT_DEBUG("Duration set to %f", min);
649 /* sequential version */
650 xbt_dynar_foreach(model_list, iter, model) {
651 surf_update_actions_state(model);
655 TRACE_paje_dump_buffer (0);
661 XBT_INLINE double surf_get_clock(void)
666 static void surf_share_resources(surf_model_t model)
668 double next_action_end = -1.0;
669 int i = __sync_fetch_and_add(&surf_min_index, 1);
670 if (strcmp(model->name,"network NS3")) {
671 XBT_DEBUG("Running for Resource [%s]", model->name);
672 next_action_end = model->model_private->share_resources(NOW);
673 XBT_DEBUG("Resource [%s] : next action end = %f",
674 model->name, next_action_end);
676 surf_mins[i] = next_action_end;
679 static void surf_update_actions_state(surf_model_t model)
681 model->model_private->update_actions_state(NOW, min);