1 /* Copyright (c) 2009, 2010. 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"
9 #undef GENERIC_LMM_ACTION
12 #define GENERIC_LMM_ACTION(action) action->generic_lmm_action
13 #define GENERIC_ACTION(action) GENERIC_LMM_ACTION(action).generic_action
14 #define ACTION_GET_CPU(action) ((surf_action_cpu_Cas01_im_t) action)->cpu
16 typedef struct surf_action_cpu_cas01_im {
17 s_surf_action_lmm_t generic_lmm_action;
18 s_xbt_swag_hookup_t cpu_list_hookup;
21 } s_surf_action_cpu_Cas01_im_t, *surf_action_cpu_Cas01_im_t;
23 typedef struct cpu_Cas01_im {
24 s_surf_resource_t generic_resource;
25 s_xbt_swag_hookup_t modified_cpu_hookup;
28 tmgr_trace_event_t power_event;
29 e_surf_resource_state_t state_current;
30 tmgr_trace_event_t state_event;
31 lmm_constraint_t constraint;
32 xbt_swag_t action_set;
34 } s_cpu_Cas01_im_t, *cpu_Cas01_im_t;
36 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu_im, surf,
37 "Logging specific to the SURF CPU IMPROVED module");
40 lmm_system_t cpu_im_maxmin_system = NULL;
41 static xbt_swag_t cpu_im_modified_cpu = NULL;
42 static xbt_heap_t cpu_im_action_heap = NULL;
43 extern int sg_maxmin_selective_update;
47 cpu_im_running_action_set_that_does_not_need_being_checked = NULL;
49 static cpu_Cas01_im_t cpu_im_new(char *name, double power_peak,
51 tmgr_trace_t power_trace,
53 e_surf_resource_state_t state_initial,
54 tmgr_trace_t state_trace,
55 xbt_dict_t cpu_properties)
57 cpu_Cas01_im_t cpu = NULL;
58 s_surf_action_cpu_Cas01_im_t action;
59 cpu = xbt_new0(s_cpu_Cas01_im_t, 1);
61 xbt_assert0(core==1,"Multi-core not handled with this model yet");
63 TRACE_surf_host_declaration(name, power_scale * power_peak);
66 xbt_assert1(!surf_model_resource_by_name(surf_cpu_model, name),
67 "Host '%s' declared several times in the platform file",
69 cpu->generic_resource.model = surf_cpu_model;
70 cpu->generic_resource.name = name;
71 cpu->generic_resource.properties = cpu_properties;
72 cpu->power_peak = power_peak;
73 xbt_assert0(cpu->power_peak > 0, "Power has to be >0");
74 cpu->power_scale = power_scale;
77 tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
79 cpu->state_current = state_initial;
82 tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
85 lmm_constraint_new(cpu_im_maxmin_system, cpu,
86 cpu->power_scale * cpu->power_peak);
88 xbt_dict_set(surf_model_resource_set(surf_cpu_model), name, cpu,
90 cpu->action_set = xbt_swag_new(xbt_swag_offset(action, cpu_list_hookup));
96 static void parse_cpu_im_init(void)
98 double power_peak = 0.0;
99 double power_scale = 0.0;
101 tmgr_trace_t power_trace = NULL;
102 e_surf_resource_state_t state_initial = SURF_RESOURCE_OFF;
103 tmgr_trace_t state_trace = NULL;
105 power_peak = get_cpu_power(A_surfxml_host_power);
106 surf_parse_get_double(&power_scale, A_surfxml_host_availability);
107 power_trace = tmgr_trace_new(A_surfxml_host_availability_file);
108 surf_parse_get_int(&core, A_surfxml_host_core);
110 xbt_assert0((A_surfxml_host_state == A_surfxml_host_state_ON) ||
111 (A_surfxml_host_state == A_surfxml_host_state_OFF),
113 if (A_surfxml_host_state == A_surfxml_host_state_ON)
114 state_initial = SURF_RESOURCE_ON;
115 if (A_surfxml_host_state == A_surfxml_host_state_OFF)
116 state_initial = SURF_RESOURCE_OFF;
117 state_trace = tmgr_trace_new(A_surfxml_host_state_file);
119 current_property_set = xbt_dict_new();
120 cpu_im_new(xbt_strdup(A_surfxml_host_id), power_peak, power_scale,
121 power_trace, core, state_initial, state_trace,
122 current_property_set);
126 static void cpu_im_add_traces_cpu(void)
128 xbt_dict_cursor_t cursor = NULL;
129 char *trace_name, *elm;
130 static int called = 0;
135 /* connect all traces relative to hosts */
136 xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
137 tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
138 cpu_Cas01_im_t host = surf_model_resource_by_name(surf_cpu_model, elm);
140 xbt_assert1(host, "Host %s undefined", elm);
141 xbt_assert1(trace, "Trace %s undefined", trace_name);
144 tmgr_history_add_trace(history, trace, 0.0, 0, host);
147 xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
148 tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
149 cpu_Cas01_im_t host = surf_model_resource_by_name(surf_cpu_model, elm);
151 xbt_assert1(host, "Host %s undefined", elm);
152 xbt_assert1(trace, "Trace %s undefined", trace_name);
155 tmgr_history_add_trace(history, trace, 0.0, 0, host);
159 static void cpu_im_define_callbacks(const char *file)
162 surf_parse_reset_parser();
163 surfxml_add_callback(STag_surfxml_host_cb_list, parse_cpu_im_init);
164 surfxml_add_callback(ETag_surfxml_platform_cb_list,
165 &cpu_im_add_traces_cpu);
168 static int cpu_im_resource_used(void *resource_id)
170 return lmm_constraint_used(cpu_im_maxmin_system,
171 ((cpu_Cas01_im_t) resource_id)->constraint);
174 static int cpu_im_action_unref(surf_action_t action)
177 if (!action->refcount) {
178 xbt_swag_remove(action, action->state_set);
179 if (((surf_action_lmm_t) action)->variable)
180 lmm_variable_free(cpu_im_maxmin_system,
181 ((surf_action_lmm_t) action)->variable);
182 /* remove from heap */
183 xbt_heap_remove(cpu_im_action_heap,
184 ((surf_action_cpu_Cas01_im_t) action)->index_heap);
185 xbt_swag_remove(action,
186 ((cpu_Cas01_im_t) ACTION_GET_CPU(action))->action_set);
187 xbt_swag_insert(ACTION_GET_CPU(action), cpu_im_modified_cpu);
189 if (action->category)
190 xbt_free(action->category);
198 static void cpu_im_action_cancel(surf_action_t action)
200 surf_action_state_set(action, SURF_ACTION_FAILED);
201 xbt_heap_remove(cpu_im_action_heap,
202 ((surf_action_cpu_Cas01_im_t) action)->index_heap);
203 xbt_swag_remove(action,
204 ((cpu_Cas01_im_t) ACTION_GET_CPU(action))->action_set);
208 static void cpu_im_cpu_action_state_set(surf_action_t action,
209 e_surf_action_state_t state)
211 /* if((state==SURF_ACTION_DONE) || (state==SURF_ACTION_FAILED)) */
212 /* if(((surf_action_lmm_t)action)->variable) { */
213 /* lmm_variable_disable(cpu_im_maxmin_system, ((surf_action_lmm_t)action)->variable); */
214 /* ((surf_action_lmm_t)action)->variable = NULL; */
217 surf_action_state_set(action, state);
221 static void cpu_im_update_remains(cpu_Cas01_im_t cpu, double now)
223 surf_action_cpu_Cas01_im_t action;
225 if (cpu->last_update >= now)
227 xbt_swag_foreach(action, cpu->action_set) {
228 if (GENERIC_ACTION(action).state_set !=
229 surf_cpu_model->states.running_action_set)
232 /* bogus priority, skip it */
233 if (GENERIC_ACTION(action).priority <= 0)
236 if (GENERIC_ACTION(action).remains > 0) {
237 double_update(&(GENERIC_ACTION(action).remains),
238 lmm_variable_getvalue(GENERIC_LMM_ACTION
239 (action).variable) * (now -
242 TRACE_surf_host_set_utilization(cpu->generic_resource.name,
244 generic_lmm_action.generic_action.
245 data, (surf_action_t) action,
246 lmm_variable_getvalue
250 now - cpu->last_update);
252 DEBUG2("Update action(%p) remains %lf", action,
253 GENERIC_ACTION(action).remains);
256 cpu->last_update = now;
259 static double cpu_im_share_resources(double now)
261 surf_action_cpu_Cas01_im_t action;
264 cpu_Cas01_im_t cpu, cpu_next;
266 xbt_swag_foreach(cpu, cpu_im_modified_cpu)
267 cpu_im_update_remains(cpu, now);
269 lmm_solve(cpu_im_maxmin_system);
271 xbt_swag_foreach_safe(cpu, cpu_next, cpu_im_modified_cpu) {
272 xbt_swag_foreach(action, cpu->action_set) {
273 if (GENERIC_ACTION(action).state_set !=
274 surf_cpu_model->states.running_action_set)
277 /* bogus priority, skip it */
278 if (GENERIC_ACTION(action).priority <= 0)
282 value = lmm_variable_getvalue(GENERIC_LMM_ACTION(action).variable);
284 if (GENERIC_ACTION(action).remains > 0) {
285 value = GENERIC_ACTION(action).remains / value;
293 if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION)
295 || GENERIC_ACTION(action).start +
296 GENERIC_ACTION(action).max_duration < min))
298 GENERIC_ACTION(action).start +
299 GENERIC_ACTION(action).max_duration;
301 DEBUG4("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
302 GENERIC_ACTION(action).start, now + value,
303 GENERIC_ACTION(action).max_duration);
305 if (action->index_heap >= 0) {
306 surf_action_cpu_Cas01_im_t heap_act =
307 xbt_heap_remove(cpu_im_action_heap, action->index_heap);
308 if (heap_act != action)
312 xbt_heap_push(cpu_im_action_heap, action, min);
313 DEBUG2("Insert at heap action(%p) min %lf", action, min);
316 xbt_swag_remove(cpu, cpu_im_modified_cpu);
318 return xbt_heap_size(cpu_im_action_heap) >
319 0 ? xbt_heap_maxkey(cpu_im_action_heap) - now : -1;
322 static void cpu_im_update_actions_state(double now, double delta)
324 surf_action_cpu_Cas01_im_t action;
326 while ((xbt_heap_size(cpu_im_action_heap) > 0)
327 && (double_equals(xbt_heap_maxkey(cpu_im_action_heap), now))) {
328 action = xbt_heap_pop(cpu_im_action_heap);
329 DEBUG1("Action %p: finish", action);
330 GENERIC_ACTION(action).finish = surf_get_clock();
331 /* set the remains to 0 due to precision problems when updating the remaining amount */
333 TRACE_surf_host_set_utilization(((cpu_Cas01_im_t)
334 (action->cpu))->generic_resource.name,
336 generic_lmm_action.generic_action.data,
337 (surf_action_t) action,
338 lmm_variable_getvalue
339 (GENERIC_LMM_ACTION(action).variable),
341 (action->cpu))->last_update,
344 (action->cpu))->last_update);
346 GENERIC_ACTION(action).remains = 0;
347 cpu_im_cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
348 cpu_im_update_remains(action->cpu, surf_get_clock());
353 static void cpu_im_update_resource_state(void *id,
354 tmgr_trace_event_t event_type,
355 double value, double date)
357 cpu_Cas01_im_t cpu = id;
358 if (event_type == cpu->power_event) {
359 cpu->power_scale = value;
360 lmm_update_constraint_bound(cpu_im_maxmin_system, cpu->constraint,
361 cpu->power_scale * cpu->power_peak);
363 TRACE_surf_host_set_power(date, cpu->generic_resource.name,
364 cpu->power_scale * cpu->power_peak);
366 xbt_swag_insert(cpu, cpu_im_modified_cpu);
367 if (tmgr_trace_event_free(event_type))
368 cpu->power_event = NULL;
369 } else if (event_type == cpu->state_event) {
371 cpu->state_current = SURF_RESOURCE_ON;
373 lmm_constraint_t cnst = cpu->constraint;
374 lmm_variable_t var = NULL;
375 lmm_element_t elem = NULL;
377 cpu->state_current = SURF_RESOURCE_OFF;
380 lmm_get_var_from_cnst(cpu_im_maxmin_system, cnst, &elem))) {
381 surf_action_t action = lmm_variable_id(var);
383 if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
384 surf_action_state_get(action) == SURF_ACTION_READY ||
385 surf_action_state_get(action) ==
386 SURF_ACTION_NOT_IN_THE_SYSTEM) {
387 action->finish = date;
388 cpu_im_cpu_action_state_set(action, SURF_ACTION_FAILED);
392 if (tmgr_trace_event_free(event_type))
393 cpu->state_event = NULL;
395 CRITICAL0("Unknown event ! \n");
402 static surf_action_t cpu_im_execute(void *cpu, double size)
404 surf_action_cpu_Cas01_im_t action = NULL;
405 cpu_Cas01_im_t CPU = cpu;
407 XBT_IN2("(%s,%g)", surf_resource_name(CPU), size);
409 surf_action_new(sizeof(s_surf_action_cpu_Cas01_im_t), size,
411 CPU->state_current != SURF_RESOURCE_ON);
413 GENERIC_LMM_ACTION(action).suspended = 0; /* Should be useless because of the
414 calloc but it seems to help valgrind... */
416 GENERIC_LMM_ACTION(action).variable =
417 lmm_variable_new(cpu_im_maxmin_system, action,
418 GENERIC_ACTION(action).priority, -1.0, 1);
419 action->index_heap = -1;
421 xbt_swag_insert(CPU, cpu_im_modified_cpu);
422 xbt_swag_insert(action, CPU->action_set);
423 lmm_expand(cpu_im_maxmin_system, CPU->constraint,
424 GENERIC_LMM_ACTION(action).variable, 1.0);
426 return (surf_action_t) action;
429 static surf_action_t cpu_im_action_sleep(void *cpu, double duration)
431 surf_action_cpu_Cas01_im_t action = NULL;
434 duration = MAX(duration, MAXMIN_PRECISION);
436 XBT_IN2("(%s,%g)", surf_resource_name(cpu), duration);
437 action = (surf_action_cpu_Cas01_im_t) cpu_im_execute(cpu, 1.0);
438 GENERIC_ACTION(action).max_duration = duration;
439 GENERIC_LMM_ACTION(action).suspended = 2;
440 if (duration == NO_MAX_DURATION) {
441 /* Move to the *end* of the corresponding action set. This convention
442 is used to speed up update_resource_state */
443 xbt_swag_remove(action, ((surf_action_t) action)->state_set);
444 ((surf_action_t) action)->state_set =
445 cpu_im_running_action_set_that_does_not_need_being_checked;
446 xbt_swag_insert(action, ((surf_action_t) action)->state_set);
449 lmm_update_variable_weight(cpu_im_maxmin_system,
450 GENERIC_LMM_ACTION(action).variable, 0.0);
451 xbt_swag_insert(cpu, cpu_im_modified_cpu);
453 return (surf_action_t) action;
456 static void cpu_im_action_suspend(surf_action_t action)
458 XBT_IN1("(%p)", action);
459 if (((surf_action_lmm_t) action)->suspended != 2) {
460 lmm_update_variable_weight(cpu_im_maxmin_system,
461 ((surf_action_lmm_t) action)->variable,
463 ((surf_action_lmm_t) action)->suspended = 1;
464 xbt_heap_remove(cpu_im_action_heap,
465 ((surf_action_cpu_Cas01_im_t) action)->index_heap);
466 xbt_swag_insert(ACTION_GET_CPU(action), cpu_im_modified_cpu);
471 static void cpu_im_action_resume(surf_action_t action)
474 XBT_IN1("(%p)", action);
475 if (((surf_action_lmm_t) action)->suspended != 2) {
476 lmm_update_variable_weight(cpu_im_maxmin_system,
477 ((surf_action_lmm_t) action)->variable,
479 ((surf_action_lmm_t) action)->suspended = 0;
480 xbt_swag_insert(ACTION_GET_CPU(action), cpu_im_modified_cpu);
485 static int cpu_im_action_is_suspended(surf_action_t action)
487 return (((surf_action_lmm_t) action)->suspended == 1);
490 static void cpu_im_action_set_max_duration(surf_action_t action,
493 XBT_IN2("(%p,%g)", action, duration);
495 action->max_duration = duration;
496 /* insert cpu in modified_cpu set to notice the max duration change */
497 xbt_swag_insert(ACTION_GET_CPU(action), cpu_im_modified_cpu);
501 static void cpu_im_action_set_priority(surf_action_t action,
504 XBT_IN2("(%p,%g)", action, priority);
505 action->priority = priority;
506 lmm_update_variable_weight(cpu_im_maxmin_system,
507 ((surf_action_lmm_t) action)->variable,
510 xbt_swag_insert(ACTION_GET_CPU(action), cpu_im_modified_cpu);
514 static double cpu_im_action_get_remains(surf_action_t action)
516 XBT_IN1("(%p)", action);
517 /* update remains before return it */
518 cpu_im_update_remains(ACTION_GET_CPU(action), surf_get_clock());
519 return action->remains;
523 static e_surf_resource_state_t cpu_im_get_state(void *cpu)
525 return ((cpu_Cas01_im_t) cpu)->state_current;
528 static double cpu_im_get_speed(void *cpu, double load)
530 return load * (((cpu_Cas01_im_t) cpu)->power_peak);
533 static double cpu_im_get_available_speed(void *cpu)
535 /* number between 0 and 1 */
536 return ((cpu_Cas01_im_t) cpu)->power_scale;
539 static void cpu_im_action_update_index_heap(void *action, int i)
541 ((surf_action_cpu_Cas01_im_t) action)->index_heap = i;
544 static void cpu_im_create_resource(char *name, double power_peak,
546 tmgr_trace_t power_trace,
548 e_surf_resource_state_t state_initial,
549 tmgr_trace_t state_trace,
550 xbt_dict_t cpu_properties)
552 xbt_assert0(core==1,"Multi-core not handled with this model yet");
553 cpu_im_new(name, power_peak, power_scale, power_trace, core,
554 state_initial, state_trace, cpu_properties);
557 static void cpu_im_finalize(void)
560 xbt_dict_cursor_t cursor;
562 xbt_dict_foreach(surf_model_resource_set(surf_cpu_model), cursor, key,
564 cpu_Cas01_im_t CPU = cpu;
565 xbt_swag_free(CPU->action_set);
568 lmm_system_free(cpu_im_maxmin_system);
569 cpu_im_maxmin_system = NULL;
571 surf_model_exit(surf_cpu_model);
572 surf_cpu_model = NULL;
575 (cpu_im_running_action_set_that_does_not_need_being_checked);
576 cpu_im_running_action_set_that_does_not_need_being_checked = NULL;
577 xbt_heap_free(cpu_im_action_heap);
578 xbt_swag_free(cpu_im_modified_cpu);
581 static void surf_cpu_im_model_init_internal(void)
583 s_surf_action_t action;
584 s_cpu_Cas01_im_t cpu;
586 surf_cpu_model = surf_model_init();
588 cpu_im_running_action_set_that_does_not_need_being_checked =
589 xbt_swag_new(xbt_swag_offset(action, state_hookup));
591 surf_cpu_model->name = "CPU_IM";
593 surf_cpu_model->action_unref = cpu_im_action_unref;
594 surf_cpu_model->action_cancel = cpu_im_action_cancel;
595 surf_cpu_model->action_state_set = cpu_im_cpu_action_state_set;
597 surf_cpu_model->model_private->resource_used = cpu_im_resource_used;
598 surf_cpu_model->model_private->share_resources = cpu_im_share_resources;
599 surf_cpu_model->model_private->update_actions_state =
600 cpu_im_update_actions_state;
601 surf_cpu_model->model_private->update_resource_state =
602 cpu_im_update_resource_state;
603 surf_cpu_model->model_private->finalize = cpu_im_finalize;
605 surf_cpu_model->suspend = cpu_im_action_suspend;
606 surf_cpu_model->resume = cpu_im_action_resume;
607 surf_cpu_model->is_suspended = cpu_im_action_is_suspended;
608 surf_cpu_model->set_max_duration = cpu_im_action_set_max_duration;
609 surf_cpu_model->set_priority = cpu_im_action_set_priority;
610 surf_cpu_model->get_remains = cpu_im_action_get_remains;
612 surf_cpu_model->extension.cpu.execute = cpu_im_execute;
613 surf_cpu_model->extension.cpu.sleep = cpu_im_action_sleep;
615 surf_cpu_model->extension.cpu.get_state = cpu_im_get_state;
616 surf_cpu_model->extension.cpu.get_speed = cpu_im_get_speed;
617 surf_cpu_model->extension.cpu.get_available_speed =
618 cpu_im_get_available_speed;
619 surf_cpu_model->extension.cpu.create_resource = cpu_im_create_resource;
620 surf_cpu_model->extension.cpu.add_traces = cpu_im_add_traces_cpu;
622 if (!cpu_im_maxmin_system) {
623 sg_maxmin_selective_update = 1;
624 cpu_im_maxmin_system = lmm_system_new();
626 cpu_im_action_heap = xbt_heap_new(8, NULL);
627 xbt_heap_set_update_callback(cpu_im_action_heap,
628 cpu_im_action_update_index_heap);
629 cpu_im_modified_cpu =
630 xbt_swag_new(xbt_swag_offset(cpu, modified_cpu_hookup));
633 /*********************************************************************/
634 /* Basic sharing model for CPU: that is where all this started... ;) */
635 /*********************************************************************/
636 /* @InProceedings{casanova01simgrid, */
637 /* author = "H. Casanova", */
638 /* booktitle = "Proceedings of the IEEE Symposium on Cluster Computing */
639 /* and the Grid (CCGrid'01)", */
640 /* publisher = "IEEE Computer Society", */
641 /* title = "Simgrid: {A} Toolkit for the Simulation of Application */
645 /* note = "Available at */
646 /* \url{http://grail.sdsc.edu/papers/simgrid_ccgrid01.ps.gz}." */
648 void surf_cpu_model_init_Cas01_im(const char *filename)
652 surf_cpu_im_model_init_internal();
653 cpu_im_define_callbacks(filename);
654 xbt_dynar_push(model_list, &surf_cpu_model);