1 /* Copyright (c) 2004-2014. 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 "workstation_interface.hpp"
12 #include "vm_workstation_interface.hpp"
13 #include "simix/smx_host_private.h"
14 #include "surf_routing.hpp"
15 #include "simgrid/sg_config.h"
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 /* This function is a pimple that we ought to fix. But it won't be easy.
28 * The surf_solve() function does properly return the set of actions that
29 * changed. Instead, each model change a global data, and then the caller of
30 * surf_solve must pick into these sets of action_failed and action_done.
32 * This was not clean but ok as long as we didn't had to restart the processes
33 * when the resource comes back up.
34 * We worked by putting sentinel actions on every resources we are interested
35 * in, so that surf informs us if/when the corresponding resource fails.
37 * But this does not work to get Simix informed of when a resource comes back
38 * up, and this is where this pimple comes. We have a set of resources that are
39 * currently down and for which simix needs to know when it comes back up.
40 * And the current function is called *at every simulation step* to sweep over
41 * that set, searching for a resource that was turned back up in the meanwhile.
42 * This is UGLY and slow.
44 * The proper solution would be to not rely on globals for the action_failed and
45 * action_done swags. They must be passed as parameter by the caller (the
46 * handling of these actions in simix may let you think that these two sets can
47 * be merged, but their handling in SimDag induce the contrary unless this
48 * simdag code can check by itself whether the action is done of failed -- seems
49 * very doable, but yet more cleanup to do).
51 * Once surf_solve() is passed the set of actions that changed, you want to add
52 * a new set of resources back up as parameter to this function. You also want
53 * to add a boolean field "restart_watched" to each resource, and make sure that
54 * whenever a resource with this field enabled comes back up, it's added to that
55 * set so that Simix sees it and react accordingly. This would kill that need
56 * for surf to call simix.
60 /*static void remove_watched_host(void *key)
62 xbt_dict_remove(watched_hosts_lib, *(char**)key);
65 /*void surf_watched_hosts(void)
69 xbt_dict_cursor_t cursor;
70 xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL);
72 XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib");
73 xbt_dict_foreach(watched_hosts_lib, cursor, key, host)
75 if(SIMIX_host_get_state((smx_host_t)host) == SURF_RESOURCE_ON){
76 XBT_INFO("Restart processes on host: %s", SIMIX_host_get_name((smx_host_t)host));
77 SIMIX_host_autorestart((smx_host_t)host);
78 xbt_dynar_push_as(hosts, char*, key);
81 XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key);
83 xbt_dynar_map(hosts, remove_watched_host);
84 xbt_dynar_free(&hosts);
87 /* model_list_invoke contains only surf_workstation and surf_vm_workstation.
88 * The callback functions of cpu_model and network_model will be called from
89 * those of these workstation models. */
90 xbt_dynar_t model_list = NULL; /* for destroying all models correctly */
91 xbt_dynar_t model_list_invoke = NULL; /* for invoking callbacks */
93 tmgr_history_t history = NULL;
94 lmm_system_t maxmin_system = NULL;
95 xbt_dynar_t surf_path = NULL;
96 xbt_dynar_t host_that_restart = NULL;
97 xbt_dict_t watched_hosts_lib;
99 surf_callback(void, void) surfExitCallbacks;
101 s_surf_model_description_t surf_plugin_description[] = {
103 "Cpu energy consumption.",
104 sg_energy_plugin_init},
105 {NULL, NULL, NULL} /* this array must be NULL terminated */
108 /* Don't forget to update the option description in smx_config when you change
110 s_surf_model_description_t surf_network_model_description[] = {
112 "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). ",
113 surf_network_model_init_LegrandVelho},
115 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
116 surf_network_model_init_Constant},
118 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
119 surf_network_model_init_SMPI},
121 "Realistic network model specifically tailored for HPC settings, with Infiniband contention model",
122 surf_network_model_init_IB},
124 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
125 surf_network_model_init_CM02},
128 "Network pseudo-model using the GTNets simulator instead of an analytic model",
129 surf_network_model_init_GTNETS},
133 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
134 surf_network_model_init_NS3},
137 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
138 surf_network_model_init_Reno},
140 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
141 surf_network_model_init_Reno2},
143 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
144 surf_network_model_init_Vegas},
145 {NULL, NULL, NULL} /* this array must be NULL terminated */
148 s_surf_model_description_t surf_cpu_model_description[] = {
150 "Simplistic CPU model (time=size/power).",
151 surf_cpu_model_init_Cas01},
152 {NULL, NULL, NULL} /* this array must be NULL terminated */
155 s_surf_model_description_t surf_workstation_model_description[] = {
157 "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
158 surf_workstation_model_init_current_default},
160 "Workstation model that is automatically chosen if you change the network and CPU models",
161 surf_workstation_model_init_compound},
162 {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
163 surf_workstation_model_init_ptask_L07},
164 {NULL, NULL, NULL} /* this array must be NULL terminated */
167 s_surf_model_description_t surf_vm_workstation_model_description[] = {
169 "Default vm workstation model.",
170 surf_vm_workstation_model_init_HL13},
171 {NULL, NULL, NULL} /* this array must be NULL terminated */
174 s_surf_model_description_t surf_optimization_mode_description[] = {
176 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
179 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
182 "Full update of remaining and variables. Slow but may be useful when debugging.",
184 {NULL, NULL, NULL} /* this array must be NULL terminated */
187 s_surf_model_description_t surf_storage_model_description[] = {
189 "Simplistic storage model.",
190 surf_storage_model_init_default},
191 {NULL, NULL, NULL} /* this array must be NULL terminated */
194 #ifdef CONTEXT_THREADS
195 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
199 double *surf_mins = NULL; /* return value of share_resources for each model */
200 int surf_min_index; /* current index in surf_mins */
201 double surf_min; /* duration determined by surf_solve */
203 double surf_get_clock(void)
209 # define FILE_DELIM "\\"
211 # define FILE_DELIM "/" /* FIXME: move to better location */
214 FILE *surf_fopen(const char *name, const char *mode)
217 char *path_elm = NULL;
223 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
224 return fopen(name, mode);
226 /* search relative files in the path */
227 xbt_dynar_foreach(surf_path, cpt, path_elm) {
228 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
229 file = fopen(buff, mode);
245 static const char *disk_drives_letter_table[MAX_DRIVE] = {
276 * Returns the initial path. On Windows the initial path is
277 * the current directory for the current process in the other
278 * case the function returns "./" that represents the current
279 * directory on Unix/Linux platforms.
282 const char *__surf_get_initial_path(void)
287 char current_directory[MAX_PATH + 1] = { 0 };
288 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
289 char root[4] = { 0 };
294 strncpy(root, current_directory, 3);
296 for (i = 0; i < MAX_DRIVE; i++) {
297 if (toupper(root[0]) == disk_drives_letter_table[i][0])
298 return disk_drives_letter_table[i];
307 /* The __surf_is_absolute_file_path() returns 1 if
308 * file_path is a absolute file path, in the other
309 * case the function returns 0.
311 int __surf_is_absolute_file_path(const char *file_path)
314 WIN32_FIND_DATA wfd = { 0 };
315 HANDLE hFile = FindFirstFile(file_path, &wfd);
317 if (INVALID_HANDLE_VALUE == hFile)
323 return (file_path[0] == '/');
327 /** Displays the long description of all registered models, and quit */
328 void model_help(const char *category, s_surf_model_description_t * table)
331 printf("Long description of the %s models accepted by this simulator:\n",
333 for (i = 0; table[i].name; i++)
334 printf(" %s: %s\n", table[i].name, table[i].description);
337 int find_model_description(s_surf_model_description_t * table,
341 char *name_list = NULL;
343 for (i = 0; table[i].name; i++)
344 if (!strcmp(name, table[i].name)) {
348 xbt_die("No model is valid! This is a bug.");
349 name_list = xbt_strdup(table[0].name);
350 for (i = 1; table[i].name; i++) {
351 name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3);
352 strcat(name_list, ", ");
353 strcat(name_list, table[i].name);
355 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
359 static XBT_INLINE void routing_asr_host_free(void *p)
361 delete ((RoutingEdgePtr) p);
364 static XBT_INLINE void routing_asr_prop_free(void *p)
366 xbt_dict_t elm = (xbt_dict_t) p;
370 static XBT_INLINE void surf_cpu_free(void *r)
372 delete static_cast<CpuPtr>(r);
375 static XBT_INLINE void surf_link_free(void *r)
377 delete static_cast<NetworkLinkPtr>(r);
380 static XBT_INLINE void surf_workstation_free(void *r)
382 delete static_cast<WorkstationPtr>(r);
385 static XBT_INLINE void surf_storage_free(void *r)
387 delete static_cast<StoragePtr>(r);
391 void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
392 *ver_major = SIMGRID_VERSION_MAJOR;
393 *ver_minor = SIMGRID_VERSION_MINOR;
394 *ver_patch = SIMGRID_VERSION_PATCH;
397 void surf_init(int *argc, char **argv)
399 XBT_DEBUG("Create all Libs");
400 host_lib = xbt_lib_new();
401 link_lib = xbt_lib_new();
402 as_router_lib = xbt_lib_new();
403 storage_lib = xbt_lib_new();
404 storage_type_lib = xbt_lib_new();
405 file_lib = xbt_lib_new();
406 watched_hosts_lib = xbt_dict_new_homogeneous(NULL);
408 XBT_DEBUG("Add routing levels");
409 ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,routing_asr_host_free);
410 ROUTING_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_host_free);
411 ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
413 XBT_DEBUG("Add SURF levels");
414 SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_cpu_free);
415 SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_workstation_free);
416 SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_link_free);
417 SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_free);
419 xbt_init(argc, argv);
421 model_list = xbt_dynar_new(sizeof(ModelPtr), NULL);
422 if (!model_list_invoke)
423 model_list_invoke = xbt_dynar_new(sizeof(ModelPtr), NULL);
425 history = tmgr_history_new();
428 TRACE_add_start_function(TRACE_surf_alloc);
429 TRACE_add_end_function(TRACE_surf_release);
432 sg_config_init(argc, argv);
441 ModelPtr model = NULL;
444 TRACE_end(); /* Just in case it was not called by the upper
445 * layer (or there is no upper layer) */
448 sg_config_finalize();
450 xbt_dynar_free(&host_that_restart);
451 xbt_dynar_free(&surf_path);
453 xbt_lib_free(&host_lib);
454 xbt_lib_free(&link_lib);
455 xbt_lib_free(&as_router_lib);
456 xbt_lib_free(&storage_lib);
457 xbt_lib_free(&storage_type_lib);
458 xbt_lib_free(&file_lib);
459 xbt_dict_free(&watched_hosts_lib);
461 xbt_dynar_foreach(model_list, iter, model)
463 xbt_dynar_free(&model_list);
464 xbt_dynar_free(&model_list_invoke);
467 surf_callback_emit(surfExitCallbacks);
470 lmm_system_free(maxmin_system);
471 maxmin_system = NULL;
474 tmgr_history_free(history);
478 #ifdef CONTEXT_THREADS
479 xbt_parmap_destroy(surf_parmap);
486 surf_parse_lex_destroy();
487 surf_parse_free_callbacks();
489 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
496 Model::Model(const char *name)
497 : p_maxminSystem(NULL)
500 p_readyActionSet = new ActionList();
501 p_runningActionSet = new ActionList();
502 p_failedActionSet = new ActionList();
503 p_doneActionSet = new ActionList();
505 p_modifiedSet = NULL;
507 p_updateMechanism = UM_UNDEFINED;
508 m_selectiveUpdate = 0;
512 delete p_readyActionSet;
513 delete p_runningActionSet;
514 delete p_failedActionSet;
515 delete p_doneActionSet;
518 double Model::shareResources(double now)
520 //FIXME: set the good function once and for all
521 if (p_updateMechanism == UM_LAZY)
522 return shareResourcesLazy(now);
523 else if (p_updateMechanism == UM_FULL)
524 return shareResourcesFull(now);
526 xbt_die("Invalid cpu update mechanism!");
529 double Model::shareResourcesLazy(double now)
531 ActionPtr action = NULL;
536 ("Before share resources, the size of modified actions set is %zd",
537 p_modifiedSet->size());
539 lmm_solve(p_maxminSystem);
542 ("After share resources, The size of modified actions set is %zd",
543 p_modifiedSet->size());
545 while(!p_modifiedSet->empty()) {
546 action = &(p_modifiedSet->front());
547 p_modifiedSet->pop_front();
548 int max_dur_flag = 0;
550 if (action->getStateSet() != p_runningActionSet)
553 /* bogus priority, skip it */
554 if (action->getPriority() <= 0 || action->getHat()==LATENCY)
557 action->updateRemainingLazy(now);
560 share = lmm_variable_getvalue(action->getVariable());
563 double time_to_completion;
564 if (action->getRemains() > 0) {
565 time_to_completion = action->getRemainsNoUpdate() / share;
567 time_to_completion = 0.0;
569 min = now + time_to_completion; // when the task will complete if nothing changes
572 if ((action->getMaxDuration() != NO_MAX_DURATION)
574 || action->getStartTime() +
575 action->getMaxDuration() < min)) {
576 min = action->getStartTime() +
577 action->getMaxDuration(); // when the task will complete anyway because of the deadline if any
582 XBT_DEBUG("Action(%p) corresponds to variable %d", action, action->getVariable()->id_int);
584 XBT_DEBUG("Action(%p) Start %f. May finish at %f (got a share of %f). Max_duration %f", action,
585 action->getStartTime(), min, share,
586 action->getMaxDuration());
589 action->heapUpdate(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
590 XBT_DEBUG("Insert at heap action(%p) min %f now %f", action, min,
592 } else DIE_IMPOSSIBLE;
595 //hereafter must have already the min value for this resource model
596 if (xbt_heap_size(p_actionHeap) > 0)
597 min = xbt_heap_maxkey(p_actionHeap) - now;
601 XBT_DEBUG("The minimum with the HEAP %f", min);
606 double Model::shareResourcesFull(double /*now*/) {
610 double Model::shareResourcesMaxMin(ActionListPtr running_actions,
612 void (*solve) (lmm_system_t))
614 ActionPtr action = NULL;
620 ActionList::iterator it(running_actions->begin()), itend(running_actions->end());
621 for(; it != itend ; ++it) {
623 value = lmm_variable_getvalue(action->getVariable());
624 if ((value > 0) || (action->getMaxDuration() >= 0))
632 if (action->getRemains() > 0)
633 min = action->getRemainsNoUpdate() / value;
636 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min))
637 min = action->getMaxDuration();
639 min = action->getMaxDuration();
642 for (++it; it != itend; ++it) {
644 value = lmm_variable_getvalue(action->getVariable());
646 if (action->getRemains() > 0)
647 value = action->getRemainsNoUpdate() / value;
652 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
655 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min)) {
656 min = action->getMaxDuration();
657 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
660 XBT_DEBUG("min value : %f", min);
665 void Model::updateActionsState(double now, double delta)
667 if (p_updateMechanism == UM_FULL)
668 updateActionsStateFull(now, delta);
669 else if (p_updateMechanism == UM_LAZY)
670 updateActionsStateLazy(now, delta);
672 xbt_die("Invalid cpu update mechanism!");
675 void Model::updateActionsStateLazy(double /*now*/, double /*delta*/)
680 void Model::updateActionsStateFull(double /*now*/, double /*delta*/)
690 : p_name(NULL), p_properties(NULL), p_model(NULL)
693 Resource::Resource(ModelPtr model, const char *name, xbt_dict_t props)
694 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
695 , m_running(true), m_stateCurrent(SURF_RESOURCE_ON)
698 Resource::Resource(ModelPtr model, const char *name, xbt_dict_t props, lmm_constraint_t constraint)
699 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
700 , m_running(true), m_stateCurrent(SURF_RESOURCE_ON), p_constraint(constraint)
703 Resource::Resource(ModelPtr model, const char *name, xbt_dict_t props, e_surf_resource_state_t stateInit)
704 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
705 , m_running(true), m_stateCurrent(stateInit)
708 Resource::~Resource() {
709 xbt_free((void*)p_name);
710 xbt_dict_free(&p_properties);
713 e_surf_resource_state_t Resource::getState()
715 return m_stateCurrent;
718 void Resource::setState(e_surf_resource_state_t state)
720 m_stateCurrent = state;
723 bool Resource::isOn()
728 void Resource::turnOn()
735 void Resource::turnOff()
742 ModelPtr Resource::getModel() {
746 const char *Resource::getName() {
750 xbt_dict_t Resource::getProperties() {
751 if (p_properties==NULL)
752 p_properties = xbt_dict_new();
756 lmm_constraint_t Resource::getConstraint() {
764 const char *surf_action_state_names[6] = {
766 "SURF_ACTION_RUNNING",
767 "SURF_ACTION_FAILED",
769 "SURF_ACTION_TO_FREE",
770 "SURF_ACTION_NOT_IN_THE_SYSTEM"
773 void Action::initialize(ModelPtr model, double cost, bool failed,
779 m_maxDuration = NO_MAX_DURATION;
782 m_start = surf_get_clock();
793 Action::Action(ModelPtr model, double cost, bool failed)
795 initialize(model, cost, failed);
799 p_stateHookup.prev = 0;
800 p_stateHookup.next = 0;
802 p_stateSet = getModel()->getFailedActionSet();
804 p_stateSet = getModel()->getRunningActionSet();
806 p_stateSet->push_back(*this);
809 Action::Action(ModelPtr model, double cost, bool failed, lmm_variable_t var)
811 initialize(model, cost, failed, var);
815 p_stateHookup.prev = 0;
816 p_stateHookup.next = 0;
818 p_stateSet = getModel()->getFailedActionSet();
820 p_stateSet = getModel()->getRunningActionSet();
822 p_stateSet->push_back(*this);
827 xbt_free(p_category);
831 void Action::finish() {
832 m_finish = surf_get_clock();
835 e_surf_action_state_t Action::getState()
837 if (p_stateSet == getModel()->getReadyActionSet())
838 return SURF_ACTION_READY;
839 if (p_stateSet == getModel()->getRunningActionSet())
840 return SURF_ACTION_RUNNING;
841 if (p_stateSet == getModel()->getFailedActionSet())
842 return SURF_ACTION_FAILED;
843 if (p_stateSet == getModel()->getDoneActionSet())
844 return SURF_ACTION_DONE;
845 return SURF_ACTION_NOT_IN_THE_SYSTEM;
848 void Action::setState(e_surf_action_state_t state)
850 //surf_action_state_t action_state = &(action->model_type->states);
851 XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
852 p_stateSet->erase(p_stateSet->iterator_to(*this));
853 if (state == SURF_ACTION_READY)
854 p_stateSet = getModel()->getReadyActionSet();
855 else if (state == SURF_ACTION_RUNNING)
856 p_stateSet = getModel()->getRunningActionSet();
857 else if (state == SURF_ACTION_FAILED)
858 p_stateSet = getModel()->getFailedActionSet();
859 else if (state == SURF_ACTION_DONE)
860 p_stateSet = getModel()->getDoneActionSet();
865 p_stateSet->push_back(*this);
869 double Action::getBound()
871 return (p_variable) ? lmm_variable_getbound(p_variable) : 0;
874 void Action::setBound(double bound)
876 XBT_IN("(%p,%g)", this, bound);
878 lmm_update_variable_bound(getModel()->getMaxminSystem(), p_variable, bound);
880 if (getModel()->getUpdateMechanism() == UM_LAZY && getLastUpdate()!=surf_get_clock())
881 heapRemove(getModel()->getActionHeap());
885 double Action::getStartTime()
890 double Action::getFinishTime()
892 /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
893 return m_remains == 0 ? m_finish : -1;
896 void Action::setData(void* data)
902 void Action::setCategory(const char *category)
904 XBT_IN("(%p,%s)", this, category);
905 p_category = xbt_strdup(category);
914 void Action::setMaxDuration(double duration)
916 XBT_IN("(%p,%g)", this, duration);
917 m_maxDuration = duration;
918 if (getModel()->getUpdateMechanism() == UM_LAZY) // remove action from the heap
919 heapRemove(getModel()->getActionHeap());
923 void Action::gapRemove() {}
925 void Action::setPriority(double priority)
927 XBT_IN("(%p,%g)", this, priority);
928 m_priority = priority;
929 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), priority);
931 if (getModel()->getUpdateMechanism() == UM_LAZY)
932 heapRemove(getModel()->getActionHeap());
936 void Action::cancel(){
937 setState(SURF_ACTION_FAILED);
938 if (getModel()->getUpdateMechanism() == UM_LAZY) {
939 if (actionLmmHook::is_linked())
940 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
941 heapRemove(getModel()->getActionHeap());
948 if (actionHook::is_linked())
949 p_stateSet->erase(p_stateSet->iterator_to(*this));
951 lmm_variable_free(getModel()->getMaxminSystem(), getVariable());
952 if (getModel()->getUpdateMechanism() == UM_LAZY) {
953 /* remove from heap */
954 heapRemove(getModel()->getActionHeap());
955 if (actionLmmHook::is_linked())
956 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
964 void Action::suspend()
966 XBT_IN("(%p)", this);
967 if (m_suspended != 2) {
968 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), 0.0);
970 if (getModel()->getUpdateMechanism() == UM_LAZY)
971 heapRemove(getModel()->getActionHeap());
976 void Action::resume()
978 XBT_IN("(%p)", this);
979 if (m_suspended != 2) {
980 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), m_priority);
982 if (getModel()->getUpdateMechanism() == UM_LAZY)
983 heapRemove(getModel()->getActionHeap());
988 bool Action::isSuspended()
990 return m_suspended == 1;
992 /* insert action on heap using a given key and a hat (heap_action_type)
993 * a hat can be of three types for communications:
995 * NORMAL = this is a normal heap entry stating the date to finish transmitting
996 * LATENCY = this is a heap entry to warn us when the latency is payed
997 * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
999 void Action::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
1002 xbt_heap_push(heap, this, key);
1005 void Action::heapRemove(xbt_heap_t heap)
1008 if (m_indexHeap >= 0) {
1009 xbt_heap_remove(heap, m_indexHeap);
1013 void Action::heapUpdate(xbt_heap_t heap, double key, enum heap_action_type hat)
1016 if (m_indexHeap >= 0) {
1017 xbt_heap_update(heap, m_indexHeap, key);
1019 xbt_heap_push(heap, this, key);
1023 /* added to manage the communication action's heap */
1024 void surf_action_lmm_update_index_heap(void *action, int i) {
1025 ((ActionPtr)action)->updateIndexHeap(i);
1028 void Action::updateIndexHeap(int i) {
1032 double Action::getRemains()
1034 XBT_IN("(%p)", this);
1035 /* update remains before return it */
1036 if (getModel()->getUpdateMechanism() == UM_LAZY) /* update remains before return it */
1037 updateRemainingLazy(surf_get_clock());
1042 double Action::getRemainsNoUpdate()
1047 //FIXME split code in the right places
1048 void Action::updateRemainingLazy(double now)
1052 if(getModel() == surf_network_model)
1054 if (m_suspended != 0)
1059 xbt_assert(p_stateSet == getModel()->getRunningActionSet(),
1060 "You're updating an action that is not running.");
1062 /* bogus priority, skip it */
1063 xbt_assert(m_priority > 0,
1064 "You're updating an action that seems suspended.");
1067 delta = now - m_lastUpdate;
1069 if (m_remains > 0) {
1070 XBT_DEBUG("Updating action(%p): remains was %f, last_update was: %f", this, m_remains, m_lastUpdate);
1071 double_update(&m_remains, m_lastValue * delta, sg_surf_precision*sg_maxmin_precision);
1074 if (getModel() == surf_cpu_model_pm && TRACE_is_enabled()) {
1075 ResourcePtr cpu = static_cast<ResourcePtr>(lmm_constraint_id(lmm_get_cnst_from_var(getModel()->getMaxminSystem(), getVariable(), 0)));
1076 TRACE_surf_host_set_utilization(cpu->getName(), getCategory(), m_lastValue, m_lastUpdate, now - m_lastUpdate);
1079 XBT_DEBUG("Updating action(%p): remains is now %f", this, m_remains);
1082 if(getModel() == surf_network_model)
1084 if (m_maxDuration != NO_MAX_DURATION)
1085 double_update(&m_maxDuration, delta, sg_surf_precision);
1087 //FIXME: duplicated code
1088 if ((m_remains <= 0) &&
1089 (lmm_get_variable_weight(getVariable()) > 0)) {
1091 setState(SURF_ACTION_DONE);
1092 heapRemove(getModel()->getActionHeap());
1093 } else if (((m_maxDuration != NO_MAX_DURATION)
1094 && (m_maxDuration <= 0))) {
1096 setState(SURF_ACTION_DONE);
1097 heapRemove(getModel()->getActionHeap());
1102 m_lastValue = lmm_variable_getvalue(getVariable());