Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'hypervisor' into surf++
[simgrid.git] / src / surf / workstation.c
1 /* Copyright (c) 2004-2013. 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 "xbt/ex.h"
8 #include "xbt/dict.h"
9 #include "portable.h"
10 #include "surf_private.h"
11 #include "storage_private.h"
12 #include "surf/surf_resource.h"
13 #include "simgrid/sg_config.h"
14 #include "workstation_private.h"
15 #include "vm_workstation_private.h"
16 #include "cpu_cas01_private.h"
17 #include "maxmin_private.h"
18
19 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_workstation, surf,
20                                 "Logging specific to the SURF workstation module");
21
22 surf_model_t surf_workstation_model = NULL;
23
24
25 static void workstation_new(sg_platf_host_cbarg_t host)
26 {
27   const char *name = host->id;
28
29   /* NOTE: The properties object is NULL, because the current code uses that of
30    * that of a cpu resource. */
31   workstation_CLM03_t ws = (workstation_CLM03_t) surf_resource_new(sizeof(s_workstation_CLM03_t), surf_workstation_model, name, NULL, NULL);
32
33   ws->storage = xbt_lib_get_or_null(storage_lib, name, ROUTING_STORAGE_HOST_LEVEL);
34   ws->net_elm = xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL);
35
36   XBT_DEBUG("Create ws %s with %ld mounted disks", name, xbt_dynar_length(ws->storage));
37   xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, ws);
38 }
39
40 static void ws_parallel_action_cancel(surf_action_t action)
41 {
42   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
43 }
44
45 static int ws_parallel_action_free(surf_action_t action)
46 {
47   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
48   return -1;
49 }
50
51 int ws_action_unref(surf_action_t action)
52 {
53   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
54     return surf_network_model->action_unref(action);
55   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
56     return action->model_obj->action_unref(action);
57       // previously was: Adrien/Arnaud 6 feb
58           // surf_cpu_model->action_unref(action);
59   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
60     return ws_parallel_action_free(action);
61   else
62     DIE_IMPOSSIBLE;
63   return 0;
64 }
65
66 void ws_action_cancel(surf_action_t action)
67 {
68   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
69     surf_network_model->action_cancel(action);
70   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
71     action->model_obj->action_cancel(action);
72   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
73     ws_parallel_action_cancel(action);
74   else
75     DIE_IMPOSSIBLE;
76   return;
77 }
78
79 static void ws_action_state_set(surf_action_t action,
80                                 e_surf_action_state_t state)
81 {
82   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
83     surf_network_model->action_state_set(action, state);
84   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
85     action->model_obj->action_state_set(action, state);
86   else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
87     surf_action_state_set(action, state);
88   else
89     DIE_IMPOSSIBLE;
90   return;
91 }
92
93
94 /* -- The callback functions at model_private -- */
95 /* These callbacks are also used for the vm workstation model. */
96 int ws_resource_used(void *resource_id)
97 {
98   /* This model does not implement parallel tasks */
99   THROW_IMPOSSIBLE;
100   return -1;
101 }
102
103
104 /* TODO: iterating active constraint_set may be faster? */
105 #if 0
106 static void deactivate_dummy_cpu_action(void)
107 {
108   lmm_system_t sys = surf_cpu_model_vm->model_private->maxmin_system;
109
110   lmm_constraint_t cnst;
111   xbt_swag_foreach(cnst, &sys->active_constraint_set) {
112     /* get vcpu resource */
113     surf_resource_t cpu = lmm_constraint_id(cnst);
114     xbt_assert(cpu->model == surf_cpu_model_vm);
115
116     /* get vm_ws resource */
117     workstation_CLM03_t ws = xbt_lib_get_or_null(host_lib, cpu->name, SURF_WKS_LEVEL);
118
119     /* make sure we can cast */
120     xbt_assert(ws->generic_resouce.model == surf_vm_workstation_model);
121     workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
122
123     /* make it active in the PM layer */
124     surf_action_set_priority(vm_ws->cpu_action, 1);
125   }
126 }
127 #endif
128
129
130 /* TODO: Delete this unused code if everything looks good. */
131 #if 0
132 static int constraint_is_active(cpu_Cas01_t cpu_cas01)
133 {
134   surf_model_t cpu_model = cpu_cas01->generic_resource.model;
135   lmm_system_t sys = cpu_model->model_private->maxmin_system;
136   int found = 0;
137   lmm_constraint_t cnst_tmp;
138
139   xbt_swag_foreach(cnst_tmp, &sys->active_constraint_set) {
140     if (cnst_tmp == cpu_cas01->constraint) {
141       found = 1;
142       break;
143     }
144   }
145
146   return found;
147 }
148 #endif
149
150
151 /* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
152  * constraint (capacity) of the VM in the PM layer. If the VM does not have any
153  * active task, the dummy CPU action must be deactivated, so that the VM does
154  * not get any CPU share in the PM layer. */
155 static void adjust_weight_of_dummy_cpu_actions(void)
156 {
157   /* iterate for all hosts including virtual machines */
158   xbt_lib_cursor_t cursor;
159   char *key;
160   void **ind_host;
161
162   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
163     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
164     cpu_Cas01_t cpu_cas01 = ind_host[SURF_CPU_LEVEL];
165
166     if (!ws_clm03)
167       continue;
168     /* skip if it is not a virtual machine */
169     if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
170       continue;
171     xbt_assert(cpu_cas01, "cpu-less workstation");
172
173     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
174     workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
175
176     lmm_system_t sys = surf_cpu_model_vm->model_private->maxmin_system;
177     int is_active = lmm_constraint_used(sys, cpu_cas01->constraint);
178     // int is_active_old = constraint_is_active(cpu_cas01);
179
180     // {
181     //   xbt_assert(is_active == is_active_old, "%d %d", is_active, is_active_old);
182     // }
183
184     if (is_active) {
185       /* some tasks exist on this VM */
186       XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
187
188       /* FIXME: we shoud use lmm_update_variable_weight() ? */
189       /* FIXME: If we assgign 1.05 and 0.05, the system makes apparently wrong values. */
190       surf_action_set_priority(ws_vm2013->cpu_action, 1);
191
192     } else {
193       /* no task exits on this VM */
194       XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
195
196       surf_action_set_priority(ws_vm2013->cpu_action, 0);
197     }
198   }
199 }
200
201
202 double ws_share_resources(surf_model_t workstation_model, double now)
203 {
204   if (workstation_model->type == SURF_MODEL_TYPE_WORKSTATION)
205     adjust_weight_of_dummy_cpu_actions();
206
207   /* Invoke the share_resources() callback of the physical cpu model object and
208    * the network model objects. */
209   surf_model_t cpu_model = workstation_model->extension.workstation.cpu_model;
210   surf_model_t net_model = surf_network_model;
211
212   double min_by_cpu = cpu_model->model_private->share_resources(cpu_model, now);
213   double min_by_net = net_model->model_private->share_resources(net_model, now);
214
215   XBT_DEBUG("model %p, %s min_by_cpu %f, %s min_by_net %f",
216       workstation_model, cpu_model->name, min_by_cpu, net_model->name, min_by_net);
217
218   if (min_by_cpu >= 0.0 && min_by_net >= 0.0)
219     return min(min_by_cpu, min_by_net);
220   else if (min_by_cpu >= 0.0)
221     return min_by_cpu;
222   else if (min_by_net >= 0.0)
223     return min_by_net;
224   else
225     return min_by_cpu;  /* probably min_by_cpu == min_by_net == -1 */
226 }
227
228 void ws_update_actions_state(surf_model_t workstation_model, double now, double delta)
229 {
230   return;
231 }
232
233 void ws_update_resource_state(void *id, tmgr_trace_event_t event_type, double value, double date)
234 {
235   /* This model does not implement parallel tasks */
236   THROW_IMPOSSIBLE;
237 }
238
239 void ws_finalize(surf_model_t workstation_model)
240 {
241   surf_model_exit(workstation_model);
242   workstation_model = NULL;
243 }
244
245
246
247 surf_action_t ws_execute(void *workstation, double size)
248 {
249   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
250   return cpu->model->extension.cpu.execute(workstation, size);
251 }
252
253 surf_action_t ws_action_sleep(void *workstation, double duration)
254 {
255   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
256   return cpu->model->extension.cpu.sleep(workstation, duration);
257 }
258
259 void ws_action_suspend(surf_action_t action)
260 {
261   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
262     surf_network_model->suspend(action);
263   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
264     action->model_obj->suspend(action);
265   else
266     DIE_IMPOSSIBLE;
267 }
268
269 void ws_action_resume(surf_action_t action)
270 {
271   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
272     surf_network_model->resume(action);
273   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
274     action->model_obj->resume(action);
275   else
276     DIE_IMPOSSIBLE;
277 }
278
279 static int ws_action_is_suspended(surf_action_t action)
280 {
281   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
282     return surf_network_model->is_suspended(action);
283   if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
284     return action->model_obj->is_suspended(action);
285   DIE_IMPOSSIBLE;
286   return -1;
287 }
288
289 static void ws_action_set_max_duration(surf_action_t action,
290                                        double duration)
291 {
292   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
293     surf_network_model->set_max_duration(action, duration);
294   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
295     action->model_obj->set_max_duration(action, duration);
296   else
297     DIE_IMPOSSIBLE;
298 }
299
300 void ws_action_set_priority(surf_action_t action, double priority)
301 {
302   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
303     surf_network_model->set_priority(action, priority);
304   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
305     action->model_obj->set_priority(action, priority);
306   else
307     DIE_IMPOSSIBLE;
308 }
309
310 void ws_action_set_bound(surf_action_t action, double bound)
311 {
312   /* FIXME: only for CPU model object? */
313   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
314     surf_network_model->set_bound(action, bound);
315   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
316     action->model_obj->set_bound(action, bound);
317   else
318     DIE_IMPOSSIBLE;
319 }
320
321 void ws_action_set_affinity(surf_action_t action, void *workstation, unsigned long mask)
322 {
323   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
324     DIE_IMPOSSIBLE;
325   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
326     action->model_obj->set_affinity(action, workstation, mask);
327   else
328     DIE_IMPOSSIBLE;
329 }
330
331 #ifdef HAVE_TRACING
332 static void ws_action_set_category(surf_action_t action, const char *category)
333 {
334   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
335     surf_network_model->set_category(action, category);
336   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
337     action->model_obj->set_category(action, category);
338   else
339     DIE_IMPOSSIBLE;
340 }
341 #endif
342
343 #ifdef HAVE_LATENCY_BOUND_TRACKING
344 static int ws_get_latency_limited(surf_action_t action)
345 {
346   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
347     return surf_network_model->get_latency_limited(action);
348   else
349     return 0;
350 }
351 #endif
352
353 double ws_action_get_remains(surf_action_t action)
354 {
355   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
356     return surf_network_model->get_remains(action);
357   if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
358     return action->model_obj->get_remains(action);
359   DIE_IMPOSSIBLE;
360   return -1.0;
361 }
362
363 static surf_action_t ws_communicate(void *workstation_src,
364                                     void *workstation_dst, double size,
365                                     double rate)
366 {
367   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
368   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
369   return surf_network_model->extension.network.
370       communicate(src->net_elm,
371                   dst->net_elm, size, rate);
372 }
373
374 e_surf_resource_state_t ws_get_state(void *workstation)
375 {
376   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
377   return cpu->model->extension.cpu.get_state(workstation);
378 }
379
380 static void ws_set_state(void *workstation, e_surf_resource_state_t state)
381 {
382   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
383   cpu->model->extension.cpu.set_state(workstation, state);
384 }
385
386 double ws_get_speed(void *workstation, double load)
387 {
388   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
389   return cpu->model->extension.cpu.get_speed(workstation, load);
390 }
391
392 static int ws_get_core(void *workstation)
393 {
394   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
395   return cpu->model->extension.cpu.get_core(workstation);
396 }
397 static double ws_get_available_speed(void *workstation)
398 {
399   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
400   return cpu->model->extension.cpu.get_available_speed(workstation);
401 }
402
403 static double ws_get_current_power_peak(void *workstation)
404 {
405   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
406   return cpu->model->extension.cpu.
407       get_current_power_peak(workstation);
408 }
409
410 static double ws_get_power_peak_at(void *workstation, int pstate_index)
411 {
412   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
413   return cpu->model->extension.cpu.
414       get_power_peak_at(workstation, pstate_index);
415 }
416
417 static int ws_get_nb_pstates(void *workstation)
418 {
419   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
420   return cpu->model->extension.cpu.
421       get_nb_pstates(workstation);
422 }
423
424 static void ws_set_power_peak_at(void *workstation, int pstate_index)
425 {
426   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
427   cpu->model->extension.cpu.
428       set_power_peak_at(workstation, pstate_index);
429 }
430
431 static double ws_get_consumed_energy(void *workstation)
432 {
433   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
434   return cpu->model->extension.cpu.
435       get_consumed_energy(workstation);
436 }
437
438
439 static surf_action_t ws_execute_parallel_task(int workstation_nb,
440                                               void **workstation_list,
441                                               double *computation_amount,
442                                               double *communication_amount,
443                                               double rate)
444 {
445 #define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0)
446   if ((workstation_nb == 1)
447       && (cost_or_zero(communication_amount, 0) == 0.0))
448     return ws_execute(workstation_list[0], computation_amount[0]);
449   else if ((workstation_nb == 1)
450            && (cost_or_zero(computation_amount, 0) == 0.0))
451     return ws_communicate(workstation_list[0], workstation_list[0],communication_amount[0], rate);
452   else if ((workstation_nb == 2)
453              && (cost_or_zero(computation_amount, 0) == 0.0)
454              && (cost_or_zero(computation_amount, 1) == 0.0)) {
455     int i,nb = 0;
456     double value = 0.0;
457
458     for (i = 0; i < workstation_nb * workstation_nb; i++) {
459       if (cost_or_zero(communication_amount, i) > 0.0) {
460         nb++;
461         value = cost_or_zero(communication_amount, i);
462       }
463     }
464     if (nb == 1)
465       return ws_communicate(workstation_list[0], workstation_list[1],value, rate);
466   }
467 #undef cost_or_zero
468
469   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
470   return NULL;
471 }
472
473
474 /* returns an array of network_link_CM02_t */
475 static xbt_dynar_t ws_get_route(void *workstation_src, void *workstation_dst)
476 {
477   XBT_DEBUG("ws_get_route");
478   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
479   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
480   return surf_network_model->extension.
481       network.get_route(src->net_elm,
482                   dst->net_elm);
483 }
484
485 static double ws_get_link_bandwidth(const void *link)
486 {
487   return surf_network_model->extension.network.get_link_bandwidth(link);
488 }
489
490 static double ws_get_link_latency(const void *link)
491 {
492   return surf_network_model->extension.network.get_link_latency(link);
493 }
494
495 static int ws_link_shared(const void *link)
496 {
497   return surf_network_model->extension.network.link_shared(link);
498 }
499
500 static xbt_dict_t ws_get_properties(const void *ws)
501 {
502   return surf_resource_properties(surf_cpu_resource_priv(ws));
503 }
504
505 static storage_t find_storage_on_mount_list(void *workstation,const char* mount)
506 {
507   storage_t st = NULL;
508   s_mount_t mnt;
509   unsigned int cursor;
510   workstation_CLM03_t ws = (workstation_CLM03_t) surf_workstation_resource_priv(workstation);
511   xbt_dynar_t storage_list = ws->storage;
512
513   XBT_DEBUG("Search for storage name '%s' on '%s'",mount,ws->generic_resource.name);
514   xbt_dynar_foreach(storage_list,cursor,mnt)
515   {
516     XBT_DEBUG("See '%s'",mnt.name);
517     if(!strcmp(mount,mnt.name)){
518       st = mnt.storage;
519       break;
520     }
521   }
522   if(!st) xbt_die("Can't find mount '%s' for '%s'",mount,ws->generic_resource.name);
523   return st;
524 }
525
526 static xbt_dict_t ws_get_storage_list(void *workstation)
527 {
528   s_mount_t mnt;
529   unsigned int i;
530   xbt_dict_t storage_list = xbt_dict_new_homogeneous(NULL);
531   char *storage_name = NULL;
532
533   workstation_CLM03_t ws = (workstation_CLM03_t) surf_workstation_resource_priv(workstation);
534   xbt_dynar_t storages = ws->storage;
535
536   xbt_dynar_foreach(storages,i,mnt){
537     storage_name = ((storage_t)mnt.storage)->generic_resource.name;
538     xbt_dict_set(storage_list,mnt.name,storage_name,NULL);
539   }
540   return storage_list;
541 }
542
543 static surf_action_t ws_action_open(void *workstation, const char* mount,
544                                     const char* path)
545 {
546   storage_t st = find_storage_on_mount_list(workstation, mount);
547   XBT_DEBUG("OPEN on disk '%s'",st->generic_resource.name);
548   surf_model_t model = st->generic_resource.model;
549   return model->extension.storage.open(st, mount, path);
550 }
551
552 static surf_action_t ws_action_close(void *workstation, surf_file_t fd)
553 {
554   storage_t st = find_storage_on_mount_list(workstation, fd->mount);
555   XBT_DEBUG("CLOSE on disk '%s'",st->generic_resource.name);
556   surf_model_t model = st->generic_resource.model;
557   return model->extension.storage.close(st, fd);
558 }
559
560 static surf_action_t ws_action_read(void *workstation, surf_file_t fd, sg_storage_size_t size)
561 {
562   storage_t st = find_storage_on_mount_list(workstation, fd->mount);
563   XBT_DEBUG("READ on disk '%s'",st->generic_resource.name);
564   surf_model_t model = st->generic_resource.model;
565   return model->extension.storage.read(st, fd, size);
566 }
567
568 static surf_action_t ws_action_write(void *workstation, surf_file_t fd, sg_storage_size_t size)
569 {
570   storage_t st = find_storage_on_mount_list(workstation, fd->mount);
571   XBT_DEBUG("WRITE on disk '%s'",st->generic_resource.name);
572   surf_model_t model = st->generic_resource.model;
573   return model->extension.storage.write(st, fd, size);
574 }
575
576 static int ws_file_unlink(void *workstation, surf_file_t fd)
577 {
578   if (!fd){
579     XBT_WARN("No such file descriptor. Impossible to unlink");
580     return 0;
581   } else {
582 //    XBT_INFO("%s %zu", fd->storage, fd->size);
583     storage_t st = find_storage_on_mount_list(workstation, fd->mount);
584     xbt_dict_t content_dict = (st)->content;
585     /* Check if the file is on this storage */
586     if (!xbt_dict_get_or_null(content_dict, fd->name)){
587       XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name,
588           st->generic_resource.name);
589       return 0;
590     } else {
591       XBT_DEBUG("UNLINK on disk '%s'",st->generic_resource.name);
592       st->used_size -= fd->size;
593
594       // Remove the file from storage
595       xbt_dict_remove(content_dict,fd->name);
596
597       free(fd->name);
598       free(fd->mount);
599       xbt_free(fd);
600       return 1;
601     }
602   }
603 }
604
605 static surf_action_t ws_action_ls(void *workstation, const char* mount,
606                                   const char *path)
607 {
608   XBT_DEBUG("LS on mount '%s' and file '%s'",mount, path);
609   storage_t st = find_storage_on_mount_list(workstation, mount);
610   surf_model_t model = st->generic_resource.model;
611   return model->extension.storage.ls(st, path);
612 }
613
614 static sg_storage_size_t ws_file_get_size(void *workstation, surf_file_t fd)
615 {
616   return fd->size;
617 }
618
619 static xbt_dynar_t ws_file_get_info(void *workstation, surf_file_t fd)
620 {
621   storage_t st = find_storage_on_mount_list(workstation, fd->mount);
622   sg_storage_size_t *psize = xbt_new(sg_storage_size_t, 1);
623   *psize = fd->size;
624   xbt_dynar_t info = xbt_dynar_new(sizeof(void*), NULL);
625   xbt_dynar_push_as(info, sg_storage_size_t *, psize);
626   xbt_dynar_push_as(info, void *, fd->mount);
627   xbt_dynar_push_as(info, void *, st->generic_resource.name);
628   xbt_dynar_push_as(info, void *, st->type_id);
629   xbt_dynar_push_as(info, void *, st->content_type);
630
631   return info;
632 }
633
634 static sg_storage_size_t ws_storage_get_free_size(void *workstation,const char* name)
635 {
636   storage_t st = find_storage_on_mount_list(workstation, name);
637   return st->size - st->used_size;
638 }
639
640 static sg_storage_size_t ws_storage_get_used_size(void *workstation,const char* name)
641 {
642   storage_t st = find_storage_on_mount_list(workstation, name);
643   return st->used_size;
644 }
645
646 void ws_get_params(void *ws, ws_params_t params)
647 {
648   workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
649   memcpy(params, &ws_clm03->params, sizeof(s_ws_params_t));
650 }
651
652 void ws_set_params(void *ws, ws_params_t params)
653 {
654   workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
655   /* may check something here. */
656   memcpy(&ws_clm03->params, params, sizeof(s_ws_params_t));
657 }
658
659 static xbt_dynar_t ws_get_vms(void *pm)
660 {
661   xbt_dynar_t dyn = xbt_dynar_new(sizeof(smx_host_t), NULL);
662
663   /* iterate for all hosts including virtual machines */
664   xbt_lib_cursor_t cursor;
665   char *key;
666   void **ind_host;
667   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
668     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
669     if (!ws_clm03)
670       continue;
671     /* skip if it is not a virtual machine */
672     if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
673       continue;
674
675     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
676     workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
677     if (pm == ws_vm2013->sub_ws)
678       xbt_dynar_push(dyn, &ws_vm2013->sub_ws);
679   }
680
681   return dyn;
682 }
683
684
685 static void surf_workstation_model_init_internal(void)
686 {
687   surf_model_t model = surf_model_init();
688
689   model->name = "Workstation";
690   model->type = SURF_MODEL_TYPE_WORKSTATION;
691   model->action_unref     = ws_action_unref;
692   model->action_cancel    = ws_action_cancel;
693   model->action_state_set = ws_action_state_set;
694
695   model->model_private->resource_used         = ws_resource_used;
696   model->model_private->share_resources       = ws_share_resources;
697   model->model_private->update_actions_state  = ws_update_actions_state;
698   model->model_private->update_resource_state = ws_update_resource_state;
699   model->model_private->finalize              = ws_finalize;
700
701   model->suspend          = ws_action_suspend;
702   model->resume           = ws_action_resume;
703   model->is_suspended     = ws_action_is_suspended;
704   model->set_max_duration = ws_action_set_max_duration;
705   model->set_priority     = ws_action_set_priority;
706   model->set_bound        = ws_action_set_bound;
707   model->set_affinity     = ws_action_set_affinity;
708   #ifdef HAVE_TRACING
709   model->set_category     = ws_action_set_category;
710   #endif
711   model->get_remains      = ws_action_get_remains;
712   #ifdef HAVE_LATENCY_BOUND_TRACKING
713   model->get_latency_limited = ws_get_latency_limited;
714   #endif
715
716   /* For VM support, we have a surf cpu model object for each workstation model
717    * object. The physical workstation model object has the cpu model object of
718    * the physical machine layer. */
719   xbt_assert(surf_cpu_model_pm);
720   model->extension.workstation.cpu_model = surf_cpu_model_pm;
721
722   model->extension.workstation.execute   = ws_execute;
723   model->extension.workstation.sleep     = ws_action_sleep;
724   model->extension.workstation.get_state = ws_get_state;
725   model->extension.workstation.set_state = ws_set_state;
726   model->extension.workstation.get_core  = ws_get_core;
727   model->extension.workstation.get_speed = ws_get_speed;
728   model->extension.workstation.get_available_speed =
729       ws_get_available_speed;
730   model->extension.workstation.get_current_power_peak = ws_get_current_power_peak;
731   model->extension.workstation.get_power_peak_at = ws_get_power_peak_at;
732   model->extension.workstation.get_nb_pstates = ws_get_nb_pstates;
733   model->extension.workstation.set_power_peak_at = ws_set_power_peak_at;
734   model->extension.workstation.get_consumed_energy = ws_get_consumed_energy;
735
736   model->extension.workstation.communicate = ws_communicate;
737   model->extension.workstation.get_route = ws_get_route;
738   model->extension.workstation.execute_parallel_task = ws_execute_parallel_task;
739   model->extension.workstation.get_link_bandwidth = ws_get_link_bandwidth;
740   model->extension.workstation.get_link_latency = ws_get_link_latency;
741   model->extension.workstation.link_shared = ws_link_shared;
742   model->extension.workstation.get_properties = ws_get_properties;
743
744   model->extension.workstation.open = ws_action_open;
745   model->extension.workstation.close = ws_action_close;
746   model->extension.workstation.read = ws_action_read;
747   model->extension.workstation.write = ws_action_write;
748   model->extension.workstation.unlink = ws_file_unlink;
749   model->extension.workstation.ls = ws_action_ls;
750   model->extension.workstation.get_size = ws_file_get_size;
751   model->extension.workstation.get_info = ws_file_get_info;
752   model->extension.workstation.get_free_size = ws_storage_get_free_size;
753   model->extension.workstation.get_used_size = ws_storage_get_used_size;
754   model->extension.workstation.get_storage_list = ws_get_storage_list;
755
756   model->extension.workstation.get_params = ws_get_params;
757   model->extension.workstation.set_params = ws_set_params;
758   model->extension.workstation.get_vms    = ws_get_vms;
759
760   surf_workstation_model = model;
761 }
762
763 void surf_workstation_model_init_current_default(void)
764 {
765   xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", "yes");
766   surf_cpu_model_init_Cas01();
767   surf_network_model_init_LegrandVelho();
768
769   /* surf_cpu_mode_pm and surf_network_model must be initialized in advance. */
770   xbt_assert(surf_cpu_model_pm);
771   xbt_assert(surf_network_model);
772   surf_workstation_model_init_internal();
773
774   xbt_dynar_push(model_list, &surf_workstation_model);
775   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
776   sg_platf_host_add_cb(workstation_new);
777 }
778
779 void surf_workstation_model_init_compound()
780 {
781   xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
782   xbt_assert(surf_network_model, "No network model defined yet!");
783
784   surf_workstation_model_init_internal();
785   xbt_dynar_push(model_list, &surf_workstation_model);
786   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
787   sg_platf_host_add_cb(workstation_new);
788 }