Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
b7012df4444cd9740e03250f86dc0fc5137c37ca
[simgrid.git] / src / surf / cpu.c
1 /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. 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
9 typedef s_surf_action_lmm_t s_surf_action_cpu_Cas01_t,
10     *surf_action_cpu_Cas01_t;
11
12 typedef struct cpu_Cas01 {
13   s_surf_resource_t generic_resource;
14   double power_peak;
15   double power_scale;
16   int core;
17   tmgr_trace_event_t power_event;
18   e_surf_resource_state_t state_current;
19   tmgr_trace_event_t state_event;
20   lmm_constraint_t constraint;
21 } s_cpu_Cas01_t, *cpu_Cas01_t;
22
23 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu, surf,
24                                 "Logging specific to the SURF CPU module");
25
26
27
28 surf_model_t surf_cpu_model = NULL;
29 lmm_system_t cpu_maxmin_system = NULL;
30
31
32 static xbt_swag_t cpu_running_action_set_that_does_not_need_being_checked =
33     NULL;
34
35 static void* cpu_create_resource(const char *name, double power_peak,
36                            double power_scale,
37                            tmgr_trace_t power_trace,
38                            int core,
39                            e_surf_resource_state_t state_initial,
40                            tmgr_trace_t state_trace,
41                            xbt_dict_t cpu_properties)
42 {
43
44   cpu_Cas01_t cpu = NULL;
45   xbt_assert(!surf_cpu_resource_by_name(name),
46               "Host '%s' declared several times in the platform file",
47               name);
48   cpu = (cpu_Cas01_t) surf_resource_new(sizeof(s_cpu_Cas01_t),
49           surf_cpu_model, name,cpu_properties);
50   cpu->power_peak = power_peak;
51   xbt_assert(cpu->power_peak > 0, "Power has to be >0");
52   cpu->power_scale = power_scale;
53   cpu->core = core;
54   xbt_assert(core>0,"Invalid number of cores %d",core);
55   if (power_trace)
56     cpu->power_event =
57         tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
58
59   cpu->state_current = state_initial;
60   if (state_trace)
61     cpu->state_event =
62         tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
63
64   cpu->constraint =
65       lmm_constraint_new(cpu_maxmin_system, cpu,
66                          cpu->core * cpu->power_scale * cpu->power_peak);
67
68   xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, cpu);
69
70   return cpu;
71 }
72
73
74 static void parse_cpu_init(sg_platf_host_cbarg_t host)
75 {
76   if(strcmp(host->V_host_coord,"")) xbt_die("Coordinates not implemented yet!");
77
78   cpu_create_resource(host->V_host_id,
79                   host->V_host_power_peak,
80                   host->V_host_power_scale,
81                   host->V_host_power_trace,
82                   host->V_host_core,
83                   host->V_host_state_initial,
84                   host->V_host_state_trace,
85                   host->properties);
86 }
87
88 static void add_traces_cpu(void)
89 {
90   xbt_dict_cursor_t cursor = NULL;
91   char *trace_name, *elm;
92
93   static int called = 0;
94
95   if (called)
96     return;
97   called = 1;
98
99
100   /* connect all traces relative to hosts */
101   xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
102     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
103     cpu_Cas01_t host = surf_cpu_resource_by_name(elm);
104
105     xbt_assert(host, "Host %s undefined", elm);
106     xbt_assert(trace, "Trace %s undefined", trace_name);
107
108     host->state_event =
109         tmgr_history_add_trace(history, trace, 0.0, 0, host);
110   }
111
112   xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
113     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
114     cpu_Cas01_t host = surf_cpu_resource_by_name(elm);
115
116     xbt_assert(host, "Host %s undefined", elm);
117     xbt_assert(trace, "Trace %s undefined", trace_name);
118
119     host->power_event =
120         tmgr_history_add_trace(history, trace, 0.0, 0, host);
121   }
122 }
123
124 static void cpu_define_callbacks(void)
125 {
126   sg_platf_host_add_cb(parse_cpu_init);
127   surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_traces_cpu);
128 }
129
130 static int cpu_resource_used(void *resource_id)
131 {
132   return lmm_constraint_used(cpu_maxmin_system,
133                              ((cpu_Cas01_t) resource_id)->constraint);
134 }
135
136 static int cpu_action_unref(surf_action_t action)
137 {
138   action->refcount--;
139   if (!action->refcount) {
140     xbt_swag_remove(action, action->state_set);
141     if (((surf_action_cpu_Cas01_t) action)->variable)
142       lmm_variable_free(cpu_maxmin_system,
143                         ((surf_action_cpu_Cas01_t) action)->variable);
144 #ifdef HAVE_TRACING
145     if (action->category)
146       xbt_free(action->category);
147 #endif
148     surf_action_free(&action);
149     return 1;
150   }
151   return 0;
152 }
153
154 static void cpu_action_cancel(surf_action_t action)
155 {
156   surf_action_state_set(action, SURF_ACTION_FAILED);
157   return;
158 }
159
160 static void cpu_action_state_set(surf_action_t action,
161                                  e_surf_action_state_t state)
162 {
163 /*   if((state==SURF_ACTION_DONE) || (state==SURF_ACTION_FAILED)) */
164 /*     if(((surf_action_cpu_Cas01_t)action)->variable) { */
165 /*       lmm_variable_disable(cpu_maxmin_system, ((surf_action_cpu_Cas01_t)action)->variable); */
166 /*       ((surf_action_cpu_Cas01_t)action)->variable = NULL; */
167 /*     } */
168
169   surf_action_state_set(action, state);
170   return;
171 }
172
173 static double cpu_share_resources(double now)
174 {
175   s_surf_action_cpu_Cas01_t action;
176   return generic_maxmin_share_resources(surf_cpu_model->
177                                         states.running_action_set,
178                                         xbt_swag_offset(action, variable),
179                                         cpu_maxmin_system, lmm_solve);
180 }
181
182 static void cpu_update_actions_state(double now, double delta)
183 {
184   surf_action_cpu_Cas01_t action = NULL;
185   surf_action_cpu_Cas01_t next_action = NULL;
186   xbt_swag_t running_actions = surf_cpu_model->states.running_action_set;
187
188   xbt_swag_foreach_safe(action, next_action, running_actions) {
189 #ifdef HAVE_TRACING
190     if (TRACE_is_enabled()) {
191       cpu_Cas01_t x =
192         lmm_constraint_id(lmm_get_cnst_from_var
193                           (cpu_maxmin_system, action->variable, 0));
194
195       TRACE_surf_host_set_utilization(x->generic_resource.name,
196                                       action->generic_action.data,
197                                       (surf_action_t) action,
198                                       lmm_variable_getvalue
199                                       (action->variable), now - delta,
200                                       delta);
201       TRACE_last_timestamp_to_dump = now-delta;
202     }
203 #endif
204     double_update(&(action->generic_action.remains),
205                   lmm_variable_getvalue(action->variable) * delta);
206     if (action->generic_action.max_duration != NO_MAX_DURATION)
207       double_update(&(action->generic_action.max_duration), delta);
208     if ((action->generic_action.remains <= 0) &&
209         (lmm_get_variable_weight(action->variable) > 0)) {
210       action->generic_action.finish = surf_get_clock();
211       cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
212     } else if ((action->generic_action.max_duration != NO_MAX_DURATION) &&
213                (action->generic_action.max_duration <= 0)) {
214       action->generic_action.finish = surf_get_clock();
215       cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
216     }
217   }
218
219   return;
220 }
221
222 static void cpu_update_resource_state(void *id,
223                                       tmgr_trace_event_t event_type,
224                                       double value, double date)
225 {
226   cpu_Cas01_t cpu = id;
227   lmm_variable_t var = NULL;
228   lmm_element_t elem = NULL;
229
230   if (event_type == cpu->power_event) {
231     cpu->power_scale = value;
232     lmm_update_constraint_bound(cpu_maxmin_system, cpu->constraint,
233                                 cpu->core * cpu->power_scale * cpu->power_peak);
234 #ifdef HAVE_TRACING
235     TRACE_surf_host_set_power(date, cpu->generic_resource.name,
236                               cpu->core * cpu->power_scale * cpu->power_peak);
237 #endif
238     while ((var = lmm_get_var_from_cnst
239             (cpu_maxmin_system, cpu->constraint, &elem))) {
240         surf_action_cpu_Cas01_t action = lmm_variable_id(var);
241         lmm_update_variable_bound(cpu_maxmin_system, action->variable,
242                                   cpu->power_scale * cpu->power_peak);
243     }
244     if (tmgr_trace_event_free(event_type))
245       cpu->power_event = NULL;
246   } else if (event_type == cpu->state_event) {
247     if (value > 0)
248       cpu->state_current = SURF_RESOURCE_ON;
249     else {
250       lmm_constraint_t cnst = cpu->constraint;
251       lmm_variable_t var = NULL;
252       lmm_element_t elem = NULL;
253
254       cpu->state_current = SURF_RESOURCE_OFF;
255
256       while ((var = lmm_get_var_from_cnst(cpu_maxmin_system, cnst, &elem))) {
257         surf_action_t action = lmm_variable_id(var);
258
259         if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
260             surf_action_state_get(action) == SURF_ACTION_READY ||
261             surf_action_state_get(action) ==
262             SURF_ACTION_NOT_IN_THE_SYSTEM) {
263           action->finish = date;
264           cpu_action_state_set(action, SURF_ACTION_FAILED);
265         }
266       }
267     }
268     if (tmgr_trace_event_free(event_type))
269       cpu->state_event = NULL;
270   } else {
271     XBT_CRITICAL("Unknown event ! \n");
272     xbt_abort();
273   }
274
275   return;
276 }
277
278 static surf_action_t cpu_execute(void *cpu, double size)
279 {
280   surf_action_cpu_Cas01_t action = NULL;
281   cpu_Cas01_t CPU = cpu;
282
283   XBT_IN("(%s,%g)", surf_resource_name(CPU), size);
284   action =
285       surf_action_new(sizeof(s_surf_action_cpu_Cas01_t), size,
286                       surf_cpu_model,
287                       CPU->state_current != SURF_RESOURCE_ON);
288
289   action->suspended = 0;        /* Should be useless because of the
290                                    calloc but it seems to help valgrind... */
291
292   action->variable = lmm_variable_new(cpu_maxmin_system, action,
293                                       action->generic_action.priority,
294                                       CPU->power_scale * CPU->power_peak, 1);
295   lmm_expand(cpu_maxmin_system, CPU->constraint, action->variable, 1.0);
296   XBT_OUT();
297   return (surf_action_t) action;
298 }
299
300 static surf_action_t cpu_action_sleep(void *cpu, double duration)
301 {
302   surf_action_cpu_Cas01_t action = NULL;
303
304   if (duration > 0)
305     duration = MAX(duration, MAXMIN_PRECISION);
306
307   XBT_IN("(%s,%g)", surf_resource_name(cpu), duration);
308   action = (surf_action_cpu_Cas01_t) cpu_execute(cpu, 1.0);
309   action->generic_action.max_duration = duration;
310   action->suspended = 2;
311   if (duration == NO_MAX_DURATION) {
312     /* Move to the *end* of the corresponding action set. This convention
313        is used to speed up update_resource_state  */
314     xbt_swag_remove(action, ((surf_action_t) action)->state_set);
315     ((surf_action_t) action)->state_set =
316         cpu_running_action_set_that_does_not_need_being_checked;
317     xbt_swag_insert(action, ((surf_action_t) action)->state_set);
318   }
319
320   lmm_update_variable_weight(cpu_maxmin_system, action->variable, 0.0);
321   XBT_OUT();
322   return (surf_action_t) action;
323 }
324
325 static void cpu_action_suspend(surf_action_t action)
326 {
327   XBT_IN("(%p)", action);
328   if (((surf_action_cpu_Cas01_t) action)->suspended != 2) {
329     lmm_update_variable_weight(cpu_maxmin_system,
330                                ((surf_action_cpu_Cas01_t)
331                                 action)->variable, 0.0);
332     ((surf_action_cpu_Cas01_t) action)->suspended = 1;
333   }
334   XBT_OUT();
335 }
336
337 static void cpu_action_resume(surf_action_t action)
338 {
339   XBT_IN("(%p)", action);
340   if (((surf_action_cpu_Cas01_t) action)->suspended != 2) {
341     lmm_update_variable_weight(cpu_maxmin_system,
342                                ((surf_action_cpu_Cas01_t)
343                                 action)->variable, action->priority);
344     ((surf_action_cpu_Cas01_t) action)->suspended = 0;
345   }
346   XBT_OUT();
347 }
348
349 static int cpu_action_is_suspended(surf_action_t action)
350 {
351   return (((surf_action_cpu_Cas01_t) action)->suspended == 1);
352 }
353
354 static void cpu_action_set_max_duration(surf_action_t action,
355                                         double duration)
356 {
357   XBT_IN("(%p,%g)", action, duration);
358   action->max_duration = duration;
359   XBT_OUT();
360 }
361
362 static void cpu_action_set_priority(surf_action_t action, double priority)
363 {
364   XBT_IN("(%p,%g)", action, priority);
365   action->priority = priority;
366   lmm_update_variable_weight(cpu_maxmin_system,
367                              ((surf_action_cpu_Cas01_t) action)->variable,
368                              priority);
369
370   XBT_OUT();
371 }
372
373 #ifdef HAVE_TRACING
374 static void cpu_action_set_category(surf_action_t action, const char *category)
375 {
376   XBT_IN("(%p,%s)", action, category);
377   action->category = xbt_strdup (category);
378   XBT_OUT();
379 }
380 #endif
381
382 static double cpu_action_get_remains(surf_action_t action)
383 {
384   XBT_IN("(%p)", action);
385   return action->remains;
386   XBT_OUT();
387 }
388
389 static e_surf_resource_state_t cpu_get_state(void *cpu)
390 {
391   return ((cpu_Cas01_t) cpu)->state_current;
392 }
393
394 static double cpu_get_speed(void *cpu, double load)
395 {
396   return load * (((cpu_Cas01_t) cpu)->power_peak);
397 }
398
399 static double cpu_get_available_speed(void *cpu)
400 {
401   /* number between 0 and 1 */
402   return ((cpu_Cas01_t) cpu)->power_scale;
403 }
404
405
406 static void cpu_finalize(void)
407 {
408   lmm_system_free(cpu_maxmin_system);
409   cpu_maxmin_system = NULL;
410
411   surf_model_exit(surf_cpu_model);
412   surf_cpu_model = NULL;
413
414   xbt_swag_free(cpu_running_action_set_that_does_not_need_being_checked);
415   cpu_running_action_set_that_does_not_need_being_checked = NULL;
416 }
417
418 static void surf_cpu_model_init_internal(void)
419 {
420   s_surf_action_t action;
421
422   surf_cpu_model = surf_model_init();
423
424   cpu_running_action_set_that_does_not_need_being_checked =
425       xbt_swag_new(xbt_swag_offset(action, state_hookup));
426
427   surf_cpu_model->name = "CPU";
428
429   surf_cpu_model->action_unref = cpu_action_unref;
430   surf_cpu_model->action_cancel = cpu_action_cancel;
431   surf_cpu_model->action_state_set = cpu_action_state_set;
432
433   surf_cpu_model->model_private->resource_used = cpu_resource_used;
434   surf_cpu_model->model_private->share_resources = cpu_share_resources;
435   surf_cpu_model->model_private->update_actions_state =
436       cpu_update_actions_state;
437   surf_cpu_model->model_private->update_resource_state =
438       cpu_update_resource_state;
439   surf_cpu_model->model_private->finalize = cpu_finalize;
440
441   surf_cpu_model->suspend = cpu_action_suspend;
442   surf_cpu_model->resume = cpu_action_resume;
443   surf_cpu_model->is_suspended = cpu_action_is_suspended;
444   surf_cpu_model->set_max_duration = cpu_action_set_max_duration;
445   surf_cpu_model->set_priority = cpu_action_set_priority;
446 #ifdef HAVE_TRACING
447   surf_cpu_model->set_category = cpu_action_set_category;
448 #endif
449   surf_cpu_model->get_remains = cpu_action_get_remains;
450
451   surf_cpu_model->extension.cpu.execute = cpu_execute;
452   surf_cpu_model->extension.cpu.sleep = cpu_action_sleep;
453
454   surf_cpu_model->extension.cpu.get_state = cpu_get_state;
455   surf_cpu_model->extension.cpu.get_speed = cpu_get_speed;
456   surf_cpu_model->extension.cpu.get_available_speed =
457       cpu_get_available_speed;
458   surf_cpu_model->extension.cpu.create_resource = cpu_create_resource;
459   surf_cpu_model->extension.cpu.add_traces = add_traces_cpu;
460
461   if (!cpu_maxmin_system)
462     cpu_maxmin_system = lmm_system_new();
463 }
464
465 /*********************************************************************/
466 /* Basic sharing model for CPU: that is where all this started... ;) */
467 /*********************************************************************/
468 /* @InProceedings{casanova01simgrid, */
469 /*   author =       "H. Casanova", */
470 /*   booktitle =    "Proceedings of the IEEE Symposium on Cluster Computing */
471 /*                  and the Grid (CCGrid'01)", */
472 /*   publisher =    "IEEE Computer Society", */
473 /*   title =        "Simgrid: {A} Toolkit for the Simulation of Application */
474 /*                  Scheduling", */
475 /*   year =         "2001", */
476 /*   month =        may, */
477 /*   note =         "Available at */
478 /*                  \url{http://grail.sdsc.edu/papers/simgrid_ccgrid01.ps.gz}." */
479 /* } */
480 void surf_cpu_model_init_Cas01()
481 {
482   if (surf_cpu_model)
483     return;
484   surf_cpu_model_init_internal();
485   cpu_define_callbacks();
486   xbt_dynar_push(model_list, &surf_cpu_model);
487 }