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 potability. */
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[] = {
151 {"Cas01_fullupdate", "CPU classical model time=size/power (Cas01). [Deprecated. Use Cas01 with option --cfg=cpu/optim:Full. The Full option updates all actions at every step, which may be useful for debug.]",
152 surf_cpu_model_init_Cas01},
154 "Simplistic CPU model (time=size/power).",
155 surf_cpu_model_init_Cas01},
157 "CPU classical model time=size/power (Cas01). [Deprecated. Use Cas01 with option --cfg=cpu/optim:TI. The TI optimization is highly optimized when using traces]",
158 surf_cpu_model_init_ti},
159 {NULL, NULL, NULL} /* this array must be NULL terminated */
162 s_surf_model_description_t surf_workstation_model_description[] = {
164 "Curent default workstation model (may change with versions of SimGrid). Currently Cas01 and LV08 (with full duplex support) as CPU and Network",
165 surf_workstation_model_init_current_default},
167 "Default workstation model, using Cas01 and CM02 as CPU and Network",
168 surf_workstation_model_init_CLM03},
170 "Workstation model that is automatically chosen if you change the network and CPU models",
171 surf_workstation_model_init_compound},
172 {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
173 surf_workstation_model_init_ptask_L07},
174 {NULL, NULL, NULL} /* this array must be NULL terminated */
177 s_surf_model_description_t surf_optimization_mode_description[] = {
179 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
182 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
185 "Full update of remaining and variables. Slow but may be useful when debugging.",
187 {NULL, NULL, NULL} /* this array must be NULL terminated */
190 /** Displays the long description of all registered models, and quit */
191 void model_help(const char *category, s_surf_model_description_t * table)
194 printf("Long description of the %s models accepted by this simulator:\n",
196 for (i = 0; table[i].name; i++)
197 printf(" %s: %s\n", table[i].name, table[i].description);
200 int find_model_description(s_surf_model_description_t * table,
204 char *name_list = NULL;
206 for (i = 0; table[i].name; i++)
207 if (!strcmp(name, table[i].name)) {
210 name_list = strdup(table[0].name);
211 for (i = 1; table[i].name; i++) {
213 xbt_realloc(name_list,
214 strlen(name_list) + strlen(table[i].name) + 3);
215 strcat(name_list, ", ");
216 strcat(name_list, table[i].name);
218 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
222 double generic_maxmin_share_resources(xbt_swag_t running_actions,
225 void (*solve) (lmm_system_t))
227 surf_action_t action = NULL;
230 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
234 xbt_swag_foreach(action, running_actions) {
235 value = lmm_variable_getvalue(VARIABLE(action));
236 if ((value > 0) || (action->max_duration >= 0))
244 if (action->remains > 0)
245 min = action->remains / value;
248 if ((action->max_duration >= 0) && (action->max_duration < min))
249 min = action->max_duration;
251 min = action->max_duration;
254 for (action = xbt_swag_getNext(action, running_actions->offset);
256 action = xbt_swag_getNext(action, running_actions->offset)) {
257 value = lmm_variable_getvalue(VARIABLE(action));
259 if (action->remains > 0)
260 value = action->remains / value;
265 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
268 if ((action->max_duration >= 0) && (action->max_duration < min)) {
269 min = action->max_duration;
270 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
273 XBT_DEBUG("min value : %f", min);
279 XBT_LOG_EXTERNAL_CATEGORY(surf_cpu);
280 XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
281 XBT_LOG_EXTERNAL_CATEGORY(surf_lagrange);
282 XBT_LOG_EXTERNAL_CATEGORY(surf_lagrange_dichotomy);
283 XBT_LOG_EXTERNAL_CATEGORY(surf_maxmin);
284 XBT_LOG_EXTERNAL_CATEGORY(surf_network);
285 XBT_LOG_EXTERNAL_CATEGORY(surf_trace);
286 XBT_LOG_EXTERNAL_CATEGORY(surf_parse);
287 XBT_LOG_EXTERNAL_CATEGORY(surf_timer);
288 XBT_LOG_EXTERNAL_CATEGORY(surf_workstation);
289 XBT_LOG_EXTERNAL_CATEGORY(surf_config);
290 XBT_LOG_EXTERNAL_CATEGORY(surf_route);
293 XBT_LOG_EXTERNAL_CATEGORY(surf_network_gtnets);
296 void surf_init(int *argc, char **argv)
298 XBT_DEBUG("Create all Libs");
299 host_lib = xbt_lib_new();
300 link_lib = xbt_lib_new();
301 as_router_lib = xbt_lib_new();
303 XBT_DEBUG("ADD ROUTING LEVEL");
304 ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,xbt_free);
305 ROUTING_ASR_LEVEL = xbt_lib_add_level(as_router_lib,xbt_free);
307 XBT_DEBUG("ADD SURF LEVELS");
308 SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
309 SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
310 SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_resource_free);
312 /* Connect our log channels: that must be done manually under windows */
313 XBT_LOG_CONNECT(surf_cpu, surf);
314 XBT_LOG_CONNECT(surf_kernel, surf);
315 XBT_LOG_CONNECT(surf_lagrange, surf);
316 XBT_LOG_CONNECT(surf_lagrange_dichotomy, surf_lagrange);
317 XBT_LOG_CONNECT(surf_maxmin, surf);
318 XBT_LOG_CONNECT(surf_network, surf);
319 XBT_LOG_CONNECT(surf_trace, surf);
320 XBT_LOG_CONNECT(surf_parse, surf);
321 XBT_LOG_CONNECT(surf_timer, surf);
322 XBT_LOG_CONNECT(surf_workstation, surf);
323 XBT_LOG_CONNECT(surf_config, surf);
324 XBT_LOG_CONNECT(surf_route, surf);
327 XBT_LOG_CONNECT(surf_network_gtnets, surf);
330 xbt_init(argc, argv);
332 model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
334 history = tmgr_history_new();
336 surf_config_init(argc, argv);
343 # define FILE_DELIM "\\"
345 # define FILE_DELIM "/" /* FIXME: move to better location */
348 FILE *surf_fopen(const char *name, const char *mode)
351 char *path_elm = NULL;
357 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
358 return fopen(name, mode);
360 /* search relative files in the path */
361 xbt_dynar_foreach(surf_path, cpt, path_elm) {
362 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
363 file = fopen(buff, mode);
375 surf_model_t model = NULL;
377 surf_config_finalize();
379 xbt_dynar_foreach(model_list, iter, model)
380 model->model_private->finalize();
381 xbt_dynar_free(&model_list);
385 lmm_system_free(maxmin_system);
386 maxmin_system = NULL;
389 tmgr_history_free(history);
394 xbt_dynar_free(&surf_path);
396 xbt_lib_free(&host_lib);
397 xbt_lib_free(&link_lib);
398 xbt_lib_free(&as_router_lib);
402 surf_parse_lex_destroy();
403 surf_parse_free_callbacks();
405 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
408 void surf_presolve(void)
410 double next_event_date = -1.0;
411 tmgr_trace_event_t event = NULL;
413 surf_resource_t resource = NULL;
414 surf_model_t model = NULL;
418 ("First Run! Let's \"purge\" events and put models in the right state");
419 while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
420 if (next_event_date > NOW)
423 tmgr_history_get_next_event_leq(history, next_event_date,
425 (void **) &resource))) {
426 resource->model->model_private->update_resource_state(resource,
431 xbt_dynar_foreach(model_list, iter, model)
432 model->model_private->update_actions_state(NOW, 0.0);
435 double surf_solve(double max_date)
437 double min = -1.0; /* duration */
438 double next_event_date = -1.0;
439 double model_next_action_end = -1.0;
441 surf_resource_t resource = NULL;
442 surf_model_t model = NULL;
443 tmgr_trace_event_t event = NULL;
446 if (max_date != -1.0 && max_date != NOW) {
447 min = max_date - NOW;
450 XBT_DEBUG("Looking for next action end for all models except NS3");
451 xbt_dynar_foreach(model_list, iter, model) {
452 if(strcmp(model->name,"network NS3") ){
453 XBT_DEBUG("Running for Resource [%s]", model->name);
454 model_next_action_end = model->model_private->share_resources(NOW);
455 XBT_DEBUG("Resource [%s] : next action end = %f",
456 model->name, model_next_action_end);
457 if (((min < 0.0) || (model_next_action_end < min))
458 && (model_next_action_end >= 0.0))
459 min = model_next_action_end;
463 XBT_DEBUG("Min for resources (except NS3) : %f", min);
465 XBT_DEBUG("Looking for next trace event");
468 XBT_DEBUG("Next TRACE event : %f", next_event_date);
470 next_event_date = tmgr_history_next_date(history);
472 if(surf_network_model->name && !strcmp(surf_network_model->name,"network NS3")){
473 if(next_event_date!=-1.0 && min!=-1.0) {
474 min = MIN(next_event_date - NOW, min);
476 min = MAX(next_event_date - NOW, min);
479 XBT_DEBUG("Run for NS3 at most %f", min);
480 // run until min or next flow
481 model_next_action_end = surf_network_model->model_private->share_resources(min);
483 XBT_DEBUG("Min for NS3 : %f", model_next_action_end);
484 if(model_next_action_end>=0.0)
485 min = model_next_action_end;
488 if (next_event_date == -1.0) break;
490 if ((min != -1.0) && (next_event_date > NOW + min)) break;
492 XBT_DEBUG("Updating models");
494 tmgr_history_get_next_event_leq(history, next_event_date,
496 (void **) &resource))) {
497 if (resource->model->model_private->resource_used(resource)) {
498 min = next_event_date - NOW;
500 ("This event will modify model state. Next event set to %f",
503 /* update state of model_obj according to new value. Does not touch lmm.
504 It will be modified if needed when updating actions */
505 XBT_DEBUG("Calling update_resource_state for resource %s with min %lf",
506 resource->model->name, min);
507 resource->model->model_private->update_resource_state(resource,
513 /* FIXME: Moved this test to here to avoid stoping simulation if there are actions running on cpus and all cpus are with availability = 0.
514 * This may cause an infinite loop if one cpu has a trace with periodicity = 0 and the other a trace with periodicity > 0.
515 * The options are: all traces with same periodicity(0 or >0) or we need to change the way how the events are managed */
519 XBT_DEBUG("Duration set to %f", min);
523 xbt_dynar_foreach(model_list, iter, model)
524 model->model_private->update_actions_state(NOW, min);
527 TRACE_paje_dump_buffer (0);
533 XBT_INLINE double surf_get_clock(void)