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::xbt::signal<void(void)> surfExitCallbacks;
46 #include <simgrid/plugins/energy.h> // FIXME: this plugin should not be linked to the core
48 s_surf_model_description_t surf_plugin_description[] = {
49 {"Energy", "Cpu energy consumption.", sg_energy_plugin_init},
50 {NULL, NULL, NULL} /* this array must be NULL terminated */
53 /* Don't forget to update the option description in smx_config when you change
55 s_surf_model_description_t surf_network_model_description[] = {
57 "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). ",
58 surf_network_model_init_LegrandVelho},
60 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
61 surf_network_model_init_Constant},
63 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
64 surf_network_model_init_SMPI},
66 "Realistic network model specifically tailored for HPC settings, with Infiniband contention model",
67 surf_network_model_init_IB},
69 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
70 surf_network_model_init_CM02},
73 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
74 surf_network_model_init_NS3},
77 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
78 surf_network_model_init_Reno},
80 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
81 surf_network_model_init_Reno2},
83 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
84 surf_network_model_init_Vegas},
85 {NULL, NULL, NULL} /* this array must be NULL terminated */
88 s_surf_model_description_t surf_cpu_model_description[] = {
90 "Simplistic CPU model (time=size/power).",
91 surf_cpu_model_init_Cas01},
92 {NULL, NULL, NULL} /* this array must be NULL terminated */
95 s_surf_model_description_t surf_host_model_description[] = {
97 "Default host model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
98 surf_host_model_init_current_default},
100 "Host model that is automatically chosen if you change the network and CPU models",
101 surf_host_model_init_compound},
102 {"ptask_L07", "Host model somehow similar to Cas01+CM02 but allowing parallel tasks",
103 surf_host_model_init_ptask_L07},
104 {NULL, NULL, NULL} /* this array must be NULL terminated */
107 s_surf_model_description_t surf_vm_model_description[] = {
110 surf_vm_model_init_HL13},
111 {NULL, NULL, NULL} /* this array must be NULL terminated */
114 s_surf_model_description_t surf_optimization_mode_description[] = {
116 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
119 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
122 "Full update of remaining and variables. Slow but may be useful when debugging.",
124 {NULL, NULL, NULL} /* this array must be NULL terminated */
127 s_surf_model_description_t surf_storage_model_description[] = {
129 "Simplistic storage model.",
130 surf_storage_model_init_default},
131 {NULL, NULL, NULL} /* this array must be NULL terminated */
134 #ifdef CONTEXT_THREADS
135 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
140 double surf_get_clock(void)
146 # define FILE_DELIM "\\"
148 # define FILE_DELIM "/" /* FIXME: move to better location */
151 FILE *surf_fopen(const char *name, const char *mode)
154 char *path_elm = NULL;
160 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
161 return fopen(name, mode);
163 /* search relative files in the path */
164 xbt_dynar_foreach(surf_path, cpt, path_elm) {
165 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
166 file = fopen(buff, mode);
178 static const char *disk_drives_letter_table[MAX_DRIVE] = {
179 "A:\\","B:\\","C:\\","D:\\","E:\\","F:\\","G:\\","H:\\","I:\\","J:\\","K:\\","L:\\","M:\\",
180 "N:\\","O:\\","P:\\","Q:\\","R:\\","S:\\","T:\\","U:\\","V:\\","W:\\","X:\\","Y:\\","Z:\\"
185 * Returns the initial path. On Windows the initial path is
186 * the current directory for the current process in the other
187 * case the function returns "./" that represents the current
188 * directory on Unix/Linux platforms.
191 const char *__surf_get_initial_path(void)
196 char current_directory[MAX_PATH + 1] = { 0 };
197 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
198 char root[4] = { 0 };
203 strncpy(root, current_directory, 3);
205 for (i = 0; i < MAX_DRIVE; i++) {
206 if (toupper(root[0]) == disk_drives_letter_table[i][0])
207 return disk_drives_letter_table[i];
216 /* The __surf_is_absolute_file_path() returns 1 if
217 * file_path is a absolute file path, in the other
218 * case the function returns 0.
220 int __surf_is_absolute_file_path(const char *file_path)
223 WIN32_FIND_DATA wfd = { 0 };
224 HANDLE hFile = FindFirstFile(file_path, &wfd);
226 if (INVALID_HANDLE_VALUE == hFile)
232 return (file_path[0] == '/');
236 /** Displays the long description of all registered models, and quit */
237 void model_help(const char *category, s_surf_model_description_t * table)
240 printf("Long description of the %s models accepted by this simulator:\n",
242 for (i = 0; table[i].name; i++)
243 printf(" %s: %s\n", table[i].name, table[i].description);
246 int find_model_description(s_surf_model_description_t * table,
250 char *name_list = NULL;
252 for (i = 0; table[i].name; i++)
253 if (!strcmp(name, table[i].name)) {
257 xbt_die("No model is valid! This is a bug.");
258 name_list = xbt_strdup(table[0].name);
259 for (i = 1; table[i].name; i++) {
260 name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3);
261 strcat(name_list, ", ");
262 strcat(name_list, table[i].name);
264 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
268 static XBT_INLINE void routing_asr_prop_free(void *p)
270 //xbt_dict_t elm = (xbt_dict_t) p;
271 //xbt_dict_free(&elm); FIXME: leaking in some case? That's a sometimes double-free with AsCluster::~AsCluster
274 static XBT_INLINE void surf_storage_free(void *r)
276 delete static_cast<simgrid::surf::Storage*>(r);
279 void sg_version_check(int lib_version_major,int lib_version_minor,int lib_version_patch) {
280 if ((lib_version_major != SIMGRID_VERSION_MAJOR) || (lib_version_minor != SIMGRID_VERSION_MINOR)) {
282 "FATAL ERROR: Your program was compiled with SimGrid version %d.%d.%d, "
283 "and then linked against SimGrid %d.%d.%d. Please fix this.\n",
284 SIMGRID_VERSION_MAJOR,SIMGRID_VERSION_MINOR,SIMGRID_VERSION_PATCH,
285 lib_version_major,lib_version_minor,lib_version_patch);
288 if (lib_version_patch != SIMGRID_VERSION_PATCH) {
290 "Warning: Your program was compiled with SimGrid version %d.%d.%d, "
291 "and then linked against SimGrid %d.%d.%d. Proceeding anyway.\n",
292 SIMGRID_VERSION_MAJOR,SIMGRID_VERSION_MINOR,SIMGRID_VERSION_PATCH,
293 lib_version_major,lib_version_minor,lib_version_patch);
297 void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
298 *ver_major = SIMGRID_VERSION_MAJOR;
299 *ver_minor = SIMGRID_VERSION_MINOR;
300 *ver_patch = SIMGRID_VERSION_PATCH;
303 void surf_init(int *argc, char **argv)
305 XBT_DEBUG("Create all Libs");
306 host_list = xbt_dict_new_homogeneous([](void*p) {
307 simgrid::s4u::Host* host = static_cast<simgrid::s4u::Host*>(p);
308 simgrid::s4u::Host::onDestruction(*host);
311 as_router_lib = xbt_lib_new();
312 storage_lib = xbt_lib_new();
313 storage_type_lib = xbt_lib_new();
314 file_lib = xbt_lib_new();
315 watched_hosts_lib = xbt_dict_new_homogeneous(NULL);
319 XBT_DEBUG("Add routing levels");
320 ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
322 XBT_DEBUG("Add SURF levels");
323 simgrid::surf::Host::classInit();
324 SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_free);
326 xbt_init(argc, argv);
327 if (!all_existing_models)
328 all_existing_models = xbt_dynar_new(sizeof(simgrid::surf::Model*), NULL);
329 if (!model_list_invoke)
330 model_list_invoke = xbt_dynar_new(sizeof(simgrid::surf::Model*), NULL);
332 history = tmgr_history_new();
334 TRACE_add_start_function(TRACE_surf_alloc);
335 TRACE_add_end_function(TRACE_surf_release);
337 sg_config_init(argc, argv);
346 simgrid::surf::Model *model = NULL;
348 TRACE_end(); /* Just in case it was not called by the upper
349 * layer (or there is no upper layer) */
351 sg_config_finalize();
353 xbt_dynar_free(&host_that_restart);
354 xbt_dynar_free(&surf_path);
356 xbt_dict_free(&host_list);
357 xbt_lib_free(&as_router_lib);
358 xbt_lib_free(&storage_lib);
360 xbt_lib_free(&storage_type_lib);
361 xbt_lib_free(&file_lib);
362 xbt_dict_free(&watched_hosts_lib);
364 xbt_dynar_foreach(all_existing_models, iter, model)
366 xbt_dynar_free(&all_existing_models);
367 xbt_dynar_free(&model_list_invoke);
370 simgrid::surf::surfExitCallbacks();
373 lmm_system_free(maxmin_system);
374 maxmin_system = NULL;
377 tmgr_history_free(history);
381 #ifdef CONTEXT_THREADS
382 xbt_parmap_destroy(surf_parmap);
386 surf_parse_lex_destroy();
387 surf_parse_free_callbacks();
389 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
400 : p_maxminSystem(NULL)
402 p_readyActionSet = new ActionList();
403 p_runningActionSet = new ActionList();
404 p_failedActionSet = new ActionList();
405 p_doneActionSet = new ActionList();
407 p_modifiedSet = NULL;
409 p_updateMechanism = UM_UNDEFINED;
410 m_selectiveUpdate = 0;
414 delete p_readyActionSet;
415 delete p_runningActionSet;
416 delete p_failedActionSet;
417 delete p_doneActionSet;
420 double Model::shareResources(double now)
422 //FIXME: set the good function once and for all
423 if (p_updateMechanism == UM_LAZY)
424 return shareResourcesLazy(now);
425 else if (p_updateMechanism == UM_FULL)
426 return shareResourcesFull(now);
428 xbt_die("Invalid cpu update mechanism!");
431 double Model::shareResourcesLazy(double now)
433 Action *action = NULL;
438 ("Before share resources, the size of modified actions set is %zd",
439 p_modifiedSet->size());
441 lmm_solve(p_maxminSystem);
444 ("After share resources, The size of modified actions set is %zd",
445 p_modifiedSet->size());
447 while(!p_modifiedSet->empty()) {
448 action = &(p_modifiedSet->front());
449 p_modifiedSet->pop_front();
450 int max_dur_flag = 0;
452 if (action->getStateSet() != p_runningActionSet)
455 /* bogus priority, skip it */
456 if (action->getPriority() <= 0 || action->getHat()==LATENCY)
459 action->updateRemainingLazy(now);
462 share = lmm_variable_getvalue(action->getVariable());
465 double time_to_completion;
466 if (action->getRemains() > 0) {
467 time_to_completion = action->getRemainsNoUpdate() / share;
469 time_to_completion = 0.0;
471 min = now + time_to_completion; // when the task will complete if nothing changes
474 if ((action->getMaxDuration() != NO_MAX_DURATION)
476 || action->getStartTime() +
477 action->getMaxDuration() < min)) {
478 min = action->getStartTime() +
479 action->getMaxDuration(); // when the task will complete anyway because of the deadline if any
484 XBT_DEBUG("Action(%p) corresponds to variable %d", action, action->getVariable()->id_int);
486 XBT_DEBUG("Action(%p) Start %f. May finish at %f (got a share of %f). Max_duration %f", action,
487 action->getStartTime(), min, share,
488 action->getMaxDuration());
491 action->heapUpdate(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
492 XBT_DEBUG("Insert at heap action(%p) min %f now %f", action, min,
494 } else DIE_IMPOSSIBLE;
497 //hereafter must have already the min value for this resource model
498 if (xbt_heap_size(p_actionHeap) > 0)
499 min = xbt_heap_maxkey(p_actionHeap) - now;
503 XBT_DEBUG("The minimum with the HEAP %f", min);
508 double Model::shareResourcesFull(double /*now*/) {
512 double Model::shareResourcesMaxMin(ActionList *running_actions,
514 void (*solve) (lmm_system_t))
516 Action *action = NULL;
522 ActionList::iterator it(running_actions->begin()), itend(running_actions->end());
523 for(; it != itend ; ++it) {
525 value = lmm_variable_getvalue(action->getVariable());
526 if ((value > 0) || (action->getMaxDuration() >= 0))
534 if (action->getRemains() > 0)
535 min = action->getRemainsNoUpdate() / value;
538 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min))
539 min = action->getMaxDuration();
541 min = action->getMaxDuration();
544 for (++it; it != itend; ++it) {
546 value = lmm_variable_getvalue(action->getVariable());
548 if (action->getRemains() > 0)
549 value = action->getRemainsNoUpdate() / value;
554 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
557 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min)) {
558 min = action->getMaxDuration();
559 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
562 XBT_DEBUG("min value : %f", min);
567 void Model::updateActionsState(double now, double delta)
569 if (p_updateMechanism == UM_FULL)
570 updateActionsStateFull(now, delta);
571 else if (p_updateMechanism == UM_LAZY)
572 updateActionsStateLazy(now, delta);
574 xbt_die("Invalid cpu update mechanism!");
577 void Model::updateActionsStateLazy(double /*now*/, double /*delta*/)
582 void Model::updateActionsStateFull(double /*now*/, double /*delta*/)
597 Resource::Resource(Model *model, const char *name)
598 : Resource(model, name, 1/*ON*/)
601 Resource::Resource(Model *model, const char *name, lmm_constraint_t constraint)
602 : Resource(model, name, constraint, 1/*ON*/)
605 Resource::Resource(Model *model, const char *name, lmm_constraint_t constraint, int initiallyOn)
606 : p_name(xbt_strdup(name))
608 , m_isOn(initiallyOn)
609 , p_constraint(constraint)
612 Resource::Resource(Model *model, const char *name, int initiallyOn)
613 : p_name(xbt_strdup(name))
615 , m_isOn(initiallyOn)
619 Resource::~Resource() {
620 xbt_free((void*)p_name);
623 bool Resource::isOn() {
626 bool Resource::isOff() {
630 void Resource::turnOn()
637 void Resource::turnOff()
644 Model *Resource::getModel() {
648 const char *Resource::getName() {
652 lmm_constraint_t Resource::getConstraint() {
663 const char *surf_action_state_names[6] = {
665 "SURF_ACTION_RUNNING",
666 "SURF_ACTION_FAILED",
668 "SURF_ACTION_TO_FREE",
669 "SURF_ACTION_NOT_IN_THE_SYSTEM"
672 /* added to manage the communication action's heap */
673 void surf_action_lmm_update_index_heap(void *action, int i) {
674 static_cast<simgrid::surf::Action*>(action)->updateIndexHeap(i);
680 void Action::initialize(simgrid::surf::Model *model, double cost, bool failed,
684 m_start = surf_get_clock();
689 p_stateSet = getModel()->getFailedActionSet();
691 p_stateSet = getModel()->getRunningActionSet();
693 p_stateSet->push_back(*this);
696 Action::Action(simgrid::surf::Model *model, double cost, bool failed)
698 initialize(model, cost, failed);
701 Action::Action(simgrid::surf::Model *model, double cost, bool failed, lmm_variable_t var)
703 initialize(model, cost, failed, var);
707 xbt_free(p_category);
710 void Action::finish() {
711 m_finish = surf_get_clock();
714 e_surf_action_state_t Action::getState()
716 if (p_stateSet == getModel()->getReadyActionSet())
717 return SURF_ACTION_READY;
718 if (p_stateSet == getModel()->getRunningActionSet())
719 return SURF_ACTION_RUNNING;
720 if (p_stateSet == getModel()->getFailedActionSet())
721 return SURF_ACTION_FAILED;
722 if (p_stateSet == getModel()->getDoneActionSet())
723 return SURF_ACTION_DONE;
724 return SURF_ACTION_NOT_IN_THE_SYSTEM;
727 void Action::setState(e_surf_action_state_t state)
729 //surf_action_state_t action_state = &(action->model_type->states);
730 XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
731 p_stateSet->erase(p_stateSet->iterator_to(*this));
732 if (state == SURF_ACTION_READY)
733 p_stateSet = getModel()->getReadyActionSet();
734 else if (state == SURF_ACTION_RUNNING)
735 p_stateSet = getModel()->getRunningActionSet();
736 else if (state == SURF_ACTION_FAILED)
737 p_stateSet = getModel()->getFailedActionSet();
738 else if (state == SURF_ACTION_DONE)
739 p_stateSet = getModel()->getDoneActionSet();
744 p_stateSet->push_back(*this);
748 double Action::getBound()
750 return (p_variable) ? lmm_variable_getbound(p_variable) : 0;
753 void Action::setBound(double bound)
755 XBT_IN("(%p,%g)", this, bound);
757 lmm_update_variable_bound(getModel()->getMaxminSystem(), p_variable, bound);
759 if (getModel()->getUpdateMechanism() == UM_LAZY && getLastUpdate()!=surf_get_clock())
760 heapRemove(getModel()->getActionHeap());
764 double Action::getStartTime()
769 double Action::getFinishTime()
771 /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
772 return m_remains == 0 ? m_finish : -1;
775 void Action::setData(void* data)
780 void Action::setCategory(const char *category)
782 XBT_IN("(%p,%s)", this, category);
783 p_category = xbt_strdup(category);
791 void Action::setMaxDuration(double duration)
793 XBT_IN("(%p,%g)", this, duration);
794 m_maxDuration = duration;
795 if (getModel()->getUpdateMechanism() == UM_LAZY) // remove action from the heap
796 heapRemove(getModel()->getActionHeap());
800 void Action::gapRemove() {}
802 void Action::setPriority(double priority)
804 XBT_IN("(%p,%g)", this, priority);
805 m_priority = priority;
806 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), priority);
808 if (getModel()->getUpdateMechanism() == UM_LAZY)
809 heapRemove(getModel()->getActionHeap());
813 void Action::cancel(){
814 setState(SURF_ACTION_FAILED);
815 if (getModel()->getUpdateMechanism() == UM_LAZY) {
816 if (action_lmm_hook.is_linked())
817 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
818 heapRemove(getModel()->getActionHeap());
825 if (action_hook.is_linked())
826 p_stateSet->erase(p_stateSet->iterator_to(*this));
828 lmm_variable_free(getModel()->getMaxminSystem(), getVariable());
829 if (getModel()->getUpdateMechanism() == UM_LAZY) {
830 /* remove from heap */
831 heapRemove(getModel()->getActionHeap());
832 if (action_lmm_hook.is_linked())
833 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
841 void Action::suspend()
843 XBT_IN("(%p)", this);
844 if (m_suspended != 2) {
845 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), 0.0);
847 if (getModel()->getUpdateMechanism() == UM_LAZY)
848 heapRemove(getModel()->getActionHeap());
853 void Action::resume()
855 XBT_IN("(%p)", this);
856 if (m_suspended != 2) {
857 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), m_priority);
859 if (getModel()->getUpdateMechanism() == UM_LAZY)
860 heapRemove(getModel()->getActionHeap());
865 bool Action::isSuspended()
867 return m_suspended == 1;
869 /* insert action on heap using a given key and a hat (heap_action_type)
870 * a hat can be of three types for communications:
872 * NORMAL = this is a normal heap entry stating the date to finish transmitting
873 * LATENCY = this is a heap entry to warn us when the latency is payed
874 * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
876 void Action::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
879 xbt_heap_push(heap, this, key);
882 void Action::heapRemove(xbt_heap_t heap)
885 if (m_indexHeap >= 0) {
886 xbt_heap_remove(heap, m_indexHeap);
890 void Action::heapUpdate(xbt_heap_t heap, double key, enum heap_action_type hat)
893 if (m_indexHeap >= 0) {
894 xbt_heap_update(heap, m_indexHeap, key);
896 xbt_heap_push(heap, this, key);
900 void Action::updateIndexHeap(int i) {
904 double Action::getRemains()
906 XBT_IN("(%p)", this);
907 /* update remains before return it */
908 if (getModel()->getUpdateMechanism() == UM_LAZY) /* update remains before return it */
909 updateRemainingLazy(surf_get_clock());
914 double Action::getRemainsNoUpdate()
919 //FIXME split code in the right places
920 void Action::updateRemainingLazy(double now)
924 if(getModel() == surf_network_model)
926 if (m_suspended != 0)
931 xbt_assert(p_stateSet == getModel()->getRunningActionSet(),
932 "You're updating an action that is not running.");
934 /* bogus priority, skip it */
935 xbt_assert(m_priority > 0,
936 "You're updating an action that seems suspended.");
939 delta = now - m_lastUpdate;
942 XBT_DEBUG("Updating action(%p): remains was %f, last_update was: %f", this, m_remains, m_lastUpdate);
943 double_update(&m_remains, m_lastValue * delta, sg_surf_precision*sg_maxmin_precision);
945 if (getModel() == surf_cpu_model_pm && TRACE_is_enabled()) {
946 simgrid::surf::Resource *cpu = static_cast<simgrid::surf::Resource*>(
947 lmm_constraint_id(lmm_get_cnst_from_var(getModel()->getMaxminSystem(), getVariable(), 0)));
948 TRACE_surf_host_set_utilization(cpu->getName(), getCategory(), m_lastValue, m_lastUpdate, now - m_lastUpdate);
950 XBT_DEBUG("Updating action(%p): remains is now %f", this, m_remains);
953 if(getModel() == surf_network_model)
955 if (m_maxDuration != NO_MAX_DURATION)
956 double_update(&m_maxDuration, delta, sg_surf_precision);
958 //FIXME: duplicated code
959 if ((m_remains <= 0) &&
960 (lmm_get_variable_weight(getVariable()) > 0)) {
962 setState(SURF_ACTION_DONE);
963 heapRemove(getModel()->getActionHeap());
964 } else if (((m_maxDuration != NO_MAX_DURATION)
965 && (m_maxDuration <= 0))) {
967 setState(SURF_ACTION_DONE);
968 heapRemove(getModel()->getActionHeap());
973 m_lastValue = lmm_variable_getvalue(getVariable());