1 #include "surf_private.h"
4 #include "simix/smx_host_private.h"
5 #include "surf_routing.hpp"
6 #include "simgrid/sg_config.h"
10 XBT_LOG_NEW_CATEGORY(surf, "All SURF categories");
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
12 "Logging specific to SURF (kernel)");
19 /* This function is a pimple that we ought to fix. But it won't be easy.
21 * The surf_solve() function does properly return the set of actions that changed.
22 * Instead, each model change a global data, and then the caller of surf_solve must
23 * pick into these sets of action_failed and action_done.
25 * This was not clean but ok as long as we didn't had to restart the processes when the resource comes back up.
26 * We worked by putting sentinel actions on every resources we are interested in,
27 * so that surf informs us if/when the corresponding resource fails.
29 * But this does not work to get Simix informed of when a resource comes back up, and this is where this pimple comes.
30 * We have a set of resources that are currently down and for which simix needs to know when it comes back up.
31 * And the current function is called *at every simulation step* to sweep over that set, searching for a resource
32 * that was turned back up in the meanwhile. This is UGLY and slow.
34 * The proper solution would be to not rely on globals for the action_failed and action_done swags.
35 * They must be passed as parameter by the caller (the handling of these actions in simix may let you
36 * think that these two sets can be merged, but their handling in SimDag induce the contrary unless this
37 * simdag code can check by itself whether the action is done of failed -- seems very doable, but yet more
40 * Once surf_solve() is passed the set of actions that changed, you want to add a new set of resources back up
41 * as parameter to this function. You also want to add a boolean field "restart_watched" to each resource, and
42 * make sure that whenever a resource with this field enabled comes back up, it's added to that set so that Simix
43 * sees it and react accordingly. This would kill that need for surf to call simix.
47 static void remove_watched_host(void *key)
49 xbt_dict_remove(watched_hosts_lib, *(char**)key);
52 void surf_watched_hosts(void)
56 xbt_dict_cursor_t cursor;
57 xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL);
59 XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib");
60 xbt_dict_foreach(watched_hosts_lib, cursor, key, host)
62 if(SIMIX_host_get_state((smx_host_t)host) == SURF_RESOURCE_ON){
63 XBT_INFO("Restart processes on host: %s", SIMIX_host_get_name((smx_host_t)host));
64 SIMIX_host_autorestart((smx_host_t)host);
65 xbt_dynar_push_as(hosts, char*, key);
68 XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key);
70 xbt_dynar_map(hosts, remove_watched_host);
71 xbt_dynar_free(&hosts);
75 xbt_dynar_t model_list = NULL;
76 tmgr_history_t history = NULL;
77 lmm_system_t maxmin_system = NULL;
78 xbt_dynar_t surf_path = NULL;
80 /* Don't forget to update the option description in smx_config when you change this */
81 s_surf_model_description_t surf_network_model_description[] = {
83 "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). ",
84 surf_network_model_init_LegrandVelho},
86 "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
87 surf_network_model_init_Constant},
89 "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
90 surf_network_model_init_SMPI},
92 "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
93 surf_network_model_init_CM02},
96 "Network pseudo-model using the GTNets simulator instead of an analytic model",
97 surf_network_model_init_GTNETS},
101 "Network pseudo-model using the NS3 tcp model instead of an analytic model",
102 surf_network_model_init_NS3},
105 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
106 surf_network_model_init_Reno},
108 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
109 surf_network_model_init_Reno2},
111 "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
112 surf_network_model_init_Vegas},
113 {NULL, NULL, NULL} /* this array must be NULL terminated */
116 s_surf_model_description_t surf_cpu_model_description[] = {
118 "Simplistic CPU model (time=size/power).",
119 surf_cpu_model_init_Cas01},
120 {NULL, NULL, NULL} /* this array must be NULL terminated */
123 s_surf_model_description_t surf_workstation_model_description[] = {
125 "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
126 surf_workstation_model_init_current_default},
128 "Workstation model that is automatically chosen if you change the network and CPU models",
129 surf_workstation_model_init_compound},
130 {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
131 surf_workstation_model_init_ptask_L07},
132 {NULL, NULL, NULL} /* this array must be NULL terminated */
135 s_surf_model_description_t surf_optimization_mode_description[] = {
137 "Lazy action management (partial invalidation in lmm + heap in action remaining).",
140 "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
143 "Full update of remaining and variables. Slow but may be useful when debugging.",
145 {NULL, NULL, NULL} /* this array must be NULL terminated */
148 s_surf_model_description_t surf_storage_model_description[] = {
150 "Simplistic storage model.",
151 surf_storage_model_init_default},
152 {NULL, NULL, NULL} /* this array must be NULL terminated */
155 /* ********************************************************************* */
156 /* TUTORIAL: New model */
157 s_surf_model_description_t surf_new_model_description[] = {
160 surf_new_model_init_default},
161 {NULL, NULL, NULL} /* this array must be NULL terminated */
163 /* ********************************************************************* */
165 #ifdef CONTEXT_THREADS
166 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
169 static double *surf_mins = NULL; /* return value of share_resources for each model */
170 static int surf_min_index; /* current index in surf_mins */
171 static double min; /* duration determined by surf_solve */
175 XBT_INLINE double surf_get_clock(void)
180 /*TODO: keepit void surf_watched_hosts(void)
185 xbt_dict_cursor_t cursor;
186 xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL);
188 XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib");
189 xbt_dict_foreach(watched_hosts_lib,cursor,key,_host)
191 host = (smx_host_t) host;
192 if(SIMIX_host_get_state(host) == SURF_RESOURCE_ON){
193 XBT_INFO("Restart processes on host: %s",SIMIX_host_get_name(host));
194 SIMIX_host_autorestart(host);
195 xbt_dynar_push_as(hosts, char*, key);
198 XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key);
200 xbt_dynar_map(hosts, remove_watched_host);
201 xbt_dynar_free(&hosts);
205 # define FILE_DELIM "\\"
207 # define FILE_DELIM "/" /* FIXME: move to better location */
210 FILE *surf_fopen(const char *name, const char *mode)
213 char *path_elm = NULL;
219 if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */
220 return fopen(name, mode);
222 /* search relative files in the path */
223 xbt_dynar_foreach(surf_path, cpt, path_elm) {
224 buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
225 file = fopen(buff, mode);
235 * Returns the initial path. On Windows the initial path is
236 * the current directory for the current process in the other
237 * case the function returns "./" that represents the current
238 * directory on Unix/Linux platforms.
241 const char *__surf_get_initial_path(void)
246 char current_directory[MAX_PATH + 1] = { 0 };
247 unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
248 char root[4] = { 0 };
253 strncpy(root, current_directory, 3);
255 for (i = 0; i < MAX_DRIVE; i++) {
256 if (toupper(root[0]) == disk_drives_letter_table[i][0])
257 return disk_drives_letter_table[i];
266 /* The __surf_is_absolute_file_path() returns 1 if
267 * file_path is a absolute file path, in the other
268 * case the function returns 0.
270 int __surf_is_absolute_file_path(const char *file_path)
273 WIN32_FIND_DATA wfd = { 0 };
274 HANDLE hFile = FindFirstFile(file_path, &wfd);
276 if (INVALID_HANDLE_VALUE == hFile)
282 return (file_path[0] == '/');
286 /** Displays the long description of all registered models, and quit */
287 void model_help(const char *category, s_surf_model_description_t * table)
290 printf("Long description of the %s models accepted by this simulator:\n",
292 for (i = 0; table[i].name; i++)
293 printf(" %s: %s\n", table[i].name, table[i].description);
296 int find_model_description(s_surf_model_description_t * table,
300 char *name_list = NULL;
302 for (i = 0; table[i].name; i++)
303 if (!strcmp(name, table[i].name)) {
306 name_list = strdup(table[0].name);
307 for (i = 1; table[i].name; i++) {
308 name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3);
309 strcat(name_list, ", ");
310 strcat(name_list, table[i].name);
312 xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
316 static XBT_INLINE void routing_asr_host_free(void *p)
318 delete ((RoutingEdgePtr) p);
321 static XBT_INLINE void routing_asr_prop_free(void *p)
323 xbt_dict_t elm = (xbt_dict_t) p;
327 static XBT_INLINE void surf_resource_free(void *r)
329 ResourcePtr resource = (ResourcePtr) r;
333 void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
334 *ver_major = SIMGRID_VERSION_MAJOR;
335 *ver_minor = SIMGRID_VERSION_MINOR;
336 *ver_patch = SIMGRID_VERSION_PATCH;
339 void surf_init(int *argc, char **argv)
341 XBT_DEBUG("Create all Libs");
342 host_lib = xbt_lib_new();
343 link_lib = xbt_lib_new();
344 as_router_lib = xbt_lib_new();
345 storage_lib = xbt_lib_new();
346 storage_type_lib = xbt_lib_new();
347 watched_hosts_lib = xbt_dict_new();
349 XBT_DEBUG("Add routing levels");
350 ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,routing_asr_host_free);
351 ROUTING_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_host_free);
352 ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
354 XBT_DEBUG("Add SURF levels");
355 SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
356 SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
357 SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_resource_free);
359 xbt_init(argc, argv);
361 model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
363 history = tmgr_history_new();
366 TRACE_add_start_function(TRACE_surf_alloc);
367 TRACE_add_end_function(TRACE_surf_release);
370 sg_config_init(argc, argv);
380 ModelPtr model = NULL;
382 sg_config_finalize();
384 xbt_dynar_foreach(model_list, iter, model)
386 xbt_dynar_free(&model_list);
390 lmm_system_free(maxmin_system);
391 maxmin_system = NULL;
394 tmgr_history_free(history);
399 #ifdef CONTEXT_THREADS
400 xbt_parmap_destroy(surf_parmap);
405 xbt_dynar_free(&surf_path);
407 xbt_lib_free(&host_lib);
408 xbt_lib_free(&link_lib);
409 xbt_lib_free(&as_router_lib);
410 xbt_lib_free(&storage_lib);
411 xbt_lib_free(&storage_type_lib);
413 xbt_dict_free(&watched_hosts_lib);
416 surf_parse_lex_destroy();
417 surf_parse_free_callbacks();
419 NOW = 0; /* Just in case the user plans to restart the simulation afterward */
425 Model::Model(string name)
426 : m_name(name), m_resOnCB(0), m_resOffCB(0), m_actSuspendCB(0), m_actCancelCB(0), m_actResumeCB(0)
429 p_readyActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
430 p_runningActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
431 p_failedActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
432 p_doneActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
434 p_modifiedSet = NULL;
436 p_updateMechanism = UM_UNDEFINED;
437 m_selectiveUpdate = 0;
441 xbt_swag_free(p_readyActionSet);
442 xbt_swag_free(p_runningActionSet);
443 xbt_swag_free(p_failedActionSet);
444 xbt_swag_free(p_doneActionSet);
447 double Model::shareResources(double now)
449 //FIXME: to implement
452 double Model::shareResourcesLazy(double now)
454 ActionLmmPtr action = NULL;
459 ("Before share resources, the size of modified actions set is %d",
460 xbt_swag_size(p_modifiedSet));
462 lmm_solve(p_maxminSystem);
465 ("After share resources, The size of modified actions set is %d",
466 xbt_swag_size(p_modifiedSet));
468 while((action = (ActionLmmPtr) xbt_swag_extract(p_modifiedSet))) {
469 int max_dur_flag = 0;
471 if (action->p_stateSet != p_runningActionSet)
474 /* bogus priority, skip it */
475 if (action->m_priority <= 0)
478 action->updateRemainingLazy(now);
481 value = lmm_variable_getvalue(action->p_variable);
483 if (action->m_remains > 0) {
484 value = action->m_remains / value;
492 if ((action->m_maxDuration != NO_MAX_DURATION)
495 action->m_maxDuration < min)) {
496 min = action->m_start +
497 action->m_maxDuration;
501 XBT_DEBUG("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
502 action->m_start, now + value,
503 action->m_maxDuration);
506 action->heapRemove(p_actionHeap);
507 action->heapInsert(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
508 XBT_DEBUG("Insert at heap action(%p) min %lf now %lf", action, min,
510 } else DIE_IMPOSSIBLE;
513 //hereafter must have already the min value for this resource model
514 if (xbt_heap_size(p_actionHeap) > 0)
515 min = xbt_heap_maxkey(p_actionHeap) - now;
519 XBT_DEBUG("The minimum with the HEAP %lf", min);
524 double Model::shareResourcesMaxMin(xbt_swag_t running_actions,
527 void (*solve) (lmm_system_t))
529 void *_action = NULL;
530 ActionPtr action = NULL;
533 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
537 xbt_swag_foreach(_action, running_actions) {
538 action = (ActionPtr)_action;
539 value = lmm_variable_getvalue(VARIABLE(action));
540 if ((value > 0) || (action->m_maxDuration >= 0))
548 if (action->m_remains > 0)
549 min = action->m_remains / value;
552 if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min))
553 min = action->m_maxDuration;
555 min = action->m_maxDuration;
558 for (action = (ActionPtr) xbt_swag_getNext(action, running_actions->offset);
560 action = (ActionPtr) xbt_swag_getNext(action, running_actions->offset)) {
561 value = lmm_variable_getvalue(VARIABLE(action));
563 if (action->m_remains > 0)
564 value = action->m_remains / value;
569 XBT_DEBUG("Updating min (value) with %p: %f", action, min);
572 if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min)) {
573 min = action->m_maxDuration;
574 XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
577 XBT_DEBUG("min value : %f", min);
583 void Model::updateActionsState(double now, double delta)
585 if (p_updateMechanism == UM_FULL)
586 updateActionsStateFull(now, delta);
587 else if (p_updateMechanism == UM_LAZY)
588 updateActionsStateLazy(now, delta);
590 xbt_die("Invalid cpu update mechanism!");
593 void Model::updateActionsStateLazy(double now, double delta)
598 void Model::updateActionsStateFull(double now, double delta)
604 void Model::addTurnedOnCallback(ResourceCallback rc)
609 void Model::notifyResourceTurnedOn(ResourcePtr r)
614 void Model::addTurnedOffCallback(ResourceCallback rc)
619 void Model::notifyResourceTurnedOff(ResourcePtr r)
624 void Model::addActionCancelCallback(ActionCallback ac)
629 void Model::notifyActionCancel(ActionPtr a)
634 void Model::addActionResumeCallback(ActionCallback ac)
639 void Model::notifyActionResume(ActionPtr a)
644 void Model::addActionSuspendCallback(ActionCallback ac)
649 void Model::notifyActionSuspend(ActionPtr a)
659 Resource::Resource(surf_model_t model, const char *name, xbt_dict_t props)
660 : m_name(xbt_strdup(name)), m_running(true), p_model(model), m_properties(props)
663 Resource::Resource(){
664 //FIXME:free(m_name);
665 xbt_dict_free(&m_properties);
668 const char *Resource::getName()
673 xbt_dict_t Resource::getProperties()
678 e_surf_resource_state_t Resource::getState()
680 return m_stateCurrent;
683 bool Resource::isOn()
688 void Resource::turnOn()
692 p_model->notifyResourceTurnedOn(this);
696 void Resource::turnOff()
700 p_model->notifyResourceTurnedOff(this);
704 ResourceLmm::ResourceLmm(surf_model_t model, const char *name, xbt_dict_t props,
706 double constraint_value,
707 tmgr_history_t history,
708 e_surf_resource_state_t state_init,
709 tmgr_trace_t state_trace,
711 tmgr_trace_t metric_trace)
712 : Resource(model, name, props)
714 p_constraint = lmm_constraint_new(system, this, constraint_value);
715 p_stateCurrent = state_init;
717 p_stateEvent = tmgr_history_add_trace(history, state_trace, 0.0, 0, this);
719 p_power.peak = metric_peak;
721 p_power.event = tmgr_history_add_trace(history, metric_trace, 0.0, 0, this);
728 const char *surf_action_state_names[6] = {
730 "SURF_ACTION_RUNNING",
731 "SURF_ACTION_FAILED",
733 "SURF_ACTION_TO_FREE",
734 "SURF_ACTION_NOT_IN_THE_SYSTEM"
738 * \brief Initializes the action module of Surf.
740 void surf_action_init(void) {
742 /* the action mallocator will always provide actions of the following size,
743 * so this size should be set to the maximum size of the surf action structures
745 /*FIXME:action_mallocator_allocated_size = sizeof(s_surf_action_network_CM02_t);
746 action_mallocator = xbt_mallocator_new(65536, surf_action_mallocator_new_f,
747 surf_action_mallocator_free_f, surf_action_mallocator_reset_f);*/
751 * \brief Uninitializes the action module of Surf.
753 void surf_action_exit(void) {
754 //FIXME:xbt_mallocator_free(action_mallocator);
759 Action::Action(ModelPtr model, double cost, bool failed):
760 m_cost(cost), p_model(model), m_failed(failed), m_remains(cost),
761 m_refcount(1), m_priority(1.0), m_maxDuration(NO_MAX_DURATION),
762 m_start(surf_get_clock()), m_finish(-1.0)
768 p_stateSet = p_model->p_failedActionSet;
770 p_stateSet = p_model->p_runningActionSet;
772 xbt_swag_insert(this, p_stateSet);
781 void Action::cancel(){
785 void Action::recycle(){
789 e_surf_action_state_t Action::getState()
791 if (p_stateSet == p_model->p_readyActionSet)
792 return SURF_ACTION_READY;
793 if (p_stateSet == p_model->p_runningActionSet)
794 return SURF_ACTION_RUNNING;
795 if (p_stateSet == p_model->p_failedActionSet)
796 return SURF_ACTION_FAILED;
797 if (p_stateSet == p_model->p_doneActionSet)
798 return SURF_ACTION_DONE;
799 return SURF_ACTION_NOT_IN_THE_SYSTEM;
802 void Action::setState(e_surf_action_state_t state)
804 //surf_action_state_t action_state = &(action->model_type->states);
805 XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
806 xbt_swag_remove(this, p_stateSet);
808 if (state == SURF_ACTION_READY)
809 p_stateSet = p_model->p_readyActionSet;
810 else if (state == SURF_ACTION_RUNNING)
811 p_stateSet = p_model->p_runningActionSet;
812 else if (state == SURF_ACTION_FAILED)
813 p_stateSet = p_model->p_failedActionSet;
814 else if (state == SURF_ACTION_DONE)
815 p_stateSet = p_model->p_doneActionSet;
820 xbt_swag_insert(this, p_stateSet);
824 double Action::getStartTime()
829 double Action::getFinishTime()
831 /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
832 return m_remains == 0 ? m_finish : -1;
835 void Action::setData(void* data)
841 void Action::setCategory(const char *category)
843 XBT_IN("(%p,%s)", this, category);
844 p_category = xbt_strdup(category);
853 void ActionLmm::setMaxDuration(double duration)
855 XBT_IN("(%p,%g)", this, duration);
856 m_maxDuration = duration;
857 if (p_model->p_updateMechanism == UM_LAZY) // remove action from the heap
858 heapRemove(p_model->p_actionHeap);
862 void ActionLmm::gapRemove() {}
864 void ActionLmm::setPriority(double priority)
866 XBT_IN("(%p,%g)", this, priority);
867 m_priority = priority;
868 lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, priority);
870 if (p_model->p_updateMechanism == UM_LAZY)
871 heapRemove(p_model->p_actionHeap);
875 void ActionLmm::cancel(){
876 setState(SURF_ACTION_FAILED);
877 if (p_model->p_updateMechanism == UM_LAZY) {
878 xbt_swag_remove(this, p_model->p_modifiedSet);
879 heapRemove(p_model->p_actionHeap);
883 int ActionLmm::unref(){
886 xbt_swag_remove(this, p_stateSet);
888 lmm_variable_free(p_model->p_maxminSystem, p_variable);
889 if (p_model->p_updateMechanism == UM_LAZY) {
890 /* remove from heap */
891 heapRemove(p_model->p_actionHeap);
892 xbt_swag_remove(this, p_model->p_modifiedSet);
895 xbt_free(p_category);
903 void ActionLmm::suspend()
905 XBT_IN("(%p)", this);
906 if (m_suspended != 2) {
907 lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, 0.0);
909 if (p_model->p_updateMechanism == UM_LAZY)
910 heapRemove(p_model->p_actionHeap);
915 void ActionLmm::resume()
917 XBT_IN("(%p)", this);
918 if (m_suspended != 2) {
919 lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, m_priority);
921 if (p_model->p_updateMechanism == UM_LAZY)
922 heapRemove(p_model->p_actionHeap);
927 bool ActionLmm::isSuspended()
929 return m_suspended == 1;
931 /* insert action on heap using a given key and a hat (heap_action_type)
932 * a hat can be of three types for communications:
934 * NORMAL = this is a normal heap entry stating the date to finish transmitting
935 * LATENCY = this is a heap entry to warn us when the latency is payed
936 * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
938 void ActionLmm::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
941 xbt_heap_push(heap, this, key);
944 void ActionLmm::heapRemove(xbt_heap_t heap)
947 if (m_indexHeap >= 0) {
948 xbt_heap_remove(heap, m_indexHeap);
952 /* added to manage the communication action's heap */
953 void surf_action_lmm_update_index_heap(void *action, int i) {
954 ((ActionLmmPtr)action)->updateIndexHeap(i);
957 void ActionLmm::updateIndexHeap(int i) {
962 double ActionLmm::getRemains()
964 XBT_IN("(%p)", this);
965 /* update remains before return it */
966 if (p_updateMechanism == UM_LAZY) /* update remains before return it */
967 updateRemainingLazy(surf_get_clock());
972 /*void Action::cancel()
974 p_model->notifyActionCancel(this);
977 void Action::suspend()
979 p_model->notifyActionSuspend(this);
982 void Action::resume()
984 p_model->notifyActionResume(this);
987 bool Action::isSuspended()