Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
10eb8715338b70e4e204bc70c89aa5c5abd8b4ba
[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                                         ((surf_action_t)action)->category,
249                                         lmm_variable_getvalue(GENERIC_LMM_ACTION(action).variable),
250                                         GENERIC_LMM_ACTION(action).last_update,
251                                         now - GENERIC_LMM_ACTION(action).last_update);
252       }
253 #endif
254       XBT_DEBUG("Update action(%p) remains %lf", action,
255                 GENERIC_ACTION(action).remains);
256     }
257     GENERIC_LMM_ACTION(action).last_update = now;
258   }
259
260 }
261
262 static double cpu_share_resources_lazy(double now)
263 {
264   surf_action_cpu_Cas01_t action = NULL;
265   double min = -1;
266   double value;
267
268   XBT_DEBUG
269       ("Before share resources, the size of modified actions set is %d",
270        xbt_swag_size(cpu_modified_set));
271   update_action_remaining_lazy(now);
272
273   lmm_solve(cpu_maxmin_system);
274
275   XBT_DEBUG
276       ("After share resources, The size of modified actions set is %d",
277        xbt_swag_size(cpu_modified_set));
278
279   xbt_swag_foreach(action, cpu_modified_set) {
280     int max_dur_flag = 0;
281
282     if (GENERIC_ACTION(action).state_set !=
283         surf_cpu_model->states.running_action_set)
284       continue;
285
286     /* bogus priority, skip it */
287     if (GENERIC_ACTION(action).priority <= 0)
288       continue;
289
290     min = -1;
291     value = lmm_variable_getvalue(GENERIC_LMM_ACTION(action).variable);
292     if (value > 0) {
293       if (GENERIC_ACTION(action).remains > 0) {
294         value = GENERIC_ACTION(action).remains / value;
295         min = now + value;
296       } else {
297         value = 0.0;
298         min = now;
299       }
300     }
301
302     if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION)
303         && (min == -1
304             || GENERIC_ACTION(action).start +
305             GENERIC_ACTION(action).max_duration < min)) {
306       min = GENERIC_ACTION(action).start +
307           GENERIC_ACTION(action).max_duration;
308       max_dur_flag = 1;
309     }
310
311     XBT_DEBUG("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
312         GENERIC_ACTION(action).start, now + value,
313         GENERIC_ACTION(action).max_duration);
314
315     if (min != -1) {
316       heap_remove(action);
317       heap_insert(action, min, max_dur_flag ? MAX_DURATION : NORMAL);
318       XBT_DEBUG("Insert at heap action(%p) min %lf now %lf", action, min,
319                 now);
320     } else DIE_IMPOSSIBLE;
321   }
322
323   //hereafter must have already the min value for this resource model
324   if (xbt_heap_size(cpu_action_heap) > 0)
325     min = xbt_heap_maxkey(cpu_action_heap) - now;
326   else
327     min = -1;
328
329   XBT_DEBUG("The minimum with the HEAP %lf", min);
330
331   return min;
332 }
333
334 static double cpu_share_resources_full(double now)
335 {
336   s_surf_action_cpu_Cas01_t action;
337   return generic_maxmin_share_resources(surf_cpu_model->states.
338                                         running_action_set,
339                                         xbt_swag_offset(action,
340                                                         generic_lmm_action.
341                                                         variable),
342                                         cpu_maxmin_system, lmm_solve);
343 }
344
345 static void cpu_update_actions_state_lazy(double now, double delta)
346 {
347   surf_action_cpu_Cas01_t action;
348   while ((xbt_heap_size(cpu_action_heap) > 0)
349          && (double_equals(xbt_heap_maxkey(cpu_action_heap), now))) {
350     action = xbt_heap_pop(cpu_action_heap);
351     XBT_DEBUG("Action %p: finish", action);
352     GENERIC_ACTION(action).finish = surf_get_clock();
353 #ifdef HAVE_TRACING
354     if (TRACE_is_enabled()) {
355       cpu_Cas01_t cpu =
356           lmm_constraint_id(lmm_get_cnst_from_var
357                             (cpu_maxmin_system,
358                              GENERIC_LMM_ACTION(action).variable, 0));
359       TRACE_surf_host_set_utilization(cpu->generic_resource.name,
360                                       ((surf_action_t)action)->category,
361                                       lmm_variable_getvalue(GENERIC_LMM_ACTION(action).variable),
362                                       GENERIC_LMM_ACTION(action).last_update,
363                                       now - GENERIC_LMM_ACTION(action).last_update);
364     }
365 #endif
366     /* set the remains to 0 due to precision problems when updating the remaining amount */
367     GENERIC_ACTION(action).remains = 0;
368     cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
369     heap_remove(action);
370   }
371 #ifdef HAVE_TRACING
372   if (TRACE_is_enabled()) {
373     //defining the last timestamp that we can safely dump to trace file
374     //without losing the event ascending order (considering all CPU's)
375     double smaller = -1;
376     xbt_swag_t running_actions = surf_cpu_model->states.running_action_set;
377     xbt_swag_foreach(action, running_actions) {
378         if (smaller < 0) {
379           smaller = GENERIC_LMM_ACTION(action).last_update;
380           continue;
381         }
382         if (GENERIC_LMM_ACTION(action).last_update < smaller) {
383           smaller = GENERIC_LMM_ACTION(action).last_update;
384         }
385     }
386     if (smaller > 0) {
387       TRACE_last_timestamp_to_dump = smaller;
388     }
389   }
390 #endif
391   return;
392 }
393
394 static void cpu_update_actions_state_full(double now, double delta)
395 {
396   surf_action_cpu_Cas01_t action = NULL;
397   surf_action_cpu_Cas01_t next_action = NULL;
398   xbt_swag_t running_actions = surf_cpu_model->states.running_action_set;
399   xbt_swag_foreach_safe(action, next_action, running_actions) {
400 #ifdef HAVE_TRACING
401     if (TRACE_is_enabled()) {
402       cpu_Cas01_t x =
403           lmm_constraint_id(lmm_get_cnst_from_var
404                             (cpu_maxmin_system,
405                              GENERIC_LMM_ACTION(action).variable, 0));
406
407       TRACE_surf_host_set_utilization(x->generic_resource.name,
408                                       ((surf_action_t)action)->category,
409                                       lmm_variable_getvalue(GENERIC_LMM_ACTION(action).
410                                        variable),
411                                       now - delta,
412                                       delta);
413       TRACE_last_timestamp_to_dump = now - delta;
414     }
415 #endif
416     double_update(&(GENERIC_ACTION(action).remains),
417                   lmm_variable_getvalue(GENERIC_LMM_ACTION(action).
418                                         variable) * delta);
419     if (GENERIC_LMM_ACTION(action).generic_action.max_duration !=
420         NO_MAX_DURATION)
421       double_update(&(GENERIC_ACTION(action).max_duration), delta);
422     if ((GENERIC_ACTION(action).remains <= 0) &&
423         (lmm_get_variable_weight(GENERIC_LMM_ACTION(action).variable) >
424          0)) {
425       GENERIC_ACTION(action).finish = surf_get_clock();
426       cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
427     } else if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION) &&
428                (GENERIC_ACTION(action).max_duration <= 0)) {
429       GENERIC_ACTION(action).finish = surf_get_clock();
430       cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
431     }
432   }
433
434   return;
435 }
436
437 static void cpu_update_resource_state(void *id,
438                                       tmgr_trace_event_t event_type,
439                                       double value, double date)
440 {
441   cpu_Cas01_t cpu = id;
442   lmm_variable_t var = NULL;
443   lmm_element_t elem = NULL;
444
445   if (event_type == cpu->power_event) {
446     cpu->power_scale = value;
447     lmm_update_constraint_bound(cpu_maxmin_system, cpu->constraint,
448                                 cpu->core * cpu->power_scale *
449                                 cpu->power_peak);
450 #ifdef HAVE_TRACING
451     TRACE_surf_host_set_power(date, cpu->generic_resource.name,
452                               cpu->core * cpu->power_scale *
453                               cpu->power_peak);
454 #endif
455     while ((var = lmm_get_var_from_cnst
456             (cpu_maxmin_system, cpu->constraint, &elem))) {
457       surf_action_cpu_Cas01_t action = lmm_variable_id(var);
458       lmm_update_variable_bound(cpu_maxmin_system,
459                                 GENERIC_LMM_ACTION(action).variable,
460                                 cpu->power_scale * cpu->power_peak);
461     }
462     if (tmgr_trace_event_free(event_type))
463       cpu->power_event = NULL;
464   } else if (event_type == cpu->state_event) {
465     if (value > 0)
466       cpu->state_current = SURF_RESOURCE_ON;
467     else {
468       lmm_constraint_t cnst = cpu->constraint;
469
470       cpu->state_current = SURF_RESOURCE_OFF;
471
472       while ((var = lmm_get_var_from_cnst(cpu_maxmin_system, cnst, &elem))) {
473         surf_action_t action = lmm_variable_id(var);
474
475         if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
476             surf_action_state_get(action) == SURF_ACTION_READY ||
477             surf_action_state_get(action) ==
478             SURF_ACTION_NOT_IN_THE_SYSTEM) {
479           action->finish = date;
480           cpu_action_state_set(action, SURF_ACTION_FAILED);
481         }
482       }
483     }
484     if (tmgr_trace_event_free(event_type))
485       cpu->state_event = NULL;
486   } else {
487     XBT_CRITICAL("Unknown event ! \n");
488     xbt_abort();
489   }
490
491   return;
492 }
493
494 static surf_action_t cpu_execute(void *cpu, double size)
495 {
496   surf_action_cpu_Cas01_t action = NULL;
497   cpu_Cas01_t CPU = cpu;
498
499   XBT_IN("(%s,%g)", surf_resource_name(CPU), size);
500   action =
501       surf_action_new(sizeof(s_surf_action_cpu_Cas01_t), size,
502                       surf_cpu_model,
503                       CPU->state_current != SURF_RESOURCE_ON);
504
505   GENERIC_LMM_ACTION(action).suspended = 0;     /* Should be useless because of the
506                                                    calloc but it seems to help valgrind... */
507
508   GENERIC_LMM_ACTION(action).variable =
509       lmm_variable_new(cpu_maxmin_system, action,
510                        GENERIC_ACTION(action).priority,
511                        CPU->power_scale * CPU->power_peak, 1);
512   if (cpu_update_mechanism == UM_LAZY) {
513     GENERIC_LMM_ACTION(action).index_heap = -1;
514     GENERIC_LMM_ACTION(action).last_update = surf_get_clock();
515   }
516   lmm_expand(cpu_maxmin_system, CPU->constraint,
517              GENERIC_LMM_ACTION(action).variable, 1.0);
518   XBT_OUT();
519   return (surf_action_t) action;
520 }
521
522 static surf_action_t cpu_action_sleep(void *cpu, double duration)
523 {
524   surf_action_cpu_Cas01_t action = NULL;
525
526   if (duration > 0)
527     duration = MAX(duration, MAXMIN_PRECISION);
528
529   XBT_IN("(%s,%g)", surf_resource_name(cpu), duration);
530   action = (surf_action_cpu_Cas01_t) cpu_execute(cpu, 1.0);
531   GENERIC_ACTION(action).max_duration = duration;
532   GENERIC_LMM_ACTION(action).suspended = 2;
533   if (duration == NO_MAX_DURATION) {
534     /* Move to the *end* of the corresponding action set. This convention
535        is used to speed up update_resource_state  */
536     xbt_swag_remove(action, ((surf_action_t) action)->state_set);
537     ((surf_action_t) action)->state_set =
538         cpu_running_action_set_that_does_not_need_being_checked;
539     xbt_swag_insert(action, ((surf_action_t) action)->state_set);
540   }
541
542   lmm_update_variable_weight(cpu_maxmin_system,
543                              GENERIC_LMM_ACTION(action).variable, 0.0);
544   if (cpu_update_mechanism == UM_LAZY) {     // remove action from the heap
545     heap_remove((surf_action_cpu_Cas01_t) action);
546     // this is necessary for a variable with weight 0 since such
547     // variables are ignored in lmm and we need to set its max_duration
548     // correctly at the next call to share_resources
549     xbt_swag_insert_at_head(action,cpu_modified_set);
550   }
551
552   XBT_OUT();
553   return (surf_action_t) action;
554 }
555
556 static void cpu_action_suspend(surf_action_t action)
557 {
558   XBT_IN("(%p)", action);
559   if (((surf_action_lmm_t) action)->suspended != 2) {
560     lmm_update_variable_weight(cpu_maxmin_system,
561                                ((surf_action_lmm_t) action)->variable,
562                                0.0);
563     ((surf_action_lmm_t) action)->suspended = 1;
564     if (cpu_update_mechanism == UM_LAZY)
565       heap_remove((surf_action_cpu_Cas01_t) action);
566   }
567   XBT_OUT();
568 }
569
570 static void cpu_action_resume(surf_action_t action)
571 {
572
573   XBT_IN("(%p)", action);
574   if (((surf_action_lmm_t) action)->suspended != 2) {
575     lmm_update_variable_weight(cpu_maxmin_system,
576                                ((surf_action_lmm_t) action)->variable,
577                                action->priority);
578     ((surf_action_lmm_t) action)->suspended = 0;
579     if (cpu_update_mechanism == UM_LAZY)
580       heap_remove((surf_action_cpu_Cas01_t) action);
581   }
582   XBT_OUT();
583 }
584
585 static int cpu_action_is_suspended(surf_action_t action)
586 {
587   return (((surf_action_lmm_t) action)->suspended == 1);
588 }
589
590 static void cpu_action_set_max_duration(surf_action_t action,
591                                         double duration)
592 {
593   XBT_IN("(%p,%g)", action, duration);
594
595   action->max_duration = duration;
596   if (cpu_update_mechanism == UM_LAZY)
597     heap_remove((surf_action_cpu_Cas01_t) action);
598   XBT_OUT();
599 }
600
601 static void cpu_action_set_priority(surf_action_t action, double priority)
602 {
603   XBT_IN("(%p,%g)", action, priority);
604   action->priority = priority;
605   lmm_update_variable_weight(cpu_maxmin_system,
606                              ((surf_action_lmm_t) action)->variable,
607                              priority);
608
609   if (cpu_update_mechanism == UM_LAZY)
610     heap_remove((surf_action_cpu_Cas01_t) action);
611   XBT_OUT();
612 }
613
614 #ifdef HAVE_TRACING
615 static void cpu_action_set_category(surf_action_t action,
616                                     const char *category)
617 {
618   XBT_IN("(%p,%s)", action, category);
619   action->category = xbt_strdup(category);
620   XBT_OUT();
621 }
622 #endif
623
624 static double cpu_action_get_remains(surf_action_t action)
625 {
626   XBT_IN("(%p)", action);
627   /* update remains before return it */
628   if (cpu_update_mechanism == UM_LAZY)
629     update_action_remaining_lazy(surf_get_clock());
630   XBT_OUT();
631   return action->remains;
632 }
633
634 static e_surf_resource_state_t cpu_get_state(void *cpu)
635 {
636   return ((cpu_Cas01_t) cpu)->state_current;
637 }
638
639 static double cpu_get_speed(void *cpu, double load)
640 {
641   return load * (((cpu_Cas01_t) cpu)->power_peak);
642 }
643
644 static double cpu_get_available_speed(void *cpu)
645 {
646   /* number between 0 and 1 */
647   return ((cpu_Cas01_t) cpu)->power_scale;
648 }
649
650 static void cpu_finalize(void)
651 {
652   lmm_system_free(cpu_maxmin_system);
653   cpu_maxmin_system = NULL;
654
655   surf_model_exit(surf_cpu_model);
656   surf_cpu_model = NULL;
657
658   xbt_swag_free(cpu_running_action_set_that_does_not_need_being_checked);
659   cpu_running_action_set_that_does_not_need_being_checked = NULL;
660   if (cpu_action_heap)
661     xbt_heap_free(cpu_action_heap);
662 }
663
664 static void surf_cpu_model_init_internal()
665 {
666   s_surf_action_t action;
667   s_surf_action_cpu_Cas01_t comp;
668
669   surf_cpu_model = surf_model_init();
670
671   cpu_running_action_set_that_does_not_need_being_checked =
672       xbt_swag_new(xbt_swag_offset(action, state_hookup));
673
674   surf_cpu_model->name = "cpu";
675
676   surf_cpu_model->action_unref = cpu_action_unref;
677   surf_cpu_model->action_cancel = cpu_action_cancel;
678   surf_cpu_model->action_state_set = cpu_action_state_set;
679
680   surf_cpu_model->model_private->resource_used = cpu_resource_used;
681
682   if (cpu_update_mechanism == UM_LAZY) {
683     surf_cpu_model->model_private->share_resources =
684         cpu_share_resources_lazy;
685     surf_cpu_model->model_private->update_actions_state =
686         cpu_update_actions_state_lazy;
687   } else if (cpu_update_mechanism == UM_FULL) {
688     surf_cpu_model->model_private->share_resources =
689         cpu_share_resources_full;
690     surf_cpu_model->model_private->update_actions_state =
691         cpu_update_actions_state_full;
692   } else
693     xbt_die("Invalid update mechanism!");
694
695   surf_cpu_model->model_private->update_resource_state =
696       cpu_update_resource_state;
697   surf_cpu_model->model_private->finalize = cpu_finalize;
698
699   surf_cpu_model->suspend = cpu_action_suspend;
700   surf_cpu_model->resume = cpu_action_resume;
701   surf_cpu_model->is_suspended = cpu_action_is_suspended;
702   surf_cpu_model->set_max_duration = cpu_action_set_max_duration;
703   surf_cpu_model->set_priority = cpu_action_set_priority;
704 #ifdef HAVE_TRACING
705   surf_cpu_model->set_category = cpu_action_set_category;
706 #endif
707   surf_cpu_model->get_remains = cpu_action_get_remains;
708
709   surf_cpu_model->extension.cpu.execute = cpu_execute;
710   surf_cpu_model->extension.cpu.sleep = cpu_action_sleep;
711
712   surf_cpu_model->extension.cpu.get_state = cpu_get_state;
713   surf_cpu_model->extension.cpu.get_speed = cpu_get_speed;
714   surf_cpu_model->extension.cpu.get_available_speed =
715       cpu_get_available_speed;
716   surf_cpu_model->extension.cpu.create_resource = cpu_create_resource;
717   surf_cpu_model->extension.cpu.add_traces = cpu_add_traces_cpu;
718
719   if (!cpu_maxmin_system) {
720     cpu_maxmin_system = lmm_system_new(cpu_selective_update);
721   }
722   if (cpu_update_mechanism == UM_LAZY) {
723     cpu_action_heap = xbt_heap_new(8, NULL);
724     xbt_heap_set_update_callback(cpu_action_heap,
725         net_action_update_index_heap);
726     cpu_modified_set =
727         xbt_swag_new(xbt_swag_offset(comp, generic_lmm_action.action_list_hookup));
728     cpu_maxmin_system->keep_track = cpu_modified_set;
729   }
730 }
731
732 /*********************************************************************/
733 /* Basic sharing model for CPU: that is where all this started... ;) */
734 /*********************************************************************/
735 /* @InProceedings{casanova01simgrid, */
736 /*   author =       "H. Casanova", */
737 /*   booktitle =    "Proceedings of the IEEE Symposium on Cluster Computing */
738 /*                  and the Grid (CCGrid'01)", */
739 /*   publisher =    "IEEE Computer Society", */
740 /*   title =        "Simgrid: {A} Toolkit for the Simulation of Application */
741 /*                  Scheduling", */
742 /*   year =         "2001", */
743 /*   month =        may, */
744 /*   note =         "Available at */
745 /*                  \url{http://grail.sdsc.edu/papers/simgrid_ccgrid01.ps.gz}." */
746 /* } */
747
748 void surf_cpu_model_init_Cas01()
749 {
750   char *optim = xbt_cfg_get_string(_surf_cfg_set, "cpu/optim");
751   int select =
752       xbt_cfg_get_int(_surf_cfg_set, "cpu/maxmin_selective_update");
753
754   if (!strcmp(optim, "Full")) {
755     cpu_update_mechanism = UM_FULL;
756     cpu_selective_update = select;
757   } else if (!strcmp(optim, "Lazy")) {
758     cpu_update_mechanism = UM_LAZY;
759     cpu_selective_update = 1;
760     xbt_assert((select == 1)
761                ||
762                (xbt_cfg_is_default_value
763                 (_surf_cfg_set, "cpu/maxmin_selective_update")),
764                "Disabling selective update while using the lazy update mechanism is dumb!");
765   } else if (!strcmp(optim, "TI")) {
766     surf_cpu_model_init_ti();
767     return;
768   } else {
769     xbt_die("Unsupported optimization (%s) for this model", optim);
770   }
771
772   if (surf_cpu_model)
773     return;
774   surf_cpu_model_init_internal();
775   cpu_define_callbacks();
776   xbt_dynar_push(model_list, &surf_cpu_model);
777 }