Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add the set_affinity callback to the PM/VM models
[simgrid.git] / src / surf / workstation.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 "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);
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 surf_action_t ws_execute_parallel_task(int workstation_nb,
404                                               void **workstation_list,
405                                               double *computation_amount,
406                                               double *communication_amount,
407                                               double rate)
408 {
409 #define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0)
410   if ((workstation_nb == 1)
411       && (cost_or_zero(communication_amount, 0) == 0.0))
412     return ws_execute(workstation_list[0], computation_amount[0]);
413   else if ((workstation_nb == 1)
414            && (cost_or_zero(computation_amount, 0) == 0.0))
415     return ws_communicate(workstation_list[0], workstation_list[0],communication_amount[0], rate);
416   else if ((workstation_nb == 2)
417              && (cost_or_zero(computation_amount, 0) == 0.0)
418              && (cost_or_zero(computation_amount, 1) == 0.0)) {
419     int i,nb = 0;
420     double value = 0.0;
421
422     for (i = 0; i < workstation_nb * workstation_nb; i++) {
423       if (cost_or_zero(communication_amount, i) > 0.0) {
424         nb++;
425         value = cost_or_zero(communication_amount, i);
426       }
427     }
428     if (nb == 1)
429       return ws_communicate(workstation_list[0], workstation_list[1],value, rate);
430   }
431 #undef cost_or_zero
432
433   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
434   return NULL;
435 }
436
437
438 /* returns an array of network_link_CM02_t */
439 static xbt_dynar_t ws_get_route(void *workstation_src, void *workstation_dst)
440 {
441   XBT_DEBUG("ws_get_route");
442   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
443   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
444   return surf_network_model->extension.
445       network.get_route(src->net_elm,
446                   dst->net_elm);
447 }
448
449 static double ws_get_link_bandwidth(const void *link)
450 {
451   return surf_network_model->extension.network.get_link_bandwidth(link);
452 }
453
454 static double ws_get_link_latency(const void *link)
455 {
456   return surf_network_model->extension.network.get_link_latency(link);
457 }
458
459 static int ws_link_shared(const void *link)
460 {
461   return surf_network_model->extension.network.link_shared(link);
462 }
463
464 static xbt_dict_t ws_get_properties(const void *ws)
465 {
466   return surf_resource_properties(surf_cpu_resource_priv(ws));
467 }
468
469 static storage_t find_storage_on_mount_list(void *workstation,const char* storage)
470 {
471   storage_t st = NULL;
472   s_mount_t mnt;
473   unsigned int cursor;
474   workstation_CLM03_t ws = (workstation_CLM03_t) surf_workstation_resource_priv(workstation);
475   xbt_dynar_t storage_list = ws->storage;
476
477   XBT_DEBUG("Search for storage name '%s' on '%s'",storage,ws->generic_resource.name);
478   xbt_dynar_foreach(storage_list,cursor,mnt)
479   {
480     XBT_DEBUG("See '%s'",mnt.name);
481     if(!strcmp(storage,mnt.name)){
482       st = mnt.id;
483       break;
484     }
485   }
486   if(!st) xbt_die("Can't find mount '%s' for '%s'",storage,ws->generic_resource.name);
487   return st;
488 }
489
490 static surf_action_t ws_action_open(void *workstation, const char* mount,
491                                     const char* path)
492 {
493   storage_t st = find_storage_on_mount_list(workstation, mount);
494   XBT_DEBUG("OPEN on disk '%s'",st->generic_resource.name);
495   surf_model_t model = st->generic_resource.model;
496   return model->extension.storage.open(st, mount, path);
497 }
498
499 static surf_action_t ws_action_close(void *workstation, surf_file_t fd)
500 {
501   storage_t st = find_storage_on_mount_list(workstation, fd->storage);
502   XBT_DEBUG("CLOSE on disk '%s'",st->generic_resource.name);
503   surf_model_t model = st->generic_resource.model;
504   return model->extension.storage.close(st, fd);
505 }
506
507 static surf_action_t ws_action_read(void *workstation, void* ptr, size_t size,
508                                     surf_file_t fd)
509 {
510   storage_t st = find_storage_on_mount_list(workstation, fd->storage);
511   XBT_DEBUG("READ on disk '%s'",st->generic_resource.name);
512   surf_model_t model = st->generic_resource.model;
513   return model->extension.storage.read(st, ptr, size, fd);
514 }
515
516 static surf_action_t ws_action_write(void *workstation, const void* ptr,
517                                      size_t size, surf_file_t fd)
518 {
519   storage_t st = find_storage_on_mount_list(workstation, fd->storage);
520   XBT_DEBUG("WRITE on disk '%s'",st->generic_resource.name);
521   surf_model_t model = st->generic_resource.model;
522   return model->extension.storage.write(st,  ptr, size, fd);
523 }
524
525 static int ws_file_unlink(void *workstation, surf_file_t fd)
526 {
527   if (!fd){
528     XBT_WARN("No such file descriptor. Impossible to unlink");
529     return 0;
530   } else {
531 //    XBT_INFO("%s %zu", fd->storage, fd->size);
532     storage_t st = find_storage_on_mount_list(workstation, fd->storage);
533     xbt_dict_t content_dict = (st)->content;
534     /* Check if the file is on this storage */
535     if (!xbt_dict_get_or_null(content_dict, fd->name)){
536       XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name,
537           st->generic_resource.name);
538       return 0;
539     } else {
540       XBT_DEBUG("UNLINK on disk '%s'",st->generic_resource.name);
541       st->used_size -= fd->size;
542
543       // Remove the file from storage
544       xbt_dict_remove(content_dict,fd->name);
545
546       free(fd->name);
547       free(fd->storage);
548       xbt_free(fd);
549       return 1;
550     }
551   }
552 }
553
554 static surf_action_t ws_action_ls(void *workstation, const char* mount,
555                                   const char *path)
556 {
557   XBT_DEBUG("LS on mount '%s' and file '%s'",mount, path);
558   storage_t st = find_storage_on_mount_list(workstation, mount);
559   surf_model_t model = st->generic_resource.model;
560   return model->extension.storage.ls(st, path);
561 }
562
563 static size_t ws_file_get_size(void *workstation, surf_file_t fd)
564 {
565   return fd->size;
566 }
567
568 void ws_get_params(void *ws, ws_params_t params)
569 {
570   workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
571   memcpy(params, &ws_clm03->params, sizeof(s_ws_params_t));
572 }
573
574 void ws_set_params(void *ws, ws_params_t params)
575 {
576   workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
577   /* may check something here. */
578   memcpy(&ws_clm03->params, params, sizeof(s_ws_params_t));
579 }
580
581 static xbt_dynar_t ws_get_vms(void *pm)
582 {
583   xbt_dynar_t dyn = xbt_dynar_new(sizeof(smx_host_t), NULL);
584
585   /* iterate for all hosts including virtual machines */
586   xbt_lib_cursor_t cursor;
587   char *key;
588   void **ind_host;
589   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
590     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
591     if (!ws_clm03)
592       continue;
593     /* skip if it is not a virtual machine */
594     if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
595       continue;
596
597     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
598     workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
599     if (pm == ws_vm2013->sub_ws)
600       xbt_dynar_push(dyn, &ws_vm2013->sub_ws);
601   }
602
603   return dyn;
604 }
605
606
607 static void surf_workstation_model_init_internal(void)
608 {
609   surf_model_t model = surf_model_init();
610
611   model->name = "Workstation";
612   model->type = SURF_MODEL_TYPE_WORKSTATION;
613   model->action_unref     = ws_action_unref;
614   model->action_cancel    = ws_action_cancel;
615   model->action_state_set = ws_action_state_set;
616
617   model->model_private->resource_used         = ws_resource_used;
618   model->model_private->share_resources       = ws_share_resources;
619   model->model_private->update_actions_state  = ws_update_actions_state;
620   model->model_private->update_resource_state = ws_update_resource_state;
621   model->model_private->finalize              = ws_finalize;
622
623   model->suspend          = ws_action_suspend;
624   model->resume           = ws_action_resume;
625   model->is_suspended     = ws_action_is_suspended;
626   model->set_max_duration = ws_action_set_max_duration;
627   model->set_priority     = ws_action_set_priority;
628   model->set_bound        = ws_action_set_bound;
629   model->set_affinity     = ws_action_set_affinity;
630   #ifdef HAVE_TRACING
631   model->set_category     = ws_action_set_category;
632   #endif
633   model->get_remains      = ws_action_get_remains;
634   #ifdef HAVE_LATENCY_BOUND_TRACKING
635   model->get_latency_limited = ws_get_latency_limited;
636   #endif
637
638   /* For VM support, we have a surf cpu model object for each workstation model
639    * object. The physical workstation model object has the cpu model object of
640    * the physical machine layer. */
641   xbt_assert(surf_cpu_model_pm);
642   model->extension.workstation.cpu_model = surf_cpu_model_pm;
643
644   model->extension.workstation.execute   = ws_execute;
645   model->extension.workstation.sleep     = ws_action_sleep;
646   model->extension.workstation.get_state = ws_get_state;
647   model->extension.workstation.set_state = ws_set_state;
648   model->extension.workstation.get_core  = ws_get_core;
649   model->extension.workstation.get_speed = ws_get_speed;
650   model->extension.workstation.get_available_speed =
651       ws_get_available_speed;
652
653   model->extension.workstation.communicate           = ws_communicate;
654   model->extension.workstation.get_route             = ws_get_route;
655   model->extension.workstation.execute_parallel_task = ws_execute_parallel_task;
656   model->extension.workstation.get_link_bandwidth    = ws_get_link_bandwidth;
657   model->extension.workstation.get_link_latency      = ws_get_link_latency;
658   model->extension.workstation.link_shared           = ws_link_shared;
659   model->extension.workstation.get_properties        = ws_get_properties;
660
661   model->extension.workstation.open   = ws_action_open;
662   model->extension.workstation.close  = ws_action_close;
663   model->extension.workstation.read   = ws_action_read;
664   model->extension.workstation.write  = ws_action_write;
665   model->extension.workstation.unlink = ws_file_unlink;
666   model->extension.workstation.ls     = ws_action_ls;
667
668   model->extension.workstation.get_params = ws_get_params;
669   model->extension.workstation.set_params = ws_set_params;
670   model->extension.workstation.get_vms    = ws_get_vms;
671
672   surf_workstation_model = model;
673 }
674
675 void surf_workstation_model_init_current_default(void)
676 {
677   xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", xbt_strdup("yes"));
678   surf_cpu_model_init_Cas01();
679   surf_network_model_init_LegrandVelho();
680
681   /* surf_cpu_mode_pm and surf_network_model must be initialized in advance. */
682   xbt_assert(surf_cpu_model_pm);
683   xbt_assert(surf_network_model);
684   surf_workstation_model_init_internal();
685
686   xbt_dynar_push(model_list, &surf_workstation_model);
687   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
688   sg_platf_host_add_cb(workstation_new);
689 }
690
691 void surf_workstation_model_init_compound()
692 {
693   xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
694   xbt_assert(surf_network_model, "No network model defined yet!");
695
696   surf_workstation_model_init_internal();
697   xbt_dynar_push(model_list, &surf_workstation_model);
698   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
699   sg_platf_host_add_cb(workstation_new);
700 }