Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'hypervisor' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid into hypervisor
[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: The current code would be slow due to the iteration. Later, we can
105  * make it faster. */
106 static int constraint_is_active(cpu_Cas01_t cpu_cas01)
107 {
108   surf_model_t cpu_model = cpu_cas01->generic_resource.model;
109   lmm_system_t sys = cpu_model->model_private->maxmin_system;
110   int found = 0;
111   lmm_constraint_t cnst_tmp;
112
113   xbt_swag_foreach(cnst_tmp, &sys->active_constraint_set) {
114     if (cnst_tmp == cpu_cas01->constraint) {
115       found = 1;
116       break;
117     }
118   }
119
120   return found;
121 }
122
123 /* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
124  * constraint (capacity) of the VM in the PM layer. If the VM does not have any
125  * active task, the dummy CPU action must be deactivated, so that the VM does
126  * not get any CPU share in the PM layer. */
127 static void adjust_weight_of_dummy_cpu_actions(void)
128 {
129   /* iterate for all hosts including virtual machines */
130   xbt_lib_cursor_t cursor;
131   char *key;
132   void **ind_host;
133
134   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
135     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
136     cpu_Cas01_t cpu_cas01 = ind_host[SURF_CPU_LEVEL];
137
138     if (!ws_clm03)
139       continue;
140     /* skip if it is not a virtual machine */
141     if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
142       continue;
143     xbt_assert(cpu_cas01, "cpu-less workstation");
144
145     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
146     workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
147
148     if (constraint_is_active(cpu_cas01)) {
149       /* some tasks exist on this VM */
150       XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
151
152       /* FIXME: we shoud use lmm_update_variable_weight() ? */
153       /* FIXME: If we assgign 1.05 and 0.05, the system makes apparently wrong values. */
154       surf_action_set_priority(ws_vm2013->cpu_action, 1);
155
156     } else {
157       /* no task exits on this VM */
158       XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
159
160       surf_action_set_priority(ws_vm2013->cpu_action, 0);
161     }
162   }
163 }
164
165
166 double ws_share_resources(surf_model_t workstation_model, double now)
167 {
168   if (workstation_model->type == SURF_MODEL_TYPE_WORKSTATION)
169     adjust_weight_of_dummy_cpu_actions();
170
171   /* Invoke the share_resources() callback of the physical cpu model object and
172    * the network model objects. */
173   surf_model_t cpu_model = workstation_model->extension.workstation.cpu_model;
174   surf_model_t net_model = surf_network_model;
175
176   double min_by_cpu = cpu_model->model_private->share_resources(cpu_model, now);
177   double min_by_net = net_model->model_private->share_resources(net_model, now);
178
179   XBT_DEBUG("model %p, %s min_by_cpu %f, %s min_by_net %f",
180       workstation_model, cpu_model->name, min_by_cpu, net_model->name, min_by_net);
181
182   if (min_by_cpu >= 0.0 && min_by_net >= 0.0)
183     return min(min_by_cpu, min_by_net);
184   else if (min_by_cpu >= 0.0)
185     return min_by_cpu;
186   else if (min_by_net >= 0.0)
187     return min_by_net;
188   else
189     return min_by_cpu;  /* probably min_by_cpu == min_by_net == -1 */
190 }
191
192 void ws_update_actions_state(surf_model_t workstation_model, double now, double delta)
193 {
194   return;
195 }
196
197 void ws_update_resource_state(void *id, tmgr_trace_event_t event_type, double value, double date)
198 {
199   /* This model does not implement parallel tasks */
200   THROW_IMPOSSIBLE;
201 }
202
203 void ws_finalize(surf_model_t workstation_model)
204 {
205   surf_model_exit(workstation_model);
206   workstation_model = NULL;
207 }
208
209
210
211 surf_action_t ws_execute(void *workstation, double size)
212 {
213   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
214   return cpu->model->extension.cpu.execute(workstation, size);
215 }
216
217 surf_action_t ws_action_sleep(void *workstation, double duration)
218 {
219   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
220   return cpu->model->extension.cpu.sleep(workstation, duration);
221 }
222
223 void ws_action_suspend(surf_action_t action)
224 {
225   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
226     surf_network_model->suspend(action);
227   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
228     action->model_obj->suspend(action);
229   else
230     DIE_IMPOSSIBLE;
231 }
232
233 void ws_action_resume(surf_action_t action)
234 {
235   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
236     surf_network_model->resume(action);
237   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
238     action->model_obj->resume(action);
239   else
240     DIE_IMPOSSIBLE;
241 }
242
243 static int ws_action_is_suspended(surf_action_t action)
244 {
245   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
246     return surf_network_model->is_suspended(action);
247   if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
248     return action->model_obj->is_suspended(action);
249   DIE_IMPOSSIBLE;
250   return -1;
251 }
252
253 static void ws_action_set_max_duration(surf_action_t action,
254                                        double duration)
255 {
256   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
257     surf_network_model->set_max_duration(action, duration);
258   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
259     action->model_obj->set_max_duration(action, duration);
260   else
261     DIE_IMPOSSIBLE;
262 }
263
264 void ws_action_set_priority(surf_action_t action, double priority)
265 {
266   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
267     surf_network_model->set_priority(action, priority);
268   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
269     action->model_obj->set_priority(action, priority);
270   else
271     DIE_IMPOSSIBLE;
272 }
273
274 void ws_action_set_bound(surf_action_t action, double bound)
275 {
276   /* FIXME: only for CPU model object? */
277   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
278     surf_network_model->set_bound(action, bound);
279   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
280     action->model_obj->set_bound(action, bound);
281   else
282     DIE_IMPOSSIBLE;
283 }
284
285 #ifdef HAVE_TRACING
286 static void ws_action_set_category(surf_action_t action, const char *category)
287 {
288   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
289     surf_network_model->set_category(action, category);
290   else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
291     action->model_obj->set_category(action, category);
292   else
293     DIE_IMPOSSIBLE;
294 }
295 #endif
296
297 #ifdef HAVE_LATENCY_BOUND_TRACKING
298 static int ws_get_latency_limited(surf_action_t action)
299 {
300   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
301     return surf_network_model->get_latency_limited(action);
302   else
303     return 0;
304 }
305 #endif
306
307 double ws_action_get_remains(surf_action_t action)
308 {
309   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
310     return surf_network_model->get_remains(action);
311   if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
312     return action->model_obj->get_remains(action);
313   DIE_IMPOSSIBLE;
314   return -1.0;
315 }
316
317 static surf_action_t ws_communicate(void *workstation_src,
318                                     void *workstation_dst, double size,
319                                     double rate)
320 {
321   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
322   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
323   return surf_network_model->extension.network.
324       communicate(src->net_elm,
325                   dst->net_elm, size, rate);
326 }
327
328 e_surf_resource_state_t ws_get_state(void *workstation)
329 {
330   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
331   return cpu->model->extension.cpu.get_state(workstation);
332 }
333
334 static void ws_set_state(void *workstation, e_surf_resource_state_t state)
335 {
336   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
337   cpu->model->extension.cpu.set_state(workstation, state);
338 }
339
340 double ws_get_speed(void *workstation, double load)
341 {
342   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
343   return cpu->model->extension.cpu.get_speed(workstation, load);
344 }
345
346 static int ws_get_core(void *workstation)
347 {
348   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
349   return cpu->model->extension.cpu.get_core(workstation);
350 }
351 static double ws_get_available_speed(void *workstation)
352 {
353   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
354   return cpu->model->extension.cpu.get_available_speed(workstation);
355 }
356
357 static surf_action_t ws_execute_parallel_task(int workstation_nb,
358                                               void **workstation_list,
359                                               double *computation_amount,
360                                               double *communication_amount,
361                                               double rate)
362 {
363 #define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0)
364   if ((workstation_nb == 1)
365       && (cost_or_zero(communication_amount, 0) == 0.0))
366     return ws_execute(workstation_list[0], computation_amount[0]);
367   else if ((workstation_nb == 1)
368            && (cost_or_zero(computation_amount, 0) == 0.0))
369     return ws_communicate(workstation_list[0], workstation_list[0],communication_amount[0], rate);
370   else if ((workstation_nb == 2)
371              && (cost_or_zero(computation_amount, 0) == 0.0)
372              && (cost_or_zero(computation_amount, 1) == 0.0)) {
373     int i,nb = 0;
374     double value = 0.0;
375
376     for (i = 0; i < workstation_nb * workstation_nb; i++) {
377       if (cost_or_zero(communication_amount, i) > 0.0) {
378         nb++;
379         value = cost_or_zero(communication_amount, i);
380       }
381     }
382     if (nb == 1)
383       return ws_communicate(workstation_list[0], workstation_list[1],value, rate);
384   }
385 #undef cost_or_zero
386
387   THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
388   return NULL;
389 }
390
391
392 /* returns an array of network_link_CM02_t */
393 static xbt_dynar_t ws_get_route(void *workstation_src, void *workstation_dst)
394 {
395   XBT_DEBUG("ws_get_route");
396   workstation_CLM03_t src = surf_workstation_resource_priv(workstation_src);
397   workstation_CLM03_t dst = surf_workstation_resource_priv(workstation_dst);
398   return surf_network_model->extension.
399       network.get_route(src->net_elm,
400                   dst->net_elm);
401 }
402
403 static double ws_get_link_bandwidth(const void *link)
404 {
405   return surf_network_model->extension.network.get_link_bandwidth(link);
406 }
407
408 static double ws_get_link_latency(const void *link)
409 {
410   return surf_network_model->extension.network.get_link_latency(link);
411 }
412
413 static int ws_link_shared(const void *link)
414 {
415   return surf_network_model->extension.network.link_shared(link);
416 }
417
418 static xbt_dict_t ws_get_properties(const void *ws)
419 {
420   return surf_resource_properties(surf_cpu_resource_priv(ws));
421 }
422
423 static storage_t find_storage_on_mount_list(void *workstation,const char* storage)
424 {
425   storage_t st = NULL;
426   s_mount_t mnt;
427   unsigned int cursor;
428   workstation_CLM03_t ws = (workstation_CLM03_t) surf_workstation_resource_priv(workstation);
429   xbt_dynar_t storage_list = ws->storage;
430
431   XBT_DEBUG("Search for storage name '%s' on '%s'",storage,ws->generic_resource.name);
432   xbt_dynar_foreach(storage_list,cursor,mnt)
433   {
434     XBT_DEBUG("See '%s'",mnt.name);
435     if(!strcmp(storage,mnt.name)){
436       st = mnt.id;
437       break;
438     }
439   }
440   if(!st) xbt_die("Can't find mount '%s' for '%s'",storage,ws->generic_resource.name);
441   return st;
442 }
443
444 static surf_action_t ws_action_open(void *workstation, const char* mount,
445                                     const char* path)
446 {
447   storage_t st = find_storage_on_mount_list(workstation, mount);
448   XBT_DEBUG("OPEN on disk '%s'",st->generic_resource.name);
449   surf_model_t model = st->generic_resource.model;
450   return model->extension.storage.open(st, mount, path);
451 }
452
453 static surf_action_t ws_action_close(void *workstation, surf_file_t fd)
454 {
455   storage_t st = find_storage_on_mount_list(workstation, fd->storage);
456   XBT_DEBUG("CLOSE on disk '%s'",st->generic_resource.name);
457   surf_model_t model = st->generic_resource.model;
458   return model->extension.storage.close(st, fd);
459 }
460
461 static surf_action_t ws_action_read(void *workstation, void* ptr, size_t size,
462                                     surf_file_t fd)
463 {
464   storage_t st = find_storage_on_mount_list(workstation, fd->storage);
465   XBT_DEBUG("READ on disk '%s'",st->generic_resource.name);
466   surf_model_t model = st->generic_resource.model;
467   return model->extension.storage.read(st, ptr, size, fd);
468 }
469
470 static surf_action_t ws_action_write(void *workstation, const void* ptr,
471                                      size_t size, surf_file_t fd)
472 {
473   storage_t st = find_storage_on_mount_list(workstation, fd->storage);
474   XBT_DEBUG("WRITE on disk '%s'",st->generic_resource.name);
475   surf_model_t model = st->generic_resource.model;
476   return model->extension.storage.write(st,  ptr, size, fd);
477 }
478
479 static int ws_file_unlink(void *workstation, surf_file_t fd)
480 {
481   if (!fd){
482     XBT_WARN("No such file descriptor. Impossible to unlink");
483     return 0;
484   } else {
485 //    XBT_INFO("%s %zu", fd->storage, fd->size);
486     storage_t st = find_storage_on_mount_list(workstation, fd->storage);
487     xbt_dict_t content_dict = (st)->content;
488     /* Check if the file is on this storage */
489     if (!xbt_dict_get_or_null(content_dict, fd->name)){
490       XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name,
491           st->generic_resource.name);
492       return 0;
493     } else {
494       XBT_DEBUG("UNLINK on disk '%s'",st->generic_resource.name);
495       st->used_size -= fd->size;
496
497       // Remove the file from storage
498       xbt_dict_remove(content_dict,fd->name);
499
500       free(fd->name);
501       free(fd->storage);
502       xbt_free(fd);
503       return 1;
504     }
505   }
506 }
507
508 static surf_action_t ws_action_ls(void *workstation, const char* mount,
509                                   const char *path)
510 {
511   XBT_DEBUG("LS on mount '%s' and file '%s'",mount, path);
512   storage_t st = find_storage_on_mount_list(workstation, mount);
513   surf_model_t model = st->generic_resource.model;
514   return model->extension.storage.ls(st, path);
515 }
516
517 static size_t ws_file_get_size(void *workstation, surf_file_t fd)
518 {
519   return fd->size;
520 }
521
522 void ws_get_params(void *ws, ws_params_t params)
523 {
524   workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
525   memcpy(params, &ws_clm03->params, sizeof(s_ws_params_t));
526 }
527
528 void ws_set_params(void *ws, ws_params_t params)
529 {
530   workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
531   /* may check something here. */
532   memcpy(&ws_clm03->params, params, sizeof(s_ws_params_t));
533 }
534
535 static xbt_dynar_t ws_get_vms(void *pm)
536 {
537   xbt_dynar_t dyn = xbt_dynar_new(sizeof(smx_host_t), NULL);
538
539   /* iterate for all hosts including virtual machines */
540   xbt_lib_cursor_t cursor;
541   char *key;
542   void **ind_host;
543   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
544     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
545     if (!ws_clm03)
546       continue;
547     /* skip if it is not a virtual machine */
548     if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
549       continue;
550
551     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
552     workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
553     if (pm == ws_vm2013->sub_ws)
554       xbt_dynar_push(dyn, &ws_vm2013->sub_ws);
555   }
556
557   return dyn;
558 }
559
560
561 static void surf_workstation_model_init_internal(void)
562 {
563   surf_model_t model = surf_model_init();
564
565   model->name = "Workstation";
566   model->type = SURF_MODEL_TYPE_WORKSTATION;
567   model->action_unref     = ws_action_unref;
568   model->action_cancel    = ws_action_cancel;
569   model->action_state_set = ws_action_state_set;
570
571   model->model_private->resource_used         = ws_resource_used;
572   model->model_private->share_resources       = ws_share_resources;
573   model->model_private->update_actions_state  = ws_update_actions_state;
574   model->model_private->update_resource_state = ws_update_resource_state;
575   model->model_private->finalize              = ws_finalize;
576
577   model->suspend          = ws_action_suspend;
578   model->resume           = ws_action_resume;
579   model->is_suspended     = ws_action_is_suspended;
580   model->set_max_duration = ws_action_set_max_duration;
581   model->set_priority     = ws_action_set_priority;
582   model->set_bound        = ws_action_set_bound;
583   #ifdef HAVE_TRACING
584   model->set_category     = ws_action_set_category;
585   #endif
586   model->get_remains      = ws_action_get_remains;
587   #ifdef HAVE_LATENCY_BOUND_TRACKING
588   model->get_latency_limited = ws_get_latency_limited;
589   #endif
590
591   /* For VM support, we have a surf cpu model object for each workstation model
592    * object. The physical workstation model object has the cpu model object of
593    * the physical machine layer. */
594   xbt_assert(surf_cpu_model_pm);
595   model->extension.workstation.cpu_model = surf_cpu_model_pm;
596
597   model->extension.workstation.execute   = ws_execute;
598   model->extension.workstation.sleep     = ws_action_sleep;
599   model->extension.workstation.get_state = ws_get_state;
600   model->extension.workstation.set_state = ws_set_state;
601   model->extension.workstation.get_core  = ws_get_core;
602   model->extension.workstation.get_speed = ws_get_speed;
603   model->extension.workstation.get_available_speed =
604       ws_get_available_speed;
605
606   model->extension.workstation.communicate           = ws_communicate;
607   model->extension.workstation.get_route             = ws_get_route;
608   model->extension.workstation.execute_parallel_task = ws_execute_parallel_task;
609   model->extension.workstation.get_link_bandwidth    = ws_get_link_bandwidth;
610   model->extension.workstation.get_link_latency      = ws_get_link_latency;
611   model->extension.workstation.link_shared           = ws_link_shared;
612   model->extension.workstation.get_properties        = ws_get_properties;
613
614   model->extension.workstation.open   = ws_action_open;
615   model->extension.workstation.close  = ws_action_close;
616   model->extension.workstation.read   = ws_action_read;
617   model->extension.workstation.write  = ws_action_write;
618   model->extension.workstation.unlink = ws_file_unlink;
619   model->extension.workstation.ls     = ws_action_ls;
620
621   model->extension.workstation.get_params = ws_get_params;
622   model->extension.workstation.set_params = ws_set_params;
623   model->extension.workstation.get_vms    = ws_get_vms;
624
625   surf_workstation_model = model;
626 }
627
628 void surf_workstation_model_init_current_default(void)
629 {
630   xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", xbt_strdup("yes"));
631   surf_cpu_model_init_Cas01();
632   surf_network_model_init_LegrandVelho();
633
634   /* surf_cpu_mode_pm and surf_network_model must be initialized in advance. */
635   xbt_assert(surf_cpu_model_pm);
636   xbt_assert(surf_network_model);
637   surf_workstation_model_init_internal();
638
639   xbt_dynar_push(model_list, &surf_workstation_model);
640   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
641   sg_platf_host_add_cb(workstation_new);
642 }
643
644 void surf_workstation_model_init_compound()
645 {
646   xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
647   xbt_assert(surf_network_model, "No network model defined yet!");
648
649   surf_workstation_model_init_internal();
650   xbt_dynar_push(model_list, &surf_workstation_model);
651   xbt_dynar_push(model_list_invoke, &surf_workstation_model);
652   sg_platf_host_add_cb(workstation_new);
653 }