Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
dcc738c293492b12986f3b3cc65219baa972f9a1
[simgrid.git] / src / surf / cpu_cas01.c
1 /* Copyright (c) 2009-2011. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7 #include "surf_private.h"
8 #include "surf/surf_resource.h"
9
10 surf_model_t surf_cpu_model = NULL;
11 lmm_system_t cpu_maxmin_system = NULL;
12 e_UM_t cpu_update_mechanism = UM_UNDEFINED;
13 static xbt_swag_t cpu_modified_cpu = NULL;
14 static xbt_heap_t cpu_action_heap = NULL;
15 extern int sg_maxmin_selective_update;
16
17 #undef GENERIC_LMM_ACTION
18 #undef GENERIC_ACTION
19 #undef ACTION_GET_CPU
20 #define GENERIC_LMM_ACTION(action) action->generic_lmm_action
21 #define GENERIC_ACTION(action) GENERIC_LMM_ACTION(action).generic_action
22 #define ACTION_GET_CPU(action) ((surf_action_cpu_Cas01_t) action)->cpu
23
24 typedef struct surf_action_cpu_cas01 {
25   s_surf_action_lmm_t generic_lmm_action;
26   s_xbt_swag_hookup_t cpu_list_hookup;
27   int index_heap;
28   void *cpu;
29 } s_surf_action_cpu_Cas01_t, *surf_action_cpu_Cas01_t;
30
31 typedef struct cpu_Cas01 {
32   s_surf_resource_t generic_resource;
33   s_xbt_swag_hookup_t modified_cpu_hookup;
34   double power_peak;
35   double power_scale;
36   tmgr_trace_event_t power_event;
37   int core;
38   e_surf_resource_state_t state_current;
39   tmgr_trace_event_t state_event;
40   lmm_constraint_t constraint;
41   xbt_swag_t action_set;
42   double last_update;
43 } s_cpu_Cas01_t, *cpu_Cas01_t;
44
45 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu, surf,
46                                 "Logging specific to the SURF CPU IMPROVED module");
47
48
49
50 static xbt_swag_t
51     cpu_running_action_set_that_does_not_need_being_checked = NULL;
52
53 static void* cpu_create_resource(const char *name, double power_peak,
54                                  double power_scale,
55                                  tmgr_trace_t power_trace,
56                                  int core,
57                                  e_surf_resource_state_t state_initial,
58                                  tmgr_trace_t state_trace,
59                                  xbt_dict_t cpu_properties)
60 {
61   cpu_Cas01_t cpu = NULL;
62   s_surf_action_cpu_Cas01_t action;
63
64   xbt_assert(!surf_cpu_resource_by_name(name),
65               "Host '%s' declared several times in the platform file",
66               name);
67   cpu = (cpu_Cas01_t) surf_resource_new(sizeof(s_cpu_Cas01_t),
68           surf_cpu_model, name,cpu_properties);
69   cpu->power_peak = power_peak;
70   xbt_assert(cpu->power_peak > 0, "Power has to be >0");
71   cpu->power_scale = power_scale;
72   cpu->core = core;
73   xbt_assert(core>0,"Invalid number of cores %d",core);
74
75   if (power_trace)
76     cpu->power_event =
77         tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
78
79   cpu->state_current = state_initial;
80   if (state_trace)
81     cpu->state_event =
82         tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
83
84   cpu->constraint =
85       lmm_constraint_new(cpu_maxmin_system, cpu,
86                          cpu->core * cpu->power_scale * cpu->power_peak);
87
88   xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, cpu);
89   if(cpu_update_mechanism == UM_LAZY)
90     cpu->action_set = xbt_swag_new(xbt_swag_offset(action, cpu_list_hookup));
91
92   return cpu;
93 }
94
95
96 static void parse_cpu_init(sg_platf_host_cbarg_t host)
97 {
98         cpu_create_resource(host->id,
99                           host->power_peak,
100                           host->power_scale,
101                           host->power_trace,
102                           host->core_amount,
103                           host->initial_state,
104                           host->state_trace,
105                           host->properties);
106 }
107
108 static void cpu_add_traces_cpu(void)
109 {
110   xbt_dict_cursor_t cursor = NULL;
111   char *trace_name, *elm;
112   static int called = 0;
113   if (called)
114     return;
115   called = 1;
116
117   /* connect all traces relative to hosts */
118   xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
119     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
120     cpu_Cas01_t host = surf_cpu_resource_by_name(elm);
121
122     xbt_assert(host, "Host %s undefined", elm);
123     xbt_assert(trace, "Trace %s undefined", trace_name);
124
125     host->state_event =
126         tmgr_history_add_trace(history, trace, 0.0, 0, host);
127   }
128
129   xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
130     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
131     cpu_Cas01_t host = surf_cpu_resource_by_name(elm);
132
133     xbt_assert(host, "Host %s undefined", elm);
134     xbt_assert(trace, "Trace %s undefined", trace_name);
135
136     host->power_event =
137         tmgr_history_add_trace(history, trace, 0.0, 0, host);
138   }
139 }
140
141 static void cpu_define_callbacks()
142 {
143   sg_platf_host_add_cb(parse_cpu_init);
144   sg_platf_postparse_add_cb(cpu_add_traces_cpu);
145 }
146
147 static int cpu_resource_used(void *resource)
148 {
149   return lmm_constraint_used(cpu_maxmin_system,
150                              ((cpu_Cas01_t) resource)->constraint);
151 }
152
153 static int cpu_action_unref(surf_action_t action)
154 {
155   action->refcount--;
156   if (!action->refcount) {
157     xbt_swag_remove(action, action->state_set);
158     if (((surf_action_lmm_t) action)->variable)
159       lmm_variable_free(cpu_maxmin_system,
160                         ((surf_action_lmm_t) action)->variable);
161     if(cpu_update_mechanism == UM_LAZY){
162     /* remove from heap */
163     xbt_heap_remove(cpu_action_heap,
164                     ((surf_action_cpu_Cas01_t) action)->index_heap);
165     xbt_swag_remove(action,
166                     ((cpu_Cas01_t) ACTION_GET_CPU(action))->action_set);
167     xbt_swag_insert(ACTION_GET_CPU(action), cpu_modified_cpu);
168     }
169 #ifdef HAVE_TRACING
170     xbt_free(action->category);
171 #endif
172     surf_action_free(&action);
173     return 1;
174   }
175   return 0;
176 }
177
178 static void cpu_action_cancel(surf_action_t action)
179 {
180   surf_action_state_set(action, SURF_ACTION_FAILED);
181   if(cpu_update_mechanism == UM_LAZY){
182   xbt_heap_remove(cpu_action_heap,
183                   ((surf_action_cpu_Cas01_t) action)->index_heap);
184   xbt_swag_remove(action,
185                   ((cpu_Cas01_t) ACTION_GET_CPU(action))->action_set);
186   }
187   return;
188 }
189
190 static void cpu_cpu_action_state_set(surf_action_t action,
191                                         e_surf_action_state_t state)
192 {
193 /*   if((state==SURF_ACTION_DONE) || (state==SURF_ACTION_FAILED)) */
194 /*     if(((surf_action_lmm_t)action)->variable) { */
195 /*       lmm_variable_disable(cpu_maxmin_system, ((surf_action_lmm_t)action)->variable); */
196 /*       ((surf_action_lmm_t)action)->variable = NULL; */
197 /*     } */
198
199   surf_action_state_set(action, state);
200   return;
201 }
202
203 static void cpu_update_remains(cpu_Cas01_t cpu, double now)
204 {
205   surf_action_cpu_Cas01_t action;
206
207   if (cpu->last_update >= now)
208     return;
209   xbt_swag_foreach(action, cpu->action_set) {
210     if (GENERIC_ACTION(action).state_set !=
211         surf_cpu_model->states.running_action_set)
212       continue;
213
214     /* bogus priority, skip it */
215     if (GENERIC_ACTION(action).priority <= 0)
216       continue;
217
218     if (GENERIC_ACTION(action).remains > 0) {
219       double_update(&(GENERIC_ACTION(action).remains),
220                     lmm_variable_getvalue(GENERIC_LMM_ACTION
221                                           (action).variable) * (now -
222                                                                 cpu->last_update));
223 #ifdef HAVE_TRACING
224       if (TRACE_is_enabled()) {
225         TRACE_surf_host_set_utilization(cpu->generic_resource.name,
226                                         action->
227                                         generic_lmm_action.generic_action.
228                                         data, (surf_action_t) action,
229                                         lmm_variable_getvalue
230                                         (GENERIC_LMM_ACTION
231                                          (action).variable),
232                                         cpu->last_update,
233                                         now - cpu->last_update);
234       }
235 #endif
236       XBT_DEBUG("Update action(%p) remains %lf", action,
237              GENERIC_ACTION(action).remains);
238     }
239   }
240   cpu->last_update = now;
241 }
242
243 static double cpu_share_resources_lazy(double now)
244 {
245   surf_action_cpu_Cas01_t action;
246   double min;
247   double value;
248   cpu_Cas01_t cpu, cpu_next;
249
250   xbt_swag_foreach(cpu, cpu_modified_cpu)
251       cpu_update_remains(cpu, now);
252
253   lmm_solve(cpu_maxmin_system);
254
255   xbt_swag_foreach_safe(cpu, cpu_next, cpu_modified_cpu) {
256     xbt_swag_foreach(action, cpu->action_set) {
257       if (GENERIC_ACTION(action).state_set !=
258           surf_cpu_model->states.running_action_set)
259         continue;
260
261       /* bogus priority, skip it */
262       if (GENERIC_ACTION(action).priority <= 0)
263         continue;
264
265       min = -1;
266       value = lmm_variable_getvalue(GENERIC_LMM_ACTION(action).variable);
267       if (value > 0) {
268         if (GENERIC_ACTION(action).remains > 0) {
269           value = GENERIC_ACTION(action).remains / value;
270           min = now + value;
271         } else {
272           value = 0.0;
273           min = now;
274         }
275       }
276
277       if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION)
278           && (min == -1
279               || GENERIC_ACTION(action).start +
280               GENERIC_ACTION(action).max_duration < min))
281         min =
282             GENERIC_ACTION(action).start +
283             GENERIC_ACTION(action).max_duration;
284
285       XBT_DEBUG("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
286              GENERIC_ACTION(action).start, now + value,
287              GENERIC_ACTION(action).max_duration);
288
289       if (action->index_heap >= 0) {
290         surf_action_cpu_Cas01_t heap_act =
291             xbt_heap_remove(cpu_action_heap, action->index_heap);
292         if (heap_act != action)
293           DIE_IMPOSSIBLE;
294       }
295       if (min != -1) {
296         xbt_heap_push(cpu_action_heap, action, min);
297         XBT_DEBUG("Insert at heap action(%p) min %lf", action, min);
298       }
299     }
300     xbt_swag_remove(cpu, cpu_modified_cpu);
301   }
302   return xbt_heap_size(cpu_action_heap) >
303       0 ? xbt_heap_maxkey(cpu_action_heap) - now : -1;
304 }
305
306 static double cpu_share_resources_full(double now) {
307   surf_action_cpu_Cas01_t action;
308   return generic_maxmin_share_resources(surf_cpu_model->states.running_action_set,
309       xbt_swag_offset(*action, generic_lmm_action.variable),
310       cpu_maxmin_system, lmm_solve);
311 }
312
313 static void cpu_update_actions_state_lazy(double now, double delta)
314 {
315   surf_action_cpu_Cas01_t action;
316   while ((xbt_heap_size(cpu_action_heap) > 0)
317          && (double_equals(xbt_heap_maxkey(cpu_action_heap), now))) {
318     action = xbt_heap_pop(cpu_action_heap);
319     XBT_DEBUG("Action %p: finish", action);
320     GENERIC_ACTION(action).finish = surf_get_clock();
321     /* set the remains to 0 due to precision problems when updating the remaining amount */
322 #ifdef HAVE_TRACING
323     if (TRACE_is_enabled()) {
324       cpu_Cas01_t cpu = ((cpu_Cas01_t)(action->cpu));
325       TRACE_surf_host_set_utilization(cpu->generic_resource.name,
326           GENERIC_LMM_ACTION(action).generic_action.data,
327           (surf_action_t) action,
328           lmm_variable_getvalue (GENERIC_LMM_ACTION(action).variable),
329           cpu->last_update,
330           now - cpu->last_update);
331     }
332 #endif
333     GENERIC_ACTION(action).remains = 0;
334     cpu_cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
335     cpu_update_remains(action->cpu, surf_get_clock());
336   }
337 #ifdef HAVE_TRACING
338   if (TRACE_is_enabled()) {
339     //defining the last timestamp that we can safely dump to trace file
340     //without losing the event ascending order (considering all CPU's)
341     void **data;
342     cpu_Cas01_t cpu;
343     xbt_lib_cursor_t cursor;
344     char *key;
345     double smaller = -1;
346     xbt_lib_foreach(host_lib, cursor, key, data){
347       if(data[SURF_CPU_LEVEL]){
348         cpu = data[SURF_CPU_LEVEL];
349         if (smaller < 0){
350           smaller = cpu->last_update;
351           continue;
352         }
353         if (cpu->last_update < smaller){
354           smaller = cpu->last_update;
355         }
356       }
357     }
358     if (smaller > 0) {
359       TRACE_last_timestamp_to_dump = smaller;
360     }
361   }
362 #endif
363   return;
364 }
365
366 static void cpu_update_actions_state_full(double now, double delta)
367 {
368   surf_action_cpu_Cas01_t action = NULL;
369   surf_action_cpu_Cas01_t next_action = NULL;
370   xbt_swag_t running_actions = surf_cpu_model->states.running_action_set;
371   xbt_swag_foreach_safe(action, next_action, running_actions) {
372 #ifdef HAVE_TRACING
373     if (TRACE_is_enabled()) {
374       cpu_Cas01_t x =
375         lmm_constraint_id(lmm_get_cnst_from_var
376                           (cpu_maxmin_system, GENERIC_LMM_ACTION(action).variable, 0));
377
378       TRACE_surf_host_set_utilization(x->generic_resource.name,
379                                       GENERIC_ACTION(action).data,
380                                       (surf_action_t) action,
381                                       lmm_variable_getvalue
382                                       (GENERIC_LMM_ACTION(action).variable), now - delta,
383                                       delta);
384       TRACE_last_timestamp_to_dump = now-delta;
385     }
386 #endif
387     double_update(&(GENERIC_ACTION(action).remains),
388                   lmm_variable_getvalue(GENERIC_LMM_ACTION(action).variable) * delta);
389     if (GENERIC_LMM_ACTION(action).generic_action.max_duration != NO_MAX_DURATION)
390       double_update(&(GENERIC_ACTION(action).max_duration), delta);
391     if ((GENERIC_ACTION(action).remains <= 0) &&
392         (lmm_get_variable_weight(GENERIC_LMM_ACTION(action).variable) > 0)) {
393       GENERIC_ACTION(action).finish = surf_get_clock();
394       cpu_cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
395     } else if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION) &&
396                (GENERIC_ACTION(action).max_duration <= 0)) {
397       GENERIC_ACTION(action).finish = surf_get_clock();
398       cpu_cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
399     }
400   }
401
402   return;
403 }
404
405 static void cpu_update_resource_state(void *id,
406                                          tmgr_trace_event_t event_type,
407                                          double value, double date)
408 {
409   cpu_Cas01_t cpu = id;
410   lmm_variable_t var = NULL;
411   lmm_element_t elem = NULL;
412
413   if (event_type == cpu->power_event) {
414     cpu->power_scale = value;
415     lmm_update_constraint_bound(cpu_maxmin_system, cpu->constraint,
416                                 cpu->core * cpu->power_scale * cpu->power_peak);
417 #ifdef HAVE_TRACING
418     TRACE_surf_host_set_power(date, cpu->generic_resource.name,
419                               cpu->core * cpu->power_scale * cpu->power_peak);
420 #endif
421     while ((var = lmm_get_var_from_cnst
422             (cpu_maxmin_system, cpu->constraint, &elem))) {
423         surf_action_cpu_Cas01_t action = lmm_variable_id(var);
424         lmm_update_variable_bound(cpu_maxmin_system, GENERIC_LMM_ACTION(action).variable,
425                                   cpu->power_scale * cpu->power_peak);
426     }
427     if(cpu_update_mechanism == UM_LAZY)
428       xbt_swag_insert(cpu, cpu_modified_cpu);
429     if (tmgr_trace_event_free(event_type))
430       cpu->power_event = NULL;
431   } else if (event_type == cpu->state_event) {
432     if (value > 0)
433       cpu->state_current = SURF_RESOURCE_ON;
434     else {
435       lmm_constraint_t cnst = cpu->constraint;
436       lmm_variable_t var = NULL;
437       lmm_element_t elem = NULL;
438
439       cpu->state_current = SURF_RESOURCE_OFF;
440
441       while ((var =
442               lmm_get_var_from_cnst(cpu_maxmin_system, cnst, &elem))) {
443         surf_action_t action = lmm_variable_id(var);
444
445         if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
446             surf_action_state_get(action) == SURF_ACTION_READY ||
447             surf_action_state_get(action) ==
448             SURF_ACTION_NOT_IN_THE_SYSTEM) {
449           action->finish = date;
450           cpu_cpu_action_state_set(action, SURF_ACTION_FAILED);
451         }
452       }
453     }
454     if (tmgr_trace_event_free(event_type))
455       cpu->state_event = NULL;
456   } else {
457     XBT_CRITICAL("Unknown event ! \n");
458     xbt_abort();
459   }
460
461   return;
462 }
463
464 static surf_action_t cpu_execute(void *cpu, double size)
465 {
466   surf_action_cpu_Cas01_t action = NULL;
467   cpu_Cas01_t CPU = cpu;
468
469   XBT_IN("(%s,%g)", surf_resource_name(CPU), size);
470   action =
471       surf_action_new(sizeof(s_surf_action_cpu_Cas01_t), size,
472                       surf_cpu_model,
473                       CPU->state_current != SURF_RESOURCE_ON);
474
475   GENERIC_LMM_ACTION(action).suspended = 0;     /* Should be useless because of the
476                                                    calloc but it seems to help valgrind... */
477
478   GENERIC_LMM_ACTION(action).variable =
479       lmm_variable_new(cpu_maxmin_system, action,
480                        GENERIC_ACTION(action).priority, CPU->power_scale * CPU->power_peak, 1);
481   if(cpu_update_mechanism == UM_LAZY){
482     action->index_heap = -1;
483     action->cpu = CPU;
484     xbt_swag_insert(CPU, cpu_modified_cpu);
485     xbt_swag_insert(action, CPU->action_set);
486   }
487   lmm_expand(cpu_maxmin_system, CPU->constraint,
488              GENERIC_LMM_ACTION(action).variable, 1.0);
489   XBT_OUT();
490   return (surf_action_t) action;
491 }
492
493 static surf_action_t cpu_action_sleep(void *cpu, double duration)
494 {
495   surf_action_cpu_Cas01_t action = NULL;
496
497   if (duration > 0)
498     duration = MAX(duration, MAXMIN_PRECISION);
499
500   XBT_IN("(%s,%g)", surf_resource_name(cpu), duration);
501   action = (surf_action_cpu_Cas01_t) cpu_execute(cpu, 1.0);
502   GENERIC_ACTION(action).max_duration = duration;
503   GENERIC_LMM_ACTION(action).suspended = 2;
504   if (duration == NO_MAX_DURATION) {
505     /* Move to the *end* of the corresponding action set. This convention
506        is used to speed up update_resource_state  */
507     xbt_swag_remove(action, ((surf_action_t) action)->state_set);
508     ((surf_action_t) action)->state_set =
509         cpu_running_action_set_that_does_not_need_being_checked;
510     xbt_swag_insert(action, ((surf_action_t) action)->state_set);
511   }
512
513   lmm_update_variable_weight(cpu_maxmin_system,
514                              GENERIC_LMM_ACTION(action).variable, 0.0);
515   if(cpu_update_mechanism == UM_LAZY)
516     xbt_swag_insert(cpu, cpu_modified_cpu);
517   XBT_OUT();
518   return (surf_action_t) action;
519 }
520
521 static void cpu_action_suspend(surf_action_t action)
522 {
523   XBT_IN("(%p)", action);
524   if (((surf_action_lmm_t) action)->suspended != 2) {
525     lmm_update_variable_weight(cpu_maxmin_system,
526                                ((surf_action_lmm_t) action)->variable,
527                                0.0);
528     ((surf_action_lmm_t) action)->suspended = 1;
529     if(cpu_update_mechanism == UM_LAZY){
530       xbt_heap_remove(cpu_action_heap,
531                       ((surf_action_cpu_Cas01_t) action)->index_heap);
532       xbt_swag_insert(ACTION_GET_CPU(action), cpu_modified_cpu);
533     }
534   }
535   XBT_OUT();
536 }
537
538 static void cpu_action_resume(surf_action_t action)
539 {
540
541   XBT_IN("(%p)", action);
542   if (((surf_action_lmm_t) action)->suspended != 2) {
543     lmm_update_variable_weight(cpu_maxmin_system,
544                                ((surf_action_lmm_t) action)->variable,
545                                action->priority);
546     ((surf_action_lmm_t) action)->suspended = 0;
547     if(cpu_update_mechanism == UM_LAZY)
548       xbt_swag_insert(ACTION_GET_CPU(action), cpu_modified_cpu);
549   }
550   XBT_OUT();
551 }
552
553 static int cpu_action_is_suspended(surf_action_t action)
554 {
555   return (((surf_action_lmm_t) action)->suspended == 1);
556 }
557
558 static void cpu_action_set_max_duration(surf_action_t action,
559                                            double duration)
560 {
561   XBT_IN("(%p,%g)", action, duration);
562
563   action->max_duration = duration;
564   /* insert cpu in modified_cpu set to notice the max duration change */
565   if(cpu_update_mechanism == UM_LAZY)
566     xbt_swag_insert(ACTION_GET_CPU(action), cpu_modified_cpu);
567   XBT_OUT();
568 }
569
570 static void cpu_action_set_priority(surf_action_t action,
571                                        double priority)
572 {
573   XBT_IN("(%p,%g)", action, priority);
574   action->priority = priority;
575   lmm_update_variable_weight(cpu_maxmin_system,
576                              ((surf_action_lmm_t) action)->variable,
577                              priority);
578
579   if(cpu_update_mechanism == UM_LAZY)
580     xbt_swag_insert(ACTION_GET_CPU(action), cpu_modified_cpu);
581   XBT_OUT();
582 }
583
584 #ifdef HAVE_TRACING
585 static void cpu_action_set_category(surf_action_t action,
586                                        const char *category)
587 {
588   XBT_IN("(%p,%s)", action, category);
589   action->category = xbt_strdup (category);
590   XBT_OUT();
591 }
592 #endif
593
594 static double cpu_action_get_remains(surf_action_t action)
595 {
596   XBT_IN("(%p)", action);
597   /* update remains before return it */
598   if(cpu_update_mechanism == UM_LAZY)
599     cpu_update_remains(ACTION_GET_CPU(action), surf_get_clock());
600   return action->remains;
601   XBT_OUT();
602 }
603
604 static e_surf_resource_state_t cpu_get_state(void *cpu)
605 {
606   return ((cpu_Cas01_t) cpu)->state_current;
607 }
608
609 static double cpu_get_speed(void *cpu, double load)
610 {
611   return load * (((cpu_Cas01_t) cpu)->power_peak);
612 }
613
614 static double cpu_get_available_speed(void *cpu)
615 {
616   /* number between 0 and 1 */
617   return ((cpu_Cas01_t) cpu)->power_scale;
618 }
619
620 static void cpu_action_update_index_heap(void *action, int i)
621 {
622   ((surf_action_cpu_Cas01_t) action)->index_heap = i;
623 }
624
625 static void cpu_finalize(void)
626 {
627   void **cpu;
628   xbt_lib_cursor_t cursor;
629   char *key;
630
631   xbt_lib_foreach(host_lib, cursor, key, cpu){
632     if(cpu[SURF_CPU_LEVEL])
633     {
634         cpu_Cas01_t CPU = cpu[SURF_CPU_LEVEL];
635         xbt_swag_free(CPU->action_set);
636     }
637   }
638
639   lmm_system_free(cpu_maxmin_system);
640   cpu_maxmin_system = NULL;
641
642   surf_model_exit(surf_cpu_model);
643   surf_cpu_model = NULL;
644
645   xbt_swag_free
646       (cpu_running_action_set_that_does_not_need_being_checked);
647   cpu_running_action_set_that_does_not_need_being_checked = NULL;
648   if(cpu_action_heap)  xbt_heap_free(cpu_action_heap);
649   if(cpu_modified_cpu) xbt_swag_free(cpu_modified_cpu);
650 }
651
652 static void surf_cpu_model_init_internal(const char* name)
653 {
654   s_surf_action_t action;
655   s_cpu_Cas01_t cpu;
656
657   surf_cpu_model = surf_model_init();
658
659   cpu_running_action_set_that_does_not_need_being_checked =
660       xbt_swag_new(xbt_swag_offset(action, state_hookup));
661
662   surf_cpu_model->name = name;
663
664   surf_cpu_model->action_unref = cpu_action_unref;
665   surf_cpu_model->action_cancel = cpu_action_cancel;
666   surf_cpu_model->action_state_set = cpu_cpu_action_state_set;
667
668   surf_cpu_model->model_private->resource_used = cpu_resource_used;
669
670   if(cpu_update_mechanism == UM_LAZY) {
671     surf_cpu_model->model_private->share_resources = cpu_share_resources_lazy;
672     surf_cpu_model->model_private->update_actions_state = cpu_update_actions_state_lazy;
673   } else if (cpu_update_mechanism == UM_FULL) {
674     surf_cpu_model->model_private->share_resources = cpu_share_resources_full;
675     surf_cpu_model->model_private->update_actions_state = cpu_update_actions_state_full;
676   } else
677     xbt_die("Invalid update mechanism!");
678
679   surf_cpu_model->model_private->update_resource_state =
680       cpu_update_resource_state;
681   surf_cpu_model->model_private->finalize = cpu_finalize;
682
683   surf_cpu_model->suspend = cpu_action_suspend;
684   surf_cpu_model->resume = cpu_action_resume;
685   surf_cpu_model->is_suspended = cpu_action_is_suspended;
686   surf_cpu_model->set_max_duration = cpu_action_set_max_duration;
687   surf_cpu_model->set_priority = cpu_action_set_priority;
688 #ifdef HAVE_TRACING
689   surf_cpu_model->set_category = cpu_action_set_category;
690 #endif
691   surf_cpu_model->get_remains = cpu_action_get_remains;
692
693   surf_cpu_model->extension.cpu.execute = cpu_execute;
694   surf_cpu_model->extension.cpu.sleep = cpu_action_sleep;
695
696   surf_cpu_model->extension.cpu.get_state = cpu_get_state;
697   surf_cpu_model->extension.cpu.get_speed = cpu_get_speed;
698   surf_cpu_model->extension.cpu.get_available_speed =
699       cpu_get_available_speed;
700   surf_cpu_model->extension.cpu.create_resource = cpu_create_resource;
701   surf_cpu_model->extension.cpu.add_traces = cpu_add_traces_cpu;
702
703   if (!cpu_maxmin_system) {
704     sg_maxmin_selective_update = 1;
705     cpu_maxmin_system = lmm_system_new();
706   }
707   if(cpu_update_mechanism == UM_LAZY){
708     cpu_action_heap = xbt_heap_new(8, NULL);
709     xbt_heap_set_update_callback(cpu_action_heap,
710                                  cpu_action_update_index_heap);
711     cpu_modified_cpu =
712         xbt_swag_new(xbt_swag_offset(cpu, modified_cpu_hookup));
713   }
714 }
715
716 /*********************************************************************/
717 /* Basic sharing model for CPU: that is where all this started... ;) */
718 /*********************************************************************/
719 /* @InProceedings{casanova01simgrid, */
720 /*   author =       "H. Casanova", */
721 /*   booktitle =    "Proceedings of the IEEE Symposium on Cluster Computing */
722 /*                  and the Grid (CCGrid'01)", */
723 /*   publisher =    "IEEE Computer Society", */
724 /*   title =        "Simgrid: {A} Toolkit for the Simulation of Application */
725 /*                  Scheduling", */
726 /*   year =         "2001", */
727 /*   month =        may, */
728 /*   note =         "Available at */
729 /*                  \url{http://grail.sdsc.edu/papers/simgrid_ccgrid01.ps.gz}." */
730 /* } */
731
732 void surf_cpu_model_init_Cas01()
733 {
734   char *optim = xbt_cfg_get_string(_surf_cfg_set, "cpu/optim");
735   char *model = xbt_cfg_get_string(_surf_cfg_set, "cpu/model");
736
737   if(!strcmp(model,"Cas01_fullupdate")) {
738     XBT_WARN("[*Deprecated*. Use --cfg=cpu/model:Cas01 with option --cfg=cpu/optim:Full instead.]");
739   } else if(!strcmp(model,"CpuTI")) {
740     XBT_WARN("[*Deprecated*. Use --cfg=cpu/model:Cas01 with option --cfg=cpu/optim:TI instead.]");
741   }
742
743   if(!strcmp(optim,"Full")) {
744     cpu_update_mechanism = UM_FULL;
745   } else if (!strcmp(optim,"Lazy")) {
746     cpu_update_mechanism = UM_LAZY;
747   } else if (!strcmp(optim,"TI")) {
748     surf_cpu_model_init_ti();
749     return;
750   } else {
751     xbt_die("Unsupported optimization (%s) for this model",optim);
752   }
753
754   if (surf_cpu_model)
755     return;
756   surf_cpu_model_init_internal("CPU");
757   cpu_define_callbacks();
758   xbt_dynar_push(model_list, &surf_cpu_model);
759 }