1 /* Copyright (c) 2004-2015. 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 "surf_interface.hpp"
9 #include "network_interface.hpp"
10 #include "cpu_interface.hpp"
11 #include "host_interface.hpp"
12 #include "simix/smx_host_private.h"
13 #include "surf_routing.hpp"
14 #include "simgrid/sg_config.h"
16 #include "vm_interface.hpp"
19 #pragma warning(disable: 4251)
20 // warning C4251: 'Action::action_hook': class 'boost::intrusive::list_member_hook<void,void,void>' needs to have dll-interface to be used by clients of class 'Action'
21 // No worry, compiler. Nobody will use those hooks from outside the DLL (or they will pay the price for it)
24 XBT_LOG_NEW_CATEGORY(surf, "All SURF categories");
25 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
26 "Logging specific to SURF (kernel)");
32 /* This function is a pimple that we ought to fix. But it won't be easy.
34 * The surf_solve() function does properly return the set of actions that
35 * changed. Instead, each model change a global data, and then the caller of
36 * surf_solve must pick into these sets of action_failed and action_done.
38 * This was not clean but ok as long as we didn't had to restart the processes
39 * when the resource comes back up.
40 * We worked by putting sentinel actions on every resources we are interested
41 * in, so that surf informs us if/when the corresponding resource fails.
43 * But this does not work to get Simix informed of when a resource comes back
44 * up, and this is where this pimple comes. We have a set of resources that are
45 * currently down and for which simix needs to know when it comes back up.
46 * And the current function is called *at every simulation step* to sweep over
47 * that set, searching for a resource that was turned back up in the meanwhile.
48 * This is UGLY and slow.
50 * The proper solution would be to not rely on globals for the action_failed and
51 * action_done swags. They must be passed as parameter by the caller (the
52 * handling of these actions in simix may let you think that these two sets can
53 * be merged, but their handling in SimDag induce the contrary unless this
54 * simdag code can check by itself whether the action is done of failed -- seems
55 * very doable, but yet more cleanup to do).
57 * Once surf_solve() is passed the set of actions that changed, you want to add
58 * a new set of resources back up as parameter to this function. You also want
59 * to add a boolean field "restart_watched" to each resource, and make sure that
60 * whenever a resource with this field enabled comes back up, it's added to that
61 * set so that Simix sees it and react accordingly. This would kill that need
62 * for surf to call simix.
66 /*static void remove_watched_host(void *key)
68 xbt_dict_remove(watched_hosts_lib, *(char**)key);
71 /*void surf_watched_hosts(void)
75 xbt_dict_cursor_t cursor;
76 xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL);
78 XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib");
79 xbt_dict_foreach(watched_hosts_lib, cursor, key, host)
81 if(SIMIX_host_get_state((smx_host_t)host) == SURF_RESOURCE_ON){
82 XBT_INFO("Restart processes on host: %s", SIMIX_host_get_name((smx_host_t)host));
83 SIMIX_host_autorestart((smx_host_t)host);
84 xbt_dynar_push_as(hosts, char*, key);
87 XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key);
89 xbt_dynar_map(hosts, remove_watched_host);
90 xbt_dynar_free(&hosts);
93 /* model_list_invoke contains only surf_host and surf_vm.
94 * The callback functions of cpu_model and network_model will be called from
95 * those of these host models. */
96 xbt_dynar_t model_list = NULL; /* for destroying all models correctly */
97 xbt_dynar_t model_list_invoke = NULL; /* for invoking callbacks */
99 tmgr_history_t history = NULL;
100 lmm_system_t maxmin_system = NULL;
101 xbt_dynar_t surf_path = NULL;
102 xbt_dynar_t host_that_restart = NULL;
103 xbt_dict_t watched_hosts_lib;
105 surf_callback(void, void) surfExitCallbacks;
107 s_surf_model_description_t surf_plugin_description[] = {
108 {"Energy", "Cpu energy consumption.", sg_energy_plugin_init},
109 {NULL, NULL, NULL} /* this array must be NULL terminated */
112 /* Don't forget to update the option description in smx_config when you change
114 s_surf_model_description_t surf_network_model_description[] = {
116 "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). ",
117 surf_network_model_init_LegrandVelho},
119 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
120 surf_network_model_init_Constant},
122 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
123 surf_network_model_init_SMPI},
125 "Realistic network model specifically tailored for HPC settings, with Infiniband contention model",
126 surf_network_model_init_IB},
128 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
129 surf_network_model_init_CM02},
132 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
133 surf_network_model_init_NS3},
136 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
137 surf_network_model_init_Reno},
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_Reno2},
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_Vegas},
144 {NULL, NULL, NULL} /* this array must be NULL terminated */
147 s_surf_model_description_t surf_cpu_model_description[] = {
149 "Simplistic CPU model (time=size/power).",
150 surf_cpu_model_init_Cas01},
151 {NULL, NULL, NULL} /* this array must be NULL terminated */
154 s_surf_model_description_t surf_host_model_description[] = {
156 "Default host model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
157 surf_host_model_init_current_default},
159 "Host model that is automatically chosen if you change the network and CPU models",
160 surf_host_model_init_compound},
161 {"ptask_L07", "Host model somehow similar to Cas01+CM02 but allowing parallel tasks",
162 surf_host_model_init_ptask_L07},
163 {NULL, NULL, NULL} /* this array must be NULL terminated */
166 s_surf_model_description_t surf_vm_model_description[] = {
169 surf_vm_model_init_HL13},
170 {NULL, NULL, NULL} /* this array must be NULL terminated */
173 s_surf_model_description_t surf_optimization_mode_description[] = {
175 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
178 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
181 "Full update of remaining and variables. Slow but may be useful when debugging.",
183 {NULL, NULL, NULL} /* this array must be NULL terminated */
186 s_surf_model_description_t surf_storage_model_description[] = {
188 "Simplistic storage model.",
189 surf_storage_model_init_default},
190 {NULL, NULL, NULL} /* this array must be NULL terminated */
193 #ifdef CONTEXT_THREADS
194 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
199 double surf_get_clock(void)
205 # define FILE_DELIM "\\"
207 # define FILE_DELIM "/" /* FIXME: move to better location */
210 FILE *surf_fopen(const char *name, const char *mode)
213 char *path_elm = NULL;
219 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
220 return fopen(name, mode);
222 /* search relative files in the path */
223 xbt_dynar_foreach(surf_path, cpt, path_elm) {
224 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
225 file = fopen(buff, mode);
237 static const char *disk_drives_letter_table[MAX_DRIVE] = {
238 "A:\\","B:\\","C:\\","D:\\","E:\\","F:\\","G:\\","H:\\","I:\\","J:\\","K:\\","L:\\","M:\\",
239 "N:\\","O:\\","P:\\","Q:\\","R:\\","S:\\","T:\\","U:\\","V:\\","W:\\","X:\\","Y:\\","Z:\\"
244 * Returns the initial path. On Windows the initial path is
245 * the current directory for the current process in the other
246 * case the function returns "./" that represents the current
247 * directory on Unix/Linux platforms.
250 const char *__surf_get_initial_path(void)
255 char current_directory[MAX_PATH + 1] = { 0 };
256 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
257 char root[4] = { 0 };
262 strncpy(root, current_directory, 3);
264 for (i = 0; i < MAX_DRIVE; i++) {
265 if (toupper(root[0]) == disk_drives_letter_table[i][0])
266 return disk_drives_letter_table[i];
275 /* The __surf_is_absolute_file_path() returns 1 if
276 * file_path is a absolute file path, in the other
277 * case the function returns 0.
279 int __surf_is_absolute_file_path(const char *file_path)
282 WIN32_FIND_DATA wfd = { 0 };
283 HANDLE hFile = FindFirstFile(file_path, &wfd);
285 if (INVALID_HANDLE_VALUE == hFile)
291 return (file_path[0] == '/');
295 /** Displays the long description of all registered models, and quit */
296 void model_help(const char *category, s_surf_model_description_t * table)
299 printf("Long description of the %s models accepted by this simulator:\n",
301 for (i = 0; table[i].name; i++)
302 printf(" %s: %s\n", table[i].name, table[i].description);
305 int find_model_description(s_surf_model_description_t * table,
309 char *name_list = NULL;
311 for (i = 0; table[i].name; i++)
312 if (!strcmp(name, table[i].name)) {
316 xbt_die("No model is valid! This is a bug.");
317 name_list = xbt_strdup(table[0].name);
318 for (i = 1; table[i].name; i++) {
319 name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3);
320 strcat(name_list, ", ");
321 strcat(name_list, table[i].name);
323 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
327 static XBT_INLINE void routing_asr_prop_free(void *p)
329 //xbt_dict_t elm = (xbt_dict_t) p;
330 //xbt_dict_free(&elm); FIXME: leaking in some case? That's a sometimes double-free with AsCluster::~AsCluster
333 static XBT_INLINE void surf_host_free(void *r)
335 delete static_cast<Host*>(r);
338 static XBT_INLINE void surf_storage_free(void *r)
340 delete static_cast<Storage*>(r);
343 void sg_version_check(int lib_version_major,int lib_version_minor,int lib_version_patch) {
344 if ((lib_version_major != SIMGRID_VERSION_MAJOR) || (lib_version_minor != SIMGRID_VERSION_MINOR)) {
346 "FATAL ERROR: Your program was compiled with SimGrid version %d.%d.%d, "
347 "and then linked against SimGrid %d.%d.%d. Please fix this.\n",
348 SIMGRID_VERSION_MAJOR,SIMGRID_VERSION_MINOR,SIMGRID_VERSION_PATCH,
349 lib_version_major,lib_version_minor,lib_version_patch);
352 if (lib_version_patch != SIMGRID_VERSION_PATCH) {
354 "Warning: Your program was compiled with SimGrid version %d.%d.%d, "
355 "and then linked against SimGrid %d.%d.%d. Proceeding anyway.\n",
356 SIMGRID_VERSION_MAJOR,SIMGRID_VERSION_MINOR,SIMGRID_VERSION_PATCH,
357 lib_version_major,lib_version_minor,lib_version_patch);
361 void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
362 *ver_major = SIMGRID_VERSION_MAJOR;
363 *ver_minor = SIMGRID_VERSION_MINOR;
364 *ver_patch = SIMGRID_VERSION_PATCH;
367 void surf_init(int *argc, char **argv)
369 XBT_DEBUG("Create all Libs");
370 host_lib = xbt_lib_new();
371 as_router_lib = xbt_lib_new();
372 storage_lib = xbt_lib_new();
373 storage_type_lib = xbt_lib_new();
374 file_lib = xbt_lib_new();
375 watched_hosts_lib = xbt_dict_new_homogeneous(NULL);
379 XBT_DEBUG("Add routing levels");
380 ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
382 XBT_DEBUG("Add SURF levels");
383 SURF_HOST_LEVEL = xbt_lib_add_level(host_lib,surf_host_free);
384 SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_free);
386 xbt_init(argc, argv);
388 model_list = xbt_dynar_new(sizeof(Model*), NULL);
389 if (!model_list_invoke)
390 model_list_invoke = xbt_dynar_new(sizeof(Model*), NULL);
392 history = tmgr_history_new();
394 TRACE_add_start_function(TRACE_surf_alloc);
395 TRACE_add_end_function(TRACE_surf_release);
397 sg_config_init(argc, argv);
408 TRACE_end(); /* Just in case it was not called by the upper
409 * layer (or there is no upper layer) */
411 sg_config_finalize();
413 xbt_dynar_free(&host_that_restart);
414 xbt_dynar_free(&surf_path);
416 xbt_lib_free(&host_lib);
417 xbt_lib_free(&as_router_lib);
418 xbt_lib_free(&storage_lib);
420 xbt_lib_free(&storage_type_lib);
421 xbt_lib_free(&file_lib);
422 xbt_dict_free(&watched_hosts_lib);
424 xbt_dynar_foreach(model_list, iter, model)
426 xbt_dynar_free(&model_list);
427 xbt_dynar_free(&model_list_invoke);
430 surf_callback_emit(surfExitCallbacks);
433 lmm_system_free(maxmin_system);
434 maxmin_system = NULL;
437 tmgr_history_free(history);
441 #ifdef CONTEXT_THREADS
442 xbt_parmap_destroy(surf_parmap);
446 surf_parse_lex_destroy();
447 surf_parse_free_callbacks();
449 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
457 : p_maxminSystem(NULL)
459 p_readyActionSet = new ActionList();
460 p_runningActionSet = new ActionList();
461 p_failedActionSet = new ActionList();
462 p_doneActionSet = new ActionList();
464 p_modifiedSet = NULL;
466 p_updateMechanism = UM_UNDEFINED;
467 m_selectiveUpdate = 0;
471 delete p_readyActionSet;
472 delete p_runningActionSet;
473 delete p_failedActionSet;
474 delete p_doneActionSet;
477 double Model::shareResources(double now)
479 //FIXME: set the good function once and for all
480 if (p_updateMechanism == UM_LAZY)
481 return shareResourcesLazy(now);
482 else if (p_updateMechanism == UM_FULL)
483 return shareResourcesFull(now);
485 xbt_die("Invalid cpu update mechanism!");
488 double Model::shareResourcesLazy(double now)
490 Action *action = NULL;
495 ("Before share resources, the size of modified actions set is %zd",
496 p_modifiedSet->size());
498 lmm_solve(p_maxminSystem);
501 ("After share resources, The size of modified actions set is %zd",
502 p_modifiedSet->size());
504 while(!p_modifiedSet->empty()) {
505 action = &(p_modifiedSet->front());
506 p_modifiedSet->pop_front();
507 int max_dur_flag = 0;
509 if (action->getStateSet() != p_runningActionSet)
512 /* bogus priority, skip it */
513 if (action->getPriority() <= 0 || action->getHat()==LATENCY)
516 action->updateRemainingLazy(now);
519 share = lmm_variable_getvalue(action->getVariable());
522 double time_to_completion;
523 if (action->getRemains() > 0) {
524 time_to_completion = action->getRemainsNoUpdate() / share;
526 time_to_completion = 0.0;
528 min = now + time_to_completion; // when the task will complete if nothing changes
531 if ((action->getMaxDuration() != NO_MAX_DURATION)
533 || action->getStartTime() +
534 action->getMaxDuration() < min)) {
535 min = action->getStartTime() +
536 action->getMaxDuration(); // when the task will complete anyway because of the deadline if any
541 XBT_DEBUG("Action(%p) corresponds to variable %d", action, action->getVariable()->id_int);
543 XBT_DEBUG("Action(%p) Start %f. May finish at %f (got a share of %f). Max_duration %f", action,
544 action->getStartTime(), min, share,
545 action->getMaxDuration());
548 action->heapUpdate(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
549 XBT_DEBUG("Insert at heap action(%p) min %f now %f", action, min,
551 } else DIE_IMPOSSIBLE;
554 //hereafter must have already the min value for this resource model
555 if (xbt_heap_size(p_actionHeap) > 0)
556 min = xbt_heap_maxkey(p_actionHeap) - now;
560 XBT_DEBUG("The minimum with the HEAP %f", min);
565 double Model::shareResourcesFull(double /*now*/) {
569 double Model::shareResourcesMaxMin(ActionList *running_actions,
571 void (*solve) (lmm_system_t))
573 Action *action = NULL;
579 ActionList::iterator it(running_actions->begin()), itend(running_actions->end());
580 for(; it != itend ; ++it) {
582 value = lmm_variable_getvalue(action->getVariable());
583 if ((value > 0) || (action->getMaxDuration() >= 0))
591 if (action->getRemains() > 0)
592 min = action->getRemainsNoUpdate() / value;
595 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min))
596 min = action->getMaxDuration();
598 min = action->getMaxDuration();
601 for (++it; it != itend; ++it) {
603 value = lmm_variable_getvalue(action->getVariable());
605 if (action->getRemains() > 0)
606 value = action->getRemainsNoUpdate() / value;
611 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
614 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min)) {
615 min = action->getMaxDuration();
616 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
619 XBT_DEBUG("min value : %f", min);
624 void Model::updateActionsState(double now, double delta)
626 if (p_updateMechanism == UM_FULL)
627 updateActionsStateFull(now, delta);
628 else if (p_updateMechanism == UM_LAZY)
629 updateActionsStateLazy(now, delta);
631 xbt_die("Invalid cpu update mechanism!");
634 void Model::updateActionsStateLazy(double /*now*/, double /*delta*/)
639 void Model::updateActionsStateFull(double /*now*/, double /*delta*/)
649 : p_name(NULL), p_properties(NULL), p_model(NULL)
652 Resource::Resource(Model *model, const char *name, xbt_dict_t props)
653 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
654 , m_running(true), m_stateCurrent(SURF_RESOURCE_ON)
657 Resource::Resource(Model *model, const char *name, xbt_dict_t props, lmm_constraint_t constraint)
658 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
659 , m_running(true), m_stateCurrent(SURF_RESOURCE_ON), p_constraint(constraint)
662 Resource::Resource(Model *model, const char *name, xbt_dict_t props, e_surf_resource_state_t stateInit)
663 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
664 , m_running(true), m_stateCurrent(stateInit)
667 Resource::~Resource() {
668 xbt_free((void*)p_name);
669 xbt_dict_free(&p_properties);
672 e_surf_resource_state_t Resource::getState()
674 return m_stateCurrent;
677 void Resource::setState(e_surf_resource_state_t state)
679 m_stateCurrent = state;
682 bool Resource::isOn()
687 void Resource::turnOn()
694 void Resource::turnOff()
701 Model *Resource::getModel() {
705 const char *Resource::getName() {
709 xbt_dict_t Resource::getProperties() {
710 if (p_properties==NULL)
711 p_properties = xbt_dict_new();
715 lmm_constraint_t Resource::getConstraint() {
723 const char *surf_action_state_names[6] = {
725 "SURF_ACTION_RUNNING",
726 "SURF_ACTION_FAILED",
728 "SURF_ACTION_TO_FREE",
729 "SURF_ACTION_NOT_IN_THE_SYSTEM"
732 void Action::initialize(Model *model, double cost, bool failed,
738 m_maxDuration = NO_MAX_DURATION;
740 m_start = surf_get_clock();
750 p_stateHookup.prev = 0;
751 p_stateHookup.next = 0;
753 p_stateSet = getModel()->getFailedActionSet();
755 p_stateSet = getModel()->getRunningActionSet();
757 p_stateSet->push_back(*this);
760 Action::Action(Model *model, double cost, bool failed)
762 initialize(model, cost, failed);
765 Action::Action(Model *model, double cost, bool failed, lmm_variable_t var)
767 initialize(model, cost, failed, var);
771 xbt_free(p_category);
774 void Action::finish() {
775 m_finish = surf_get_clock();
778 e_surf_action_state_t Action::getState()
780 if (p_stateSet == getModel()->getReadyActionSet())
781 return SURF_ACTION_READY;
782 if (p_stateSet == getModel()->getRunningActionSet())
783 return SURF_ACTION_RUNNING;
784 if (p_stateSet == getModel()->getFailedActionSet())
785 return SURF_ACTION_FAILED;
786 if (p_stateSet == getModel()->getDoneActionSet())
787 return SURF_ACTION_DONE;
788 return SURF_ACTION_NOT_IN_THE_SYSTEM;
791 void Action::setState(e_surf_action_state_t state)
793 //surf_action_state_t action_state = &(action->model_type->states);
794 XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
795 p_stateSet->erase(p_stateSet->iterator_to(*this));
796 if (state == SURF_ACTION_READY)
797 p_stateSet = getModel()->getReadyActionSet();
798 else if (state == SURF_ACTION_RUNNING)
799 p_stateSet = getModel()->getRunningActionSet();
800 else if (state == SURF_ACTION_FAILED)
801 p_stateSet = getModel()->getFailedActionSet();
802 else if (state == SURF_ACTION_DONE)
803 p_stateSet = getModel()->getDoneActionSet();
808 p_stateSet->push_back(*this);
812 double Action::getBound()
814 return (p_variable) ? lmm_variable_getbound(p_variable) : 0;
817 void Action::setBound(double bound)
819 XBT_IN("(%p,%g)", this, bound);
821 lmm_update_variable_bound(getModel()->getMaxminSystem(), p_variable, bound);
823 if (getModel()->getUpdateMechanism() == UM_LAZY && getLastUpdate()!=surf_get_clock())
824 heapRemove(getModel()->getActionHeap());
828 double Action::getStartTime()
833 double Action::getFinishTime()
835 /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
836 return m_remains == 0 ? m_finish : -1;
839 void Action::setData(void* data)
844 void Action::setCategory(const char *category)
846 XBT_IN("(%p,%s)", this, category);
847 p_category = xbt_strdup(category);
855 void Action::setMaxDuration(double duration)
857 XBT_IN("(%p,%g)", this, duration);
858 m_maxDuration = duration;
859 if (getModel()->getUpdateMechanism() == UM_LAZY) // remove action from the heap
860 heapRemove(getModel()->getActionHeap());
864 void Action::gapRemove() {}
866 void Action::setPriority(double priority)
868 XBT_IN("(%p,%g)", this, priority);
869 m_priority = priority;
870 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), priority);
872 if (getModel()->getUpdateMechanism() == UM_LAZY)
873 heapRemove(getModel()->getActionHeap());
877 void Action::cancel(){
878 setState(SURF_ACTION_FAILED);
879 if (getModel()->getUpdateMechanism() == UM_LAZY) {
880 if (action_lmm_hook.is_linked())
881 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
882 heapRemove(getModel()->getActionHeap());
889 if (action_hook.is_linked())
890 p_stateSet->erase(p_stateSet->iterator_to(*this));
892 lmm_variable_free(getModel()->getMaxminSystem(), getVariable());
893 if (getModel()->getUpdateMechanism() == UM_LAZY) {
894 /* remove from heap */
895 heapRemove(getModel()->getActionHeap());
896 if (action_lmm_hook.is_linked())
897 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
905 void Action::suspend()
907 XBT_IN("(%p)", this);
908 if (m_suspended != 2) {
909 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), 0.0);
911 if (getModel()->getUpdateMechanism() == UM_LAZY)
912 heapRemove(getModel()->getActionHeap());
917 void Action::resume()
919 XBT_IN("(%p)", this);
920 if (m_suspended != 2) {
921 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), m_priority);
923 if (getModel()->getUpdateMechanism() == UM_LAZY)
924 heapRemove(getModel()->getActionHeap());
929 bool Action::isSuspended()
931 return m_suspended == 1;
933 /* insert action on heap using a given key and a hat (heap_action_type)
934 * a hat can be of three types for communications:
936 * NORMAL = this is a normal heap entry stating the date to finish transmitting
937 * LATENCY = this is a heap entry to warn us when the latency is payed
938 * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
940 void Action::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
943 xbt_heap_push(heap, this, key);
946 void Action::heapRemove(xbt_heap_t heap)
949 if (m_indexHeap >= 0) {
950 xbt_heap_remove(heap, m_indexHeap);
954 void Action::heapUpdate(xbt_heap_t heap, double key, enum heap_action_type hat)
957 if (m_indexHeap >= 0) {
958 xbt_heap_update(heap, m_indexHeap, key);
960 xbt_heap_push(heap, this, key);
964 /* added to manage the communication action's heap */
965 void surf_action_lmm_update_index_heap(void *action, int i) {
966 static_cast<Action*>(action)->updateIndexHeap(i);
969 void Action::updateIndexHeap(int i) {
973 double Action::getRemains()
975 XBT_IN("(%p)", this);
976 /* update remains before return it */
977 if (getModel()->getUpdateMechanism() == UM_LAZY) /* update remains before return it */
978 updateRemainingLazy(surf_get_clock());
983 double Action::getRemainsNoUpdate()
988 //FIXME split code in the right places
989 void Action::updateRemainingLazy(double now)
993 if(getModel() == surf_network_model)
995 if (m_suspended != 0)
1000 xbt_assert(p_stateSet == getModel()->getRunningActionSet(),
1001 "You're updating an action that is not running.");
1003 /* bogus priority, skip it */
1004 xbt_assert(m_priority > 0,
1005 "You're updating an action that seems suspended.");
1008 delta = now - m_lastUpdate;
1010 if (m_remains > 0) {
1011 XBT_DEBUG("Updating action(%p): remains was %f, last_update was: %f", this, m_remains, m_lastUpdate);
1012 double_update(&m_remains, m_lastValue * delta, sg_surf_precision*sg_maxmin_precision);
1014 if (getModel() == surf_cpu_model_pm && TRACE_is_enabled()) {
1015 Resource *cpu = static_cast<Resource*>(lmm_constraint_id(lmm_get_cnst_from_var(getModel()->getMaxminSystem(), getVariable(), 0)));
1016 TRACE_surf_host_set_utilization(cpu->getName(), getCategory(), m_lastValue, m_lastUpdate, now - m_lastUpdate);
1018 XBT_DEBUG("Updating action(%p): remains is now %f", this, m_remains);
1021 if(getModel() == surf_network_model)
1023 if (m_maxDuration != NO_MAX_DURATION)
1024 double_update(&m_maxDuration, delta, sg_surf_precision);
1026 //FIXME: duplicated code
1027 if ((m_remains <= 0) &&
1028 (lmm_get_variable_weight(getVariable()) > 0)) {
1030 setState(SURF_ACTION_DONE);
1031 heapRemove(getModel()->getActionHeap());
1032 } else if (((m_maxDuration != NO_MAX_DURATION)
1033 && (m_maxDuration <= 0))) {
1035 setState(SURF_ACTION_DONE);
1036 heapRemove(getModel()->getActionHeap());
1041 m_lastValue = lmm_variable_getvalue(getVariable());