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 "src/simix/smx_host_private.h"
13 #include "surf_routing.hpp"
14 #include "simgrid/sg_config.h"
16 #include "virtual_machine.hpp"
18 XBT_LOG_NEW_CATEGORY(surf, "All SURF categories");
19 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
20 "Logging specific to SURF (kernel)");
26 /* model_list_invoke contains only surf_host and surf_vm.
27 * The callback functions of cpu_model and network_model will be called from
28 * those of these host models. */
29 xbt_dynar_t all_existing_models = NULL; /* to destroy models correctly */
30 xbt_dynar_t model_list_invoke = NULL; /* for invoking callbacks */
32 tmgr_history_t history = NULL;
33 lmm_system_t maxmin_system = NULL;
34 xbt_dynar_t surf_path = NULL;
35 xbt_dynar_t host_that_restart = NULL;
36 xbt_dict_t watched_hosts_lib;
41 simgrid::surf::signal<void(void)> surfExitCallbacks;
46 s_surf_model_description_t surf_plugin_description[] = {
47 {"Energy", "Cpu energy consumption.", sg_energy_plugin_init},
48 {NULL, NULL, NULL} /* this array must be NULL terminated */
51 /* Don't forget to update the option description in smx_config when you change
53 s_surf_model_description_t surf_network_model_description[] = {
55 "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). ",
56 surf_network_model_init_LegrandVelho},
58 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
59 surf_network_model_init_Constant},
61 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
62 surf_network_model_init_SMPI},
64 "Realistic network model specifically tailored for HPC settings, with Infiniband contention model",
65 surf_network_model_init_IB},
67 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
68 surf_network_model_init_CM02},
71 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
72 surf_network_model_init_NS3},
75 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
76 surf_network_model_init_Reno},
78 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
79 surf_network_model_init_Reno2},
81 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
82 surf_network_model_init_Vegas},
83 {NULL, NULL, NULL} /* this array must be NULL terminated */
86 s_surf_model_description_t surf_cpu_model_description[] = {
88 "Simplistic CPU model (time=size/power).",
89 surf_cpu_model_init_Cas01},
90 {NULL, NULL, NULL} /* this array must be NULL terminated */
93 s_surf_model_description_t surf_host_model_description[] = {
95 "Default host model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
96 surf_host_model_init_current_default},
98 "Host model that is automatically chosen if you change the network and CPU models",
99 surf_host_model_init_compound},
100 {"ptask_L07", "Host model somehow similar to Cas01+CM02 but allowing parallel tasks",
101 surf_host_model_init_ptask_L07},
102 {NULL, NULL, NULL} /* this array must be NULL terminated */
105 s_surf_model_description_t surf_vm_model_description[] = {
108 surf_vm_model_init_HL13},
109 {NULL, NULL, NULL} /* this array must be NULL terminated */
112 s_surf_model_description_t surf_optimization_mode_description[] = {
114 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
117 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
120 "Full update of remaining and variables. Slow but may be useful when debugging.",
122 {NULL, NULL, NULL} /* this array must be NULL terminated */
125 s_surf_model_description_t surf_storage_model_description[] = {
127 "Simplistic storage model.",
128 surf_storage_model_init_default},
129 {NULL, NULL, NULL} /* this array must be NULL terminated */
132 #ifdef CONTEXT_THREADS
133 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
138 double surf_get_clock(void)
144 # define FILE_DELIM "\\"
146 # define FILE_DELIM "/" /* FIXME: move to better location */
149 FILE *surf_fopen(const char *name, const char *mode)
152 char *path_elm = NULL;
158 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
159 return fopen(name, mode);
161 /* search relative files in the path */
162 xbt_dynar_foreach(surf_path, cpt, path_elm) {
163 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
164 file = fopen(buff, mode);
176 static const char *disk_drives_letter_table[MAX_DRIVE] = {
177 "A:\\","B:\\","C:\\","D:\\","E:\\","F:\\","G:\\","H:\\","I:\\","J:\\","K:\\","L:\\","M:\\",
178 "N:\\","O:\\","P:\\","Q:\\","R:\\","S:\\","T:\\","U:\\","V:\\","W:\\","X:\\","Y:\\","Z:\\"
183 * Returns the initial path. On Windows the initial path is
184 * the current directory for the current process in the other
185 * case the function returns "./" that represents the current
186 * directory on Unix/Linux platforms.
189 const char *__surf_get_initial_path(void)
194 char current_directory[MAX_PATH + 1] = { 0 };
195 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
196 char root[4] = { 0 };
201 strncpy(root, current_directory, 3);
203 for (i = 0; i < MAX_DRIVE; i++) {
204 if (toupper(root[0]) == disk_drives_letter_table[i][0])
205 return disk_drives_letter_table[i];
214 /* The __surf_is_absolute_file_path() returns 1 if
215 * file_path is a absolute file path, in the other
216 * case the function returns 0.
218 int __surf_is_absolute_file_path(const char *file_path)
221 WIN32_FIND_DATA wfd = { 0 };
222 HANDLE hFile = FindFirstFile(file_path, &wfd);
224 if (INVALID_HANDLE_VALUE == hFile)
230 return (file_path[0] == '/');
234 /** Displays the long description of all registered models, and quit */
235 void model_help(const char *category, s_surf_model_description_t * table)
238 printf("Long description of the %s models accepted by this simulator:\n",
240 for (i = 0; table[i].name; i++)
241 printf(" %s: %s\n", table[i].name, table[i].description);
244 int find_model_description(s_surf_model_description_t * table,
248 char *name_list = NULL;
250 for (i = 0; table[i].name; i++)
251 if (!strcmp(name, table[i].name)) {
255 xbt_die("No model is valid! This is a bug.");
256 name_list = xbt_strdup(table[0].name);
257 for (i = 1; table[i].name; i++) {
258 name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3);
259 strcat(name_list, ", ");
260 strcat(name_list, table[i].name);
262 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
266 static XBT_INLINE void routing_asr_prop_free(void *p)
268 //xbt_dict_t elm = (xbt_dict_t) p;
269 //xbt_dict_free(&elm); FIXME: leaking in some case? That's a sometimes double-free with AsCluster::~AsCluster
272 static XBT_INLINE void surf_storage_free(void *r)
274 delete static_cast<simgrid::surf::Storage*>(r);
277 void sg_version_check(int lib_version_major,int lib_version_minor,int lib_version_patch) {
278 if ((lib_version_major != SIMGRID_VERSION_MAJOR) || (lib_version_minor != SIMGRID_VERSION_MINOR)) {
280 "FATAL ERROR: Your program was compiled with SimGrid version %d.%d.%d, "
281 "and then linked against SimGrid %d.%d.%d. Please fix this.\n",
282 SIMGRID_VERSION_MAJOR,SIMGRID_VERSION_MINOR,SIMGRID_VERSION_PATCH,
283 lib_version_major,lib_version_minor,lib_version_patch);
286 if (lib_version_patch != SIMGRID_VERSION_PATCH) {
288 "Warning: Your program was compiled with SimGrid version %d.%d.%d, "
289 "and then linked against SimGrid %d.%d.%d. Proceeding anyway.\n",
290 SIMGRID_VERSION_MAJOR,SIMGRID_VERSION_MINOR,SIMGRID_VERSION_PATCH,
291 lib_version_major,lib_version_minor,lib_version_patch);
295 void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
296 *ver_major = SIMGRID_VERSION_MAJOR;
297 *ver_minor = SIMGRID_VERSION_MINOR;
298 *ver_patch = SIMGRID_VERSION_PATCH;
301 void surf_init(int *argc, char **argv)
303 XBT_DEBUG("Create all Libs");
304 host_list = xbt_dict_new_homogeneous([](void*p) {
305 delete static_cast<simgrid::Host*>(p);
307 as_router_lib = xbt_lib_new();
308 storage_lib = xbt_lib_new();
309 storage_type_lib = xbt_lib_new();
310 file_lib = xbt_lib_new();
311 watched_hosts_lib = xbt_dict_new_homogeneous(NULL);
315 XBT_DEBUG("Add routing levels");
316 ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
318 XBT_DEBUG("Add SURF levels");
319 SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_free);
321 xbt_init(argc, argv);
322 if (!all_existing_models)
323 all_existing_models = xbt_dynar_new(sizeof(simgrid::surf::Model*), NULL);
324 if (!model_list_invoke)
325 model_list_invoke = xbt_dynar_new(sizeof(simgrid::surf::Model*), NULL);
327 history = tmgr_history_new();
329 TRACE_add_start_function(TRACE_surf_alloc);
330 TRACE_add_end_function(TRACE_surf_release);
332 sg_config_init(argc, argv);
341 simgrid::surf::Model *model = NULL;
343 TRACE_end(); /* Just in case it was not called by the upper
344 * layer (or there is no upper layer) */
346 sg_config_finalize();
348 xbt_dynar_free(&host_that_restart);
349 xbt_dynar_free(&surf_path);
351 xbt_dict_free(&host_list);
352 xbt_lib_free(&as_router_lib);
353 xbt_lib_free(&storage_lib);
355 xbt_lib_free(&storage_type_lib);
356 xbt_lib_free(&file_lib);
357 xbt_dict_free(&watched_hosts_lib);
359 xbt_dynar_foreach(all_existing_models, iter, model)
361 xbt_dynar_free(&all_existing_models);
362 xbt_dynar_free(&model_list_invoke);
365 simgrid::surf::surfExitCallbacks();
368 lmm_system_free(maxmin_system);
369 maxmin_system = NULL;
372 tmgr_history_free(history);
376 #ifdef CONTEXT_THREADS
377 xbt_parmap_destroy(surf_parmap);
381 surf_parse_lex_destroy();
382 surf_parse_free_callbacks();
384 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
395 : p_maxminSystem(NULL)
397 p_readyActionSet = new ActionList();
398 p_runningActionSet = new ActionList();
399 p_failedActionSet = new ActionList();
400 p_doneActionSet = new ActionList();
402 p_modifiedSet = NULL;
404 p_updateMechanism = UM_UNDEFINED;
405 m_selectiveUpdate = 0;
409 delete p_readyActionSet;
410 delete p_runningActionSet;
411 delete p_failedActionSet;
412 delete p_doneActionSet;
415 double Model::shareResources(double now)
417 //FIXME: set the good function once and for all
418 if (p_updateMechanism == UM_LAZY)
419 return shareResourcesLazy(now);
420 else if (p_updateMechanism == UM_FULL)
421 return shareResourcesFull(now);
423 xbt_die("Invalid cpu update mechanism!");
426 double Model::shareResourcesLazy(double now)
428 Action *action = NULL;
433 ("Before share resources, the size of modified actions set is %zd",
434 p_modifiedSet->size());
436 lmm_solve(p_maxminSystem);
439 ("After share resources, The size of modified actions set is %zd",
440 p_modifiedSet->size());
442 while(!p_modifiedSet->empty()) {
443 action = &(p_modifiedSet->front());
444 p_modifiedSet->pop_front();
445 int max_dur_flag = 0;
447 if (action->getStateSet() != p_runningActionSet)
450 /* bogus priority, skip it */
451 if (action->getPriority() <= 0 || action->getHat()==LATENCY)
454 action->updateRemainingLazy(now);
457 share = lmm_variable_getvalue(action->getVariable());
460 double time_to_completion;
461 if (action->getRemains() > 0) {
462 time_to_completion = action->getRemainsNoUpdate() / share;
464 time_to_completion = 0.0;
466 min = now + time_to_completion; // when the task will complete if nothing changes
469 if ((action->getMaxDuration() != NO_MAX_DURATION)
471 || action->getStartTime() +
472 action->getMaxDuration() < min)) {
473 min = action->getStartTime() +
474 action->getMaxDuration(); // when the task will complete anyway because of the deadline if any
479 XBT_DEBUG("Action(%p) corresponds to variable %d", action, action->getVariable()->id_int);
481 XBT_DEBUG("Action(%p) Start %f. May finish at %f (got a share of %f). Max_duration %f", action,
482 action->getStartTime(), min, share,
483 action->getMaxDuration());
486 action->heapUpdate(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
487 XBT_DEBUG("Insert at heap action(%p) min %f now %f", action, min,
489 } else DIE_IMPOSSIBLE;
492 //hereafter must have already the min value for this resource model
493 if (xbt_heap_size(p_actionHeap) > 0)
494 min = xbt_heap_maxkey(p_actionHeap) - now;
498 XBT_DEBUG("The minimum with the HEAP %f", min);
503 double Model::shareResourcesFull(double /*now*/) {
507 double Model::shareResourcesMaxMin(ActionList *running_actions,
509 void (*solve) (lmm_system_t))
511 Action *action = NULL;
517 ActionList::iterator it(running_actions->begin()), itend(running_actions->end());
518 for(; it != itend ; ++it) {
520 value = lmm_variable_getvalue(action->getVariable());
521 if ((value > 0) || (action->getMaxDuration() >= 0))
529 if (action->getRemains() > 0)
530 min = action->getRemainsNoUpdate() / value;
533 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min))
534 min = action->getMaxDuration();
536 min = action->getMaxDuration();
539 for (++it; it != itend; ++it) {
541 value = lmm_variable_getvalue(action->getVariable());
543 if (action->getRemains() > 0)
544 value = action->getRemainsNoUpdate() / value;
549 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
552 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min)) {
553 min = action->getMaxDuration();
554 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
557 XBT_DEBUG("min value : %f", min);
562 void Model::updateActionsState(double now, double delta)
564 if (p_updateMechanism == UM_FULL)
565 updateActionsStateFull(now, delta);
566 else if (p_updateMechanism == UM_LAZY)
567 updateActionsStateLazy(now, delta);
569 xbt_die("Invalid cpu update mechanism!");
572 void Model::updateActionsStateLazy(double /*now*/, double /*delta*/)
577 void Model::updateActionsStateFull(double /*now*/, double /*delta*/)
593 : p_name(NULL), p_model(NULL)
594 {} // FIXME: DEADCODE?
596 Resource::Resource(Model *model, const char *name)
597 : Resource(model, name, 1/*SURF_RESOURCE_ON*/)
598 {} // FIXME: DEADCODE?
600 Resource::Resource(Model *model, const char *name, lmm_constraint_t constraint)
601 : Resource(model, name, constraint, 1/*SURF_RESOURCE_ON*/)
604 Resource::Resource(Model *model, const char *name, lmm_constraint_t constraint, int initiallyOn)
605 : p_name(xbt_strdup(name))
607 , m_isOn(initiallyOn)
608 , p_constraint(constraint)
611 Resource::Resource(Model *model, const char *name, int initiallyOn)
612 : p_name(xbt_strdup(name))
614 , m_isOn(initiallyOn)
615 {} // FIXME: DEADCODE?
618 Resource::~Resource() {
619 xbt_free((void*)p_name);
622 bool Resource::isOn() {
625 bool Resource::isOff() {
629 void Resource::turnOn()
636 void Resource::turnOff()
643 Model *Resource::getModel() {
647 const char *Resource::getName() {
651 lmm_constraint_t Resource::getConstraint() {
662 const char *surf_action_state_names[6] = {
664 "SURF_ACTION_RUNNING",
665 "SURF_ACTION_FAILED",
667 "SURF_ACTION_TO_FREE",
668 "SURF_ACTION_NOT_IN_THE_SYSTEM"
671 /* added to manage the communication action's heap */
672 void surf_action_lmm_update_index_heap(void *action, int i) {
673 static_cast<simgrid::surf::Action*>(action)->updateIndexHeap(i);
679 void Action::initialize(simgrid::surf::Model *model, double cost, bool failed,
683 m_start = surf_get_clock();
688 p_stateSet = getModel()->getFailedActionSet();
690 p_stateSet = getModel()->getRunningActionSet();
692 p_stateSet->push_back(*this);
695 Action::Action(simgrid::surf::Model *model, double cost, bool failed)
697 initialize(model, cost, failed);
700 Action::Action(simgrid::surf::Model *model, double cost, bool failed, lmm_variable_t var)
702 initialize(model, cost, failed, var);
706 xbt_free(p_category);
709 void Action::finish() {
710 m_finish = surf_get_clock();
713 e_surf_action_state_t Action::getState()
715 if (p_stateSet == getModel()->getReadyActionSet())
716 return SURF_ACTION_READY;
717 if (p_stateSet == getModel()->getRunningActionSet())
718 return SURF_ACTION_RUNNING;
719 if (p_stateSet == getModel()->getFailedActionSet())
720 return SURF_ACTION_FAILED;
721 if (p_stateSet == getModel()->getDoneActionSet())
722 return SURF_ACTION_DONE;
723 return SURF_ACTION_NOT_IN_THE_SYSTEM;
726 void Action::setState(e_surf_action_state_t state)
728 //surf_action_state_t action_state = &(action->model_type->states);
729 XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
730 p_stateSet->erase(p_stateSet->iterator_to(*this));
731 if (state == SURF_ACTION_READY)
732 p_stateSet = getModel()->getReadyActionSet();
733 else if (state == SURF_ACTION_RUNNING)
734 p_stateSet = getModel()->getRunningActionSet();
735 else if (state == SURF_ACTION_FAILED)
736 p_stateSet = getModel()->getFailedActionSet();
737 else if (state == SURF_ACTION_DONE)
738 p_stateSet = getModel()->getDoneActionSet();
743 p_stateSet->push_back(*this);
747 double Action::getBound()
749 return (p_variable) ? lmm_variable_getbound(p_variable) : 0;
752 void Action::setBound(double bound)
754 XBT_IN("(%p,%g)", this, bound);
756 lmm_update_variable_bound(getModel()->getMaxminSystem(), p_variable, bound);
758 if (getModel()->getUpdateMechanism() == UM_LAZY && getLastUpdate()!=surf_get_clock())
759 heapRemove(getModel()->getActionHeap());
763 double Action::getStartTime()
768 double Action::getFinishTime()
770 /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
771 return m_remains == 0 ? m_finish : -1;
774 void Action::setData(void* data)
779 void Action::setCategory(const char *category)
781 XBT_IN("(%p,%s)", this, category);
782 p_category = xbt_strdup(category);
790 void Action::setMaxDuration(double duration)
792 XBT_IN("(%p,%g)", this, duration);
793 m_maxDuration = duration;
794 if (getModel()->getUpdateMechanism() == UM_LAZY) // remove action from the heap
795 heapRemove(getModel()->getActionHeap());
799 void Action::gapRemove() {}
801 void Action::setPriority(double priority)
803 XBT_IN("(%p,%g)", this, priority);
804 m_priority = priority;
805 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), priority);
807 if (getModel()->getUpdateMechanism() == UM_LAZY)
808 heapRemove(getModel()->getActionHeap());
812 void Action::cancel(){
813 setState(SURF_ACTION_FAILED);
814 if (getModel()->getUpdateMechanism() == UM_LAZY) {
815 if (action_lmm_hook.is_linked())
816 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
817 heapRemove(getModel()->getActionHeap());
824 if (action_hook.is_linked())
825 p_stateSet->erase(p_stateSet->iterator_to(*this));
827 lmm_variable_free(getModel()->getMaxminSystem(), getVariable());
828 if (getModel()->getUpdateMechanism() == UM_LAZY) {
829 /* remove from heap */
830 heapRemove(getModel()->getActionHeap());
831 if (action_lmm_hook.is_linked())
832 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
840 void Action::suspend()
842 XBT_IN("(%p)", this);
843 if (m_suspended != 2) {
844 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), 0.0);
846 if (getModel()->getUpdateMechanism() == UM_LAZY)
847 heapRemove(getModel()->getActionHeap());
852 void Action::resume()
854 XBT_IN("(%p)", this);
855 if (m_suspended != 2) {
856 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), m_priority);
858 if (getModel()->getUpdateMechanism() == UM_LAZY)
859 heapRemove(getModel()->getActionHeap());
864 bool Action::isSuspended()
866 return m_suspended == 1;
868 /* insert action on heap using a given key and a hat (heap_action_type)
869 * a hat can be of three types for communications:
871 * NORMAL = this is a normal heap entry stating the date to finish transmitting
872 * LATENCY = this is a heap entry to warn us when the latency is payed
873 * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
875 void Action::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
878 xbt_heap_push(heap, this, key);
881 void Action::heapRemove(xbt_heap_t heap)
884 if (m_indexHeap >= 0) {
885 xbt_heap_remove(heap, m_indexHeap);
889 void Action::heapUpdate(xbt_heap_t heap, double key, enum heap_action_type hat)
892 if (m_indexHeap >= 0) {
893 xbt_heap_update(heap, m_indexHeap, key);
895 xbt_heap_push(heap, this, key);
899 void Action::updateIndexHeap(int i) {
903 double Action::getRemains()
905 XBT_IN("(%p)", this);
906 /* update remains before return it */
907 if (getModel()->getUpdateMechanism() == UM_LAZY) /* update remains before return it */
908 updateRemainingLazy(surf_get_clock());
913 double Action::getRemainsNoUpdate()
918 //FIXME split code in the right places
919 void Action::updateRemainingLazy(double now)
923 if(getModel() == surf_network_model)
925 if (m_suspended != 0)
930 xbt_assert(p_stateSet == getModel()->getRunningActionSet(),
931 "You're updating an action that is not running.");
933 /* bogus priority, skip it */
934 xbt_assert(m_priority > 0,
935 "You're updating an action that seems suspended.");
938 delta = now - m_lastUpdate;
941 XBT_DEBUG("Updating action(%p): remains was %f, last_update was: %f", this, m_remains, m_lastUpdate);
942 double_update(&m_remains, m_lastValue * delta, sg_surf_precision*sg_maxmin_precision);
944 if (getModel() == surf_cpu_model_pm && TRACE_is_enabled()) {
945 simgrid::surf::Resource *cpu = static_cast<simgrid::surf::Resource*>(
946 lmm_constraint_id(lmm_get_cnst_from_var(getModel()->getMaxminSystem(), getVariable(), 0)));
947 TRACE_surf_host_set_utilization(cpu->getName(), getCategory(), m_lastValue, m_lastUpdate, now - m_lastUpdate);
949 XBT_DEBUG("Updating action(%p): remains is now %f", this, m_remains);
952 if(getModel() == surf_network_model)
954 if (m_maxDuration != NO_MAX_DURATION)
955 double_update(&m_maxDuration, delta, sg_surf_precision);
957 //FIXME: duplicated code
958 if ((m_remains <= 0) &&
959 (lmm_get_variable_weight(getVariable()) > 0)) {
961 setState(SURF_ACTION_DONE);
962 heapRemove(getModel()->getActionHeap());
963 } else if (((m_maxDuration != NO_MAX_DURATION)
964 && (m_maxDuration <= 0))) {
966 setState(SURF_ACTION_DONE);
967 heapRemove(getModel()->getActionHeap());
972 m_lastValue = lmm_variable_getvalue(getVariable());