Logo AND Algorithmique Numérique Distribuée

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