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[] = {
102 {"Energy", "Cpu energy consumption.", sg_energy_plugin_init},
103 {NULL, NULL, NULL} /* this array must be NULL terminated */
106 /* Don't forget to update the option description in smx_config when you change
108 s_surf_model_description_t surf_network_model_description[] = {
110 "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). ",
111 surf_network_model_init_LegrandVelho},
113 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
114 surf_network_model_init_Constant},
116 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
117 surf_network_model_init_SMPI},
119 "Realistic network model specifically tailored for HPC settings, with Infiniband contention model",
120 surf_network_model_init_IB},
122 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
123 surf_network_model_init_CM02},
126 "Network pseudo-model using the GTNets simulator instead of an analytic model",
127 surf_network_model_init_GTNETS},
131 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
132 surf_network_model_init_NS3},
135 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
136 surf_network_model_init_Reno},
138 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
139 surf_network_model_init_Reno2},
141 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
142 surf_network_model_init_Vegas},
143 {NULL, NULL, NULL} /* this array must be NULL terminated */
146 s_surf_model_description_t surf_cpu_model_description[] = {
148 "Simplistic CPU model (time=size/power).",
149 surf_cpu_model_init_Cas01},
150 {NULL, NULL, NULL} /* this array must be NULL terminated */
153 s_surf_model_description_t surf_workstation_model_description[] = {
155 "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
156 surf_workstation_model_init_current_default},
158 "Workstation model that is automatically chosen if you change the network and CPU models",
159 surf_workstation_model_init_compound},
160 {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
161 surf_workstation_model_init_ptask_L07},
162 {NULL, NULL, NULL} /* this array must be NULL terminated */
165 s_surf_model_description_t surf_vm_workstation_model_description[] = {
167 "Default vm workstation model.",
168 surf_vm_workstation_model_init_HL13},
169 {NULL, NULL, NULL} /* this array must be NULL terminated */
172 s_surf_model_description_t surf_optimization_mode_description[] = {
174 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
177 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
180 "Full update of remaining and variables. Slow but may be useful when debugging.",
182 {NULL, NULL, NULL} /* this array must be NULL terminated */
185 s_surf_model_description_t surf_storage_model_description[] = {
187 "Simplistic storage model.",
188 surf_storage_model_init_default},
189 {NULL, NULL, NULL} /* this array must be NULL terminated */
192 #ifdef CONTEXT_THREADS
193 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
197 double *surf_mins = NULL; /* return value of share_resources for each model */
198 int surf_min_index; /* current index in surf_mins */
199 double surf_min; /* duration determined by surf_solve */
201 double surf_get_clock(void)
207 # define FILE_DELIM "\\"
209 # define FILE_DELIM "/" /* FIXME: move to better location */
212 FILE *surf_fopen(const char *name, const char *mode)
215 char *path_elm = NULL;
221 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
222 return fopen(name, mode);
224 /* search relative files in the path */
225 xbt_dynar_foreach(surf_path, cpt, path_elm) {
226 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
227 file = fopen(buff, mode);
243 static const char *disk_drives_letter_table[MAX_DRIVE] = {
274 * Returns the initial path. On Windows the initial path is
275 * the current directory for the current process in the other
276 * case the function returns "./" that represents the current
277 * directory on Unix/Linux platforms.
280 const char *__surf_get_initial_path(void)
285 char current_directory[MAX_PATH + 1] = { 0 };
286 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
287 char root[4] = { 0 };
292 strncpy(root, current_directory, 3);
294 for (i = 0; i < MAX_DRIVE; i++) {
295 if (toupper(root[0]) == disk_drives_letter_table[i][0])
296 return disk_drives_letter_table[i];
305 /* The __surf_is_absolute_file_path() returns 1 if
306 * file_path is a absolute file path, in the other
307 * case the function returns 0.
309 int __surf_is_absolute_file_path(const char *file_path)
312 WIN32_FIND_DATA wfd = { 0 };
313 HANDLE hFile = FindFirstFile(file_path, &wfd);
315 if (INVALID_HANDLE_VALUE == hFile)
321 return (file_path[0] == '/');
325 /** Displays the long description of all registered models, and quit */
326 void model_help(const char *category, s_surf_model_description_t * table)
329 printf("Long description of the %s models accepted by this simulator:\n",
331 for (i = 0; table[i].name; i++)
332 printf(" %s: %s\n", table[i].name, table[i].description);
335 int find_model_description(s_surf_model_description_t * table,
339 char *name_list = NULL;
341 for (i = 0; table[i].name; i++)
342 if (!strcmp(name, table[i].name)) {
346 xbt_die("No model is valid! This is a bug.");
347 name_list = xbt_strdup(table[0].name);
348 for (i = 1; table[i].name; i++) {
349 name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3);
350 strcat(name_list, ", ");
351 strcat(name_list, table[i].name);
353 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
357 static XBT_INLINE void routing_asr_host_free(void *p)
359 delete ((RoutingEdgePtr) p);
362 static XBT_INLINE void routing_asr_prop_free(void *p)
364 xbt_dict_t elm = (xbt_dict_t) p;
368 static XBT_INLINE void surf_cpu_free(void *r)
370 delete static_cast<CpuPtr>(r);
373 static XBT_INLINE void surf_link_free(void *r)
375 delete static_cast<NetworkLinkPtr>(r);
378 static XBT_INLINE void surf_workstation_free(void *r)
380 delete static_cast<WorkstationPtr>(r);
383 static XBT_INLINE void surf_storage_free(void *r)
385 delete static_cast<StoragePtr>(r);
389 void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
390 *ver_major = SIMGRID_VERSION_MAJOR;
391 *ver_minor = SIMGRID_VERSION_MINOR;
392 *ver_patch = SIMGRID_VERSION_PATCH;
395 void surf_init(int *argc, char **argv)
397 XBT_DEBUG("Create all Libs");
398 host_lib = xbt_lib_new();
399 link_lib = xbt_lib_new();
400 as_router_lib = xbt_lib_new();
401 storage_lib = xbt_lib_new();
402 storage_type_lib = xbt_lib_new();
403 file_lib = xbt_lib_new();
404 watched_hosts_lib = xbt_dict_new_homogeneous(NULL);
406 XBT_DEBUG("Add routing levels");
407 ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,routing_asr_host_free);
408 ROUTING_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_host_free);
409 ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
411 XBT_DEBUG("Add SURF levels");
412 SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_cpu_free);
413 SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_workstation_free);
414 SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_link_free);
415 SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_free);
417 xbt_init(argc, argv);
419 model_list = xbt_dynar_new(sizeof(ModelPtr), NULL);
420 if (!model_list_invoke)
421 model_list_invoke = xbt_dynar_new(sizeof(ModelPtr), NULL);
423 history = tmgr_history_new();
425 TRACE_add_start_function(TRACE_surf_alloc);
426 TRACE_add_end_function(TRACE_surf_release);
428 sg_config_init(argc, argv);
437 ModelPtr model = NULL;
439 TRACE_end(); /* Just in case it was not called by the upper
440 * layer (or there is no upper layer) */
442 sg_config_finalize();
444 xbt_dynar_free(&host_that_restart);
445 xbt_dynar_free(&surf_path);
447 xbt_lib_free(&host_lib);
448 xbt_lib_free(&link_lib);
449 xbt_lib_free(&as_router_lib);
450 xbt_lib_free(&storage_lib);
451 xbt_lib_free(&storage_type_lib);
452 xbt_lib_free(&file_lib);
453 xbt_dict_free(&watched_hosts_lib);
455 xbt_dynar_foreach(model_list, iter, model)
457 xbt_dynar_free(&model_list);
458 xbt_dynar_free(&model_list_invoke);
461 surf_callback_emit(surfExitCallbacks);
464 lmm_system_free(maxmin_system);
465 maxmin_system = NULL;
468 tmgr_history_free(history);
472 #ifdef CONTEXT_THREADS
473 xbt_parmap_destroy(surf_parmap);
480 surf_parse_lex_destroy();
481 surf_parse_free_callbacks();
483 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
490 Model::Model(const char *name)
491 : p_maxminSystem(NULL)
494 p_readyActionSet = new ActionList();
495 p_runningActionSet = new ActionList();
496 p_failedActionSet = new ActionList();
497 p_doneActionSet = new ActionList();
499 p_modifiedSet = NULL;
501 p_updateMechanism = UM_UNDEFINED;
502 m_selectiveUpdate = 0;
506 delete p_readyActionSet;
507 delete p_runningActionSet;
508 delete p_failedActionSet;
509 delete p_doneActionSet;
512 double Model::shareResources(double now)
514 //FIXME: set the good function once and for all
515 if (p_updateMechanism == UM_LAZY)
516 return shareResourcesLazy(now);
517 else if (p_updateMechanism == UM_FULL)
518 return shareResourcesFull(now);
520 xbt_die("Invalid cpu update mechanism!");
523 double Model::shareResourcesLazy(double now)
525 ActionPtr action = NULL;
530 ("Before share resources, the size of modified actions set is %zd",
531 p_modifiedSet->size());
533 lmm_solve(p_maxminSystem);
536 ("After share resources, The size of modified actions set is %zd",
537 p_modifiedSet->size());
539 while(!p_modifiedSet->empty()) {
540 action = &(p_modifiedSet->front());
541 p_modifiedSet->pop_front();
542 int max_dur_flag = 0;
544 if (action->getStateSet() != p_runningActionSet)
547 /* bogus priority, skip it */
548 if (action->getPriority() <= 0 || action->getHat()==LATENCY)
551 action->updateRemainingLazy(now);
554 share = lmm_variable_getvalue(action->getVariable());
557 double time_to_completion;
558 if (action->getRemains() > 0) {
559 time_to_completion = action->getRemainsNoUpdate() / share;
561 time_to_completion = 0.0;
563 min = now + time_to_completion; // when the task will complete if nothing changes
566 if ((action->getMaxDuration() != NO_MAX_DURATION)
568 || action->getStartTime() +
569 action->getMaxDuration() < min)) {
570 min = action->getStartTime() +
571 action->getMaxDuration(); // when the task will complete anyway because of the deadline if any
576 XBT_DEBUG("Action(%p) corresponds to variable %d", action, action->getVariable()->id_int);
578 XBT_DEBUG("Action(%p) Start %f. May finish at %f (got a share of %f). Max_duration %f", action,
579 action->getStartTime(), min, share,
580 action->getMaxDuration());
583 action->heapUpdate(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
584 XBT_DEBUG("Insert at heap action(%p) min %f now %f", action, min,
586 } else DIE_IMPOSSIBLE;
589 //hereafter must have already the min value for this resource model
590 if (xbt_heap_size(p_actionHeap) > 0)
591 min = xbt_heap_maxkey(p_actionHeap) - now;
595 XBT_DEBUG("The minimum with the HEAP %f", min);
600 double Model::shareResourcesFull(double /*now*/) {
604 double Model::shareResourcesMaxMin(ActionListPtr running_actions,
606 void (*solve) (lmm_system_t))
608 ActionPtr action = NULL;
614 ActionList::iterator it(running_actions->begin()), itend(running_actions->end());
615 for(; it != itend ; ++it) {
617 value = lmm_variable_getvalue(action->getVariable());
618 if ((value > 0) || (action->getMaxDuration() >= 0))
626 if (action->getRemains() > 0)
627 min = action->getRemainsNoUpdate() / value;
630 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min))
631 min = action->getMaxDuration();
633 min = action->getMaxDuration();
636 for (++it; it != itend; ++it) {
638 value = lmm_variable_getvalue(action->getVariable());
640 if (action->getRemains() > 0)
641 value = action->getRemainsNoUpdate() / value;
646 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
649 if ((action->getMaxDuration() >= 0) && (action->getMaxDuration() < min)) {
650 min = action->getMaxDuration();
651 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
654 XBT_DEBUG("min value : %f", min);
659 void Model::updateActionsState(double now, double delta)
661 if (p_updateMechanism == UM_FULL)
662 updateActionsStateFull(now, delta);
663 else if (p_updateMechanism == UM_LAZY)
664 updateActionsStateLazy(now, delta);
666 xbt_die("Invalid cpu update mechanism!");
669 void Model::updateActionsStateLazy(double /*now*/, double /*delta*/)
674 void Model::updateActionsStateFull(double /*now*/, double /*delta*/)
684 : p_name(NULL), p_properties(NULL), p_model(NULL)
687 Resource::Resource(ModelPtr model, const char *name, xbt_dict_t props)
688 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
689 , m_running(true), m_stateCurrent(SURF_RESOURCE_ON)
692 Resource::Resource(ModelPtr model, const char *name, xbt_dict_t props, lmm_constraint_t constraint)
693 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
694 , m_running(true), m_stateCurrent(SURF_RESOURCE_ON), p_constraint(constraint)
697 Resource::Resource(ModelPtr model, const char *name, xbt_dict_t props, e_surf_resource_state_t stateInit)
698 : p_name(xbt_strdup(name)), p_properties(props), p_model(model)
699 , m_running(true), m_stateCurrent(stateInit)
702 Resource::~Resource() {
703 xbt_free((void*)p_name);
704 xbt_dict_free(&p_properties);
707 e_surf_resource_state_t Resource::getState()
709 return m_stateCurrent;
712 void Resource::setState(e_surf_resource_state_t state)
714 m_stateCurrent = state;
717 bool Resource::isOn()
722 void Resource::turnOn()
729 void Resource::turnOff()
736 ModelPtr Resource::getModel() {
740 const char *Resource::getName() {
744 xbt_dict_t Resource::getProperties() {
745 if (p_properties==NULL)
746 p_properties = xbt_dict_new();
750 lmm_constraint_t Resource::getConstraint() {
758 const char *surf_action_state_names[6] = {
760 "SURF_ACTION_RUNNING",
761 "SURF_ACTION_FAILED",
763 "SURF_ACTION_TO_FREE",
764 "SURF_ACTION_NOT_IN_THE_SYSTEM"
767 void Action::initialize(ModelPtr model, double cost, bool failed,
773 m_maxDuration = NO_MAX_DURATION;
776 m_start = surf_get_clock();
787 Action::Action(ModelPtr model, double cost, bool failed)
789 initialize(model, cost, failed);
791 p_stateHookup.prev = 0;
792 p_stateHookup.next = 0;
794 p_stateSet = getModel()->getFailedActionSet();
796 p_stateSet = getModel()->getRunningActionSet();
798 p_stateSet->push_back(*this);
801 Action::Action(ModelPtr model, double cost, bool failed, lmm_variable_t var)
803 initialize(model, cost, failed, var);
805 p_stateHookup.prev = 0;
806 p_stateHookup.next = 0;
808 p_stateSet = getModel()->getFailedActionSet();
810 p_stateSet = getModel()->getRunningActionSet();
812 p_stateSet->push_back(*this);
816 xbt_free(p_category);
819 void Action::finish() {
820 m_finish = surf_get_clock();
823 e_surf_action_state_t Action::getState()
825 if (p_stateSet == getModel()->getReadyActionSet())
826 return SURF_ACTION_READY;
827 if (p_stateSet == getModel()->getRunningActionSet())
828 return SURF_ACTION_RUNNING;
829 if (p_stateSet == getModel()->getFailedActionSet())
830 return SURF_ACTION_FAILED;
831 if (p_stateSet == getModel()->getDoneActionSet())
832 return SURF_ACTION_DONE;
833 return SURF_ACTION_NOT_IN_THE_SYSTEM;
836 void Action::setState(e_surf_action_state_t state)
838 //surf_action_state_t action_state = &(action->model_type->states);
839 XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
840 p_stateSet->erase(p_stateSet->iterator_to(*this));
841 if (state == SURF_ACTION_READY)
842 p_stateSet = getModel()->getReadyActionSet();
843 else if (state == SURF_ACTION_RUNNING)
844 p_stateSet = getModel()->getRunningActionSet();
845 else if (state == SURF_ACTION_FAILED)
846 p_stateSet = getModel()->getFailedActionSet();
847 else if (state == SURF_ACTION_DONE)
848 p_stateSet = getModel()->getDoneActionSet();
853 p_stateSet->push_back(*this);
857 double Action::getBound()
859 return (p_variable) ? lmm_variable_getbound(p_variable) : 0;
862 void Action::setBound(double bound)
864 XBT_IN("(%p,%g)", this, bound);
866 lmm_update_variable_bound(getModel()->getMaxminSystem(), p_variable, bound);
868 if (getModel()->getUpdateMechanism() == UM_LAZY && getLastUpdate()!=surf_get_clock())
869 heapRemove(getModel()->getActionHeap());
873 double Action::getStartTime()
878 double Action::getFinishTime()
880 /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
881 return m_remains == 0 ? m_finish : -1;
884 void Action::setData(void* data)
889 void Action::setCategory(const char *category)
891 XBT_IN("(%p,%s)", this, category);
892 p_category = xbt_strdup(category);
900 void Action::setMaxDuration(double duration)
902 XBT_IN("(%p,%g)", this, duration);
903 m_maxDuration = duration;
904 if (getModel()->getUpdateMechanism() == UM_LAZY) // remove action from the heap
905 heapRemove(getModel()->getActionHeap());
909 void Action::gapRemove() {}
911 void Action::setPriority(double priority)
913 XBT_IN("(%p,%g)", this, priority);
914 m_priority = priority;
915 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), priority);
917 if (getModel()->getUpdateMechanism() == UM_LAZY)
918 heapRemove(getModel()->getActionHeap());
922 void Action::cancel(){
923 setState(SURF_ACTION_FAILED);
924 if (getModel()->getUpdateMechanism() == UM_LAZY) {
925 if (actionLmmHook::is_linked())
926 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
927 heapRemove(getModel()->getActionHeap());
934 if (actionHook::is_linked())
935 p_stateSet->erase(p_stateSet->iterator_to(*this));
937 lmm_variable_free(getModel()->getMaxminSystem(), getVariable());
938 if (getModel()->getUpdateMechanism() == UM_LAZY) {
939 /* remove from heap */
940 heapRemove(getModel()->getActionHeap());
941 if (actionLmmHook::is_linked())
942 getModel()->getModifiedSet()->erase(getModel()->getModifiedSet()->iterator_to(*this));
950 void Action::suspend()
952 XBT_IN("(%p)", this);
953 if (m_suspended != 2) {
954 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), 0.0);
956 if (getModel()->getUpdateMechanism() == UM_LAZY)
957 heapRemove(getModel()->getActionHeap());
962 void Action::resume()
964 XBT_IN("(%p)", this);
965 if (m_suspended != 2) {
966 lmm_update_variable_weight(getModel()->getMaxminSystem(), getVariable(), m_priority);
968 if (getModel()->getUpdateMechanism() == UM_LAZY)
969 heapRemove(getModel()->getActionHeap());
974 bool Action::isSuspended()
976 return m_suspended == 1;
978 /* insert action on heap using a given key and a hat (heap_action_type)
979 * a hat can be of three types for communications:
981 * NORMAL = this is a normal heap entry stating the date to finish transmitting
982 * LATENCY = this is a heap entry to warn us when the latency is payed
983 * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
985 void Action::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
988 xbt_heap_push(heap, this, key);
991 void Action::heapRemove(xbt_heap_t heap)
994 if (m_indexHeap >= 0) {
995 xbt_heap_remove(heap, m_indexHeap);
999 void Action::heapUpdate(xbt_heap_t heap, double key, enum heap_action_type hat)
1002 if (m_indexHeap >= 0) {
1003 xbt_heap_update(heap, m_indexHeap, key);
1005 xbt_heap_push(heap, this, key);
1009 /* added to manage the communication action's heap */
1010 void surf_action_lmm_update_index_heap(void *action, int i) {
1011 ((ActionPtr)action)->updateIndexHeap(i);
1014 void Action::updateIndexHeap(int i) {
1018 double Action::getRemains()
1020 XBT_IN("(%p)", this);
1021 /* update remains before return it */
1022 if (getModel()->getUpdateMechanism() == UM_LAZY) /* update remains before return it */
1023 updateRemainingLazy(surf_get_clock());
1028 double Action::getRemainsNoUpdate()
1033 //FIXME split code in the right places
1034 void Action::updateRemainingLazy(double now)
1038 if(getModel() == surf_network_model)
1040 if (m_suspended != 0)
1045 xbt_assert(p_stateSet == getModel()->getRunningActionSet(),
1046 "You're updating an action that is not running.");
1048 /* bogus priority, skip it */
1049 xbt_assert(m_priority > 0,
1050 "You're updating an action that seems suspended.");
1053 delta = now - m_lastUpdate;
1055 if (m_remains > 0) {
1056 XBT_DEBUG("Updating action(%p): remains was %f, last_update was: %f", this, m_remains, m_lastUpdate);
1057 double_update(&m_remains, m_lastValue * delta, sg_surf_precision*sg_maxmin_precision);
1059 if (getModel() == surf_cpu_model_pm && TRACE_is_enabled()) {
1060 ResourcePtr cpu = static_cast<ResourcePtr>(lmm_constraint_id(lmm_get_cnst_from_var(getModel()->getMaxminSystem(), getVariable(), 0)));
1061 TRACE_surf_host_set_utilization(cpu->getName(), getCategory(), m_lastValue, m_lastUpdate, now - m_lastUpdate);
1063 XBT_DEBUG("Updating action(%p): remains is now %f", this, m_remains);
1066 if(getModel() == surf_network_model)
1068 if (m_maxDuration != NO_MAX_DURATION)
1069 double_update(&m_maxDuration, delta, sg_surf_precision);
1071 //FIXME: duplicated code
1072 if ((m_remains <= 0) &&
1073 (lmm_get_variable_weight(getVariable()) > 0)) {
1075 setState(SURF_ACTION_DONE);
1076 heapRemove(getModel()->getActionHeap());
1077 } else if (((m_maxDuration != NO_MAX_DURATION)
1078 && (m_maxDuration <= 0))) {
1080 setState(SURF_ACTION_DONE);
1081 heapRemove(getModel()->getActionHeap());
1086 m_lastValue = lmm_variable_getvalue(getVariable());