Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ba2f7373864e049bddcec709a97456b2d020965f
[simgrid.git] / src / surf / workstation_ptask_L07.c
1 /*      $Id$     */
2
3 /* Copyright (c) 2007 Arnaud Legrand. All rights reserved.                  */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "xbt/ex.h"
9 #include "xbt/dict.h"
10 #include "surf_private.h"
11 /* extern lmm_system_t maxmin_system; */
12
13 typedef enum {
14   SURF_WORKSTATION_RESOURCE_CPU,
15   SURF_WORKSTATION_RESOURCE_LINK,
16 } e_surf_workstation_model_type_t;
17
18 /**************************************/
19 /********* cpu object *****************/
20 /**************************************/
21 typedef struct cpu_L07 {
22   surf_model_t model;   /* Do not move this field */
23   e_surf_workstation_model_type_t type; /* Do not move this field */
24   char *name;                   /* Do not move this field */
25   lmm_constraint_t constraint;  /* Do not move this field */
26   double power_scale;
27   double power_current;
28   tmgr_trace_event_t power_event;
29   e_surf_cpu_state_t state_current;
30   tmgr_trace_event_t state_event;
31   int id;                       /* cpu and network card are a single object... */
32 } s_cpu_L07_t, *cpu_L07_t;
33
34 /**************************************/
35 /*********** network object ***********/
36 /**************************************/
37
38 typedef struct network_link_L07 {
39   surf_model_t model;   /* Do not move this field */
40   e_surf_workstation_model_type_t type; /* Do not move this field */
41   char *name;                   /* Do not move this field */
42   lmm_constraint_t constraint;  /* Do not move this field */
43   double lat_current;
44   tmgr_trace_event_t lat_event;
45   double bw_current;
46   tmgr_trace_event_t bw_event;
47   e_surf_network_link_state_t state_current;
48   tmgr_trace_event_t state_event;
49 } s_network_link_L07_t, *network_link_L07_t;
50
51
52 typedef struct s_route_L07 {
53   network_link_L07_t *links;
54   int size;
55 } s_route_L07_t, *route_L07_t;
56
57 /**************************************/
58 /*************** actions **************/
59 /**************************************/
60 typedef struct surf_action_workstation_L07 {
61   s_surf_action_t generic_action;
62   lmm_variable_t variable;
63   int workstation_nb;
64   cpu_L07_t *workstation_list;
65   double *computation_amount;
66   double *communication_amount;
67   double latency;
68   double rate;
69   int suspended;
70 } s_surf_action_workstation_L07_t, *surf_action_workstation_L07_t;
71
72
73 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_workstation);
74
75 static int nb_workstation = 0;
76 static s_route_L07_t *routing_table = NULL;
77 #define ROUTE(i,j) routing_table[(i)+(j)*nb_workstation]
78 static network_link_L07_t loopback = NULL;
79 static xbt_dict_t parallel_task_network_link_set = NULL;
80 lmm_system_t ptask_maxmin_system = NULL;
81
82
83 static void update_action_bound(surf_action_workstation_L07_t action)
84 {
85   int workstation_nb = action->workstation_nb;
86   double lat_current = 0.0;
87   double lat_bound = -1.0;
88   int i, j, k;
89   
90   for (i = 0; i < workstation_nb; i++) {
91     for (j = 0; j < workstation_nb; j++) {
92       cpu_L07_t card_src = action->workstation_list[i];
93       cpu_L07_t card_dst = action->workstation_list[j];
94       int route_size = ROUTE(card_src->id, card_dst->id).size;
95       network_link_L07_t *route = ROUTE(card_src->id, card_dst->id).links;
96       double lat = 0.0;
97       
98       if (action->communication_amount[i * workstation_nb + j] > 0) {
99         for (k = 0; k < route_size; k++) {
100           lat += route[k]->lat_current;
101           xbt_dict_set(parallel_task_network_link_set, route[k]->name,
102                        route[k], NULL);
103         }
104         lat_current=MAX(lat_current,lat/action->communication_amount[i * workstation_nb + j]);
105       }
106     }
107   }
108   lat_bound = SG_TCP_CTE_GAMMA / (2.0 * lat_current);
109   DEBUG2("action (%p) : lat_bound = %g", action, lat_bound);
110   if ((action->latency == 0.0) && (action->suspended == 0)) {
111     if (action->rate < 0)
112       lmm_update_variable_bound(ptask_maxmin_system, action->variable,
113                                 lat_bound);
114     else
115       lmm_update_variable_bound(ptask_maxmin_system, action->variable,
116                                 min(action->rate,lat_bound));
117   }
118 }
119
120 /**************************************/
121 /******* Resource Public     **********/
122 /**************************************/
123
124 static void *name_service(const char *name)
125 {
126   return xbt_dict_get_or_null(workstation_set, name);
127 }
128
129 static const char *get_resource_name(void *resource_id)
130 {
131   /* We can freely cast as a cpu_L07_t because it has the same
132      prefix as network_link_L07_t. However, only cpu_L07_t
133      will theoretically be given as an argument here. */
134   return ((cpu_L07_t) resource_id)->name;
135 }
136
137 /* action_get_state is inherited from the surf module */
138
139 static void action_use(surf_action_t action)
140 {
141   action->using++;
142   return;
143 }
144
145 static int action_free(surf_action_t action)
146 {
147   action->using--;
148
149   if (!action->using) {
150     xbt_swag_remove(action, action->state_set);
151     if (((surf_action_workstation_L07_t) action)->variable)
152       lmm_variable_free(ptask_maxmin_system,
153                         ((surf_action_workstation_L07_t) action)->
154                         variable);
155     free(((surf_action_workstation_L07_t)action)->workstation_list);
156     free(((surf_action_workstation_L07_t)action)->communication_amount);
157     free(((surf_action_workstation_L07_t)action)->computation_amount);
158     free(action);
159     return 1;
160   }
161   return 0;
162 }
163
164 static void action_cancel(surf_action_t action)
165 {
166   surf_action_change_state(action, SURF_ACTION_FAILED);
167   return;
168 }
169
170 static void action_recycle(surf_action_t action)
171 {
172   DIE_IMPOSSIBLE;
173   return;
174 }
175
176 /* action_change_state is inherited from the surf module */
177 /* action_set_data is inherited from the surf module */
178
179 static void action_suspend(surf_action_t action)
180 {
181   XBT_IN1("(%p))", action);
182   if (((surf_action_workstation_L07_t) action)->suspended != 2) {
183     ((surf_action_workstation_L07_t) action)->suspended = 1;
184     lmm_update_variable_weight(ptask_maxmin_system,
185                                ((surf_action_workstation_L07_t)
186                                 action)->variable, 0.0);
187   }
188   XBT_OUT;
189 }
190
191 static void action_resume(surf_action_t action)
192 {
193   surf_action_workstation_L07_t act = (surf_action_workstation_L07_t) action;
194
195   XBT_IN1("(%p)", act);
196   if (act->suspended != 2) {
197     lmm_update_variable_weight(ptask_maxmin_system,action->variable, 1.0);
198     act->suspended = 0;
199   }
200   XBT_OUT;
201 }
202
203 static int action_is_suspended(surf_action_t action)
204 {
205   return (((surf_action_workstation_L07_t) action)->suspended == 1);
206 }
207
208 static void action_set_max_duration(surf_action_t action, double duration)
209 {                               /* FIXME: should inherit */
210   XBT_IN2("(%p,%g)", action, duration);
211   action->max_duration = duration;
212   XBT_OUT;
213 }
214
215
216 static void action_set_priority(surf_action_t action, double priority)
217 {                               /* FIXME: should inherit */
218   XBT_IN2("(%p,%g)", action, priority);
219   action->priority = priority;
220   XBT_OUT;
221 }
222
223 /**************************************/
224 /******* Resource Private    **********/
225 /**************************************/
226
227 static int resource_used(void *resource_id)
228 {
229   /* We can freely cast as a network_link_L07_t because it has
230      the same prefix as cpu_L07_t */
231   return lmm_constraint_used(ptask_maxmin_system,
232                              ((network_link_L07_t) resource_id)->
233                              constraint);
234
235 }
236
237 static double share_resources(double now)
238 {
239   s_surf_action_workstation_L07_t s_action;
240   surf_action_workstation_L07_t action = NULL;
241
242   xbt_swag_t running_actions =
243       surf_workstation_model->common_public->states.running_action_set;
244   double min = generic_maxmin_share_resources2(running_actions,
245                                                xbt_swag_offset(s_action,
246                                                                variable),
247                                                ptask_maxmin_system,
248                                                bottleneck_solve);
249
250   xbt_swag_foreach(action, running_actions) {
251     if (action->latency > 0) {
252       if (min < 0) {
253         min = action->latency;
254         DEBUG3("Updating min (value) with %p (start %f): %f", action,
255                action->generic_action.start, min);
256       } else if (action->latency < min) {
257         min = action->latency;
258         DEBUG3("Updating min (latency) with %p (start %f): %f", action,
259                action->generic_action.start, min);
260       }
261     }
262   }
263
264   DEBUG1("min value : %f", min);
265
266   return min;
267 }
268
269 static void update_actions_state(double now, double delta)
270 {
271   double deltap = 0.0;
272   surf_action_workstation_L07_t action = NULL;
273   surf_action_workstation_L07_t next_action = NULL;
274   xbt_swag_t running_actions =
275       surf_workstation_model->common_public->states.running_action_set;
276
277   xbt_swag_foreach_safe(action, next_action, running_actions) {
278     deltap = delta;
279     if (action->latency > 0) {
280       if (action->latency > deltap) {
281         double_update(&(action->latency), deltap);
282         deltap = 0.0;
283       } else {
284         double_update(&(deltap), action->latency);
285         action->latency = 0.0;
286       }
287       if ((action->latency == 0.0) && (action->suspended == 0)) {
288         update_action_bound(action);
289         lmm_update_variable_weight(ptask_maxmin_system,action->variable, 1.0);
290       }
291     }
292     DEBUG3("Action (%p) : remains (%g) updated by %g.",
293            action, action->generic_action.remains,
294            lmm_variable_getvalue(action->variable) * delta);
295     double_update(&(action->generic_action.remains),
296                   lmm_variable_getvalue(action->variable) * delta);
297
298     if (action->generic_action.max_duration != NO_MAX_DURATION)
299       double_update(&(action->generic_action.max_duration), delta);
300
301     DEBUG2("Action (%p) : remains (%g).",
302            action, action->generic_action.remains);
303     if ((action->generic_action.remains <= 0) &&
304         (lmm_get_variable_weight(action->variable) > 0)) {
305       action->generic_action.finish = surf_get_clock();
306       surf_action_change_state((surf_action_t) action, SURF_ACTION_DONE);
307     } else if ((action->generic_action.max_duration != NO_MAX_DURATION) &&
308                (action->generic_action.max_duration <= 0)) {
309       action->generic_action.finish = surf_get_clock();
310       surf_action_change_state((surf_action_t) action, SURF_ACTION_DONE);
311     } else {
312       /* Need to check that none of the model has failed */
313       lmm_constraint_t cnst = NULL;
314       int i = 0;
315       void *constraint_id = NULL;
316
317       while ((cnst =
318               lmm_get_cnst_from_var(ptask_maxmin_system, action->variable,
319                                     i++))) {
320         constraint_id = lmm_constraint_id(cnst);
321
322 /*      if(((network_link_L07_t)constraint_id)->type== */
323 /*         SURF_WORKSTATION_RESOURCE_LINK) { */
324 /*        DEBUG2("Checking for link %s (%p)", */
325 /*               ((network_link_L07_t)constraint_id)->name, */
326 /*               ((network_link_L07_t)constraint_id)); */
327 /*      } */
328 /*      if(((cpu_L07_t)constraint_id)->type== */
329 /*         SURF_WORKSTATION_RESOURCE_CPU) { */
330 /*        DEBUG3("Checking for cpu %s (%p) : %s", */
331 /*               ((cpu_L07_t)constraint_id)->name, */
332 /*               ((cpu_L07_t)constraint_id), */
333 /*               ((cpu_L07_t)constraint_id)->state_current==SURF_CPU_OFF?"Off":"On"); */
334 /*      } */
335
336         if (((((network_link_L07_t) constraint_id)->type ==
337               SURF_WORKSTATION_RESOURCE_LINK) &&
338              (((network_link_L07_t) constraint_id)->state_current ==
339               SURF_NETWORK_LINK_OFF)) ||
340             ((((cpu_L07_t) constraint_id)->type ==
341               SURF_WORKSTATION_RESOURCE_CPU) &&
342              (((cpu_L07_t) constraint_id)->state_current ==
343               SURF_CPU_OFF))) {
344           DEBUG1("Action (%p) Failed!!", action);
345           action->generic_action.finish = surf_get_clock();
346           surf_action_change_state((surf_action_t) action,
347                                    SURF_ACTION_FAILED);
348           break;
349         }
350       }
351     }
352   }
353   return;
354 }
355
356 static void update_resource_state(void *id,
357                                   tmgr_trace_event_t event_type,
358                                   double value)
359 {
360   cpu_L07_t cpu = id;
361   network_link_L07_t nw_link = id;
362
363   if (nw_link->type == SURF_WORKSTATION_RESOURCE_LINK) {
364     DEBUG2("Updating link %s (%p)", nw_link->name, nw_link);
365     if (event_type == nw_link->bw_event) {
366       nw_link->bw_current = value;
367       lmm_update_constraint_bound(ptask_maxmin_system, nw_link->constraint,
368                                   nw_link->bw_current);
369     } else if (event_type == nw_link->lat_event) {
370       lmm_variable_t var = NULL;
371       surf_action_workstation_L07_t action = NULL;
372
373       nw_link->lat_current = value;
374       while (lmm_get_var_from_cnst
375              (ptask_maxmin_system, nw_link->constraint, &var)) {
376         
377
378         action = lmm_variable_id(var);
379         update_action_bound(action);
380       }
381
382     } else if (event_type == nw_link->state_event) {
383       if (value > 0)
384         nw_link->state_current = SURF_NETWORK_LINK_ON;
385       else
386         nw_link->state_current = SURF_NETWORK_LINK_OFF;
387     } else {
388       CRITICAL0("Unknown event ! \n");
389       xbt_abort();
390     }
391     return;
392   } else if (cpu->type == SURF_WORKSTATION_RESOURCE_CPU) {
393     DEBUG3("Updating cpu %s (%p) with value %g", cpu->name, cpu, value);
394     if (event_type == cpu->power_event) {
395       cpu->power_current = value;
396       lmm_update_constraint_bound(ptask_maxmin_system, cpu->constraint,
397                                   cpu->power_current);
398     } else if (event_type == cpu->state_event) {
399       if (value > 0)
400         cpu->state_current = SURF_CPU_ON;
401       else
402         cpu->state_current = SURF_CPU_OFF;
403     } else {
404       CRITICAL0("Unknown event ! \n");
405       xbt_abort();
406     }
407     return;
408   } else {
409     DIE_IMPOSSIBLE;
410   }
411   return;
412 }
413
414 static void finalize(void)
415 {
416   int i, j;
417
418   xbt_dict_free(&network_link_set);
419   xbt_dict_free(&workstation_set);
420   if (parallel_task_network_link_set != NULL) {
421     xbt_dict_free(&parallel_task_network_link_set);
422   }
423   xbt_swag_free(surf_workstation_model->common_public->states.
424                 ready_action_set);
425   xbt_swag_free(surf_workstation_model->common_public->states.
426                 running_action_set);
427   xbt_swag_free(surf_workstation_model->common_public->states.
428                 failed_action_set);
429   xbt_swag_free(surf_workstation_model->common_public->states.
430                 done_action_set);
431
432   free(surf_workstation_model->common_public);
433   free(surf_workstation_model->common_private);
434   free(surf_workstation_model->extension_public);
435
436   free(surf_workstation_model);
437   surf_workstation_model = NULL;
438
439   for (i = 0; i < nb_workstation; i++)
440     for (j = 0; j < nb_workstation; j++)
441       free(ROUTE(i, j).links);
442   free(routing_table);
443   routing_table = NULL;
444   nb_workstation = 0;
445
446   if (ptask_maxmin_system) {
447     lmm_system_free(ptask_maxmin_system);
448     ptask_maxmin_system = NULL;
449   }
450 }
451
452 /**************************************/
453 /******* Resource Private    **********/
454 /**************************************/
455
456 static e_surf_cpu_state_t resource_get_state(void *cpu)
457 {
458   return ((cpu_L07_t) cpu)->state_current;
459 }
460
461 static double get_speed(void *cpu, double load)
462 {
463   return load * (((cpu_L07_t) cpu)->power_scale);
464 }
465
466 static double get_available_speed(void *cpu)
467 {
468   return ((cpu_L07_t) cpu)->power_current;
469 }
470
471 static surf_action_t execute_parallel_task(int workstation_nb,
472                                            void **workstation_list,
473                                            double *computation_amount,
474                                            double *communication_amount,
475                                            double amount, double rate)
476 {
477   surf_action_workstation_L07_t action = NULL;
478   int i, j, k;
479   int nb_link = 0;
480   int nb_host = 0;
481   double latency = 0.0;
482
483   if (parallel_task_network_link_set == NULL) {
484     parallel_task_network_link_set =
485         xbt_dict_new_ext(workstation_nb * workstation_nb * 10);
486   }
487
488   /* Compute the number of affected resources... */
489   for (i = 0; i < workstation_nb; i++) {
490     for (j = 0; j < workstation_nb; j++) {
491       cpu_L07_t card_src = workstation_list[i];
492       cpu_L07_t card_dst = workstation_list[j];
493       int route_size = ROUTE(card_src->id, card_dst->id).size;
494       network_link_L07_t *route = ROUTE(card_src->id, card_dst->id).links;
495       double lat = 0.0;
496
497       if (communication_amount[i * workstation_nb + j] > 0)
498         for (k = 0; k < route_size; k++) {
499           lat += route[k]->lat_current;
500           xbt_dict_set(parallel_task_network_link_set, route[k]->name,
501                        route[k], NULL);
502         }
503       latency=MAX(latency,lat);
504     }
505   }
506
507   nb_link = xbt_dict_length(parallel_task_network_link_set);
508   xbt_dict_reset(parallel_task_network_link_set);
509
510   for (i = 0; i < workstation_nb; i++)
511     if (computation_amount[i] > 0)
512       nb_host++;
513
514   action = xbt_new0(s_surf_action_workstation_L07_t, 1);
515   DEBUG3("Creating a parallel task (%p) with %d cpus and %d links.",
516          action, workstation_nb, nb_link);
517   action->generic_action.using = 1;
518   action->generic_action.cost = amount;
519   action->generic_action.remains = amount;
520   action->generic_action.max_duration = NO_MAX_DURATION;
521   action->generic_action.start = surf_get_clock();
522   action->generic_action.finish = -1.0;
523   action->generic_action.model_type =
524       (surf_model_t) surf_workstation_model;
525   action->suspended = 0;        /* Should be useless because of the
526                                    calloc but it seems to help valgrind... */
527   action->workstation_nb = workstation_nb;
528   action->workstation_list = (cpu_L07_t *)workstation_list;
529   action->computation_amount = computation_amount;
530   action->communication_amount = communication_amount;
531   action->latency = latency;
532   action->generic_action.state_set =
533       surf_workstation_model->common_public->states.running_action_set;
534
535   xbt_swag_insert(action, action->generic_action.state_set);
536   action->rate = rate;
537
538   if (action->rate > 0)
539     action->variable =
540         lmm_variable_new(ptask_maxmin_system, action, 1.0, -1.0,
541                          workstation_nb + nb_link);
542   else
543     action->variable =
544         lmm_variable_new(ptask_maxmin_system, action, 1.0, action->rate,
545                          workstation_nb + nb_link);
546
547   if (action->latency > 0) 
548     lmm_update_variable_weight(ptask_maxmin_system,action->variable,0.0);
549
550   for (i = 0; i < workstation_nb; i++)
551     lmm_expand(ptask_maxmin_system,
552                ((cpu_L07_t) workstation_list[i])->constraint,
553                action->variable, computation_amount[i]);
554   
555   for (i = 0; i < workstation_nb; i++) {
556     for (j = 0; j < workstation_nb; j++) {
557       cpu_L07_t card_src = workstation_list[i];
558       cpu_L07_t card_dst = workstation_list[j];
559       int route_size = ROUTE(card_src->id, card_dst->id).size;
560       network_link_L07_t *route = ROUTE(card_src->id, card_dst->id).links;
561       
562       if (communication_amount[i * workstation_nb + j] == 0.0) 
563         continue;
564       for (k = 0; k < route_size; k++) {
565           lmm_expand_add(ptask_maxmin_system, route[k]->constraint,
566                          action->variable,
567                          communication_amount[i * workstation_nb + j]);
568       }
569     }
570   }
571
572   if (nb_link + nb_host == 0) {
573     action->generic_action.cost = 1.0;
574     action->generic_action.remains = 0.0;
575   }
576
577   return (surf_action_t) action;
578 }
579
580 static surf_action_t execute(void *cpu, double size)
581 {
582   void **workstation_list = xbt_new0(void *, 1);
583   double *computation_amount = xbt_new0(double, 1);
584   double *communication_amount = xbt_new0(double, 1);
585
586   workstation_list[0] = cpu;
587   communication_amount[0] = 0.0;
588   computation_amount[0] = size;
589
590   return execute_parallel_task(1, workstation_list, communication_amount, 
591                                communication_amount, 1, -1);
592 }
593
594 static surf_action_t communicate(void *src, void *dst, double size,
595                                  double rate)
596 {
597   void **workstation_list = xbt_new0(void *, 2);
598   double *computation_amount = xbt_new0(double, 2);
599   double *communication_amount = xbt_new0(double, 4);
600   surf_action_t res = NULL;
601
602   workstation_list[0] = src;
603   workstation_list[1] = dst;
604   communication_amount[1] = size;
605
606   res = execute_parallel_task(2, workstation_list,
607                               computation_amount, communication_amount,
608                               1, rate);
609
610   return res;
611 }
612
613 static surf_action_t action_sleep(void *cpu, double duration)
614 {
615   surf_action_workstation_L07_t action = NULL;
616
617   XBT_IN2("(%s,%g)", ((cpu_L07_t) cpu)->name, duration);
618
619   action = (surf_action_workstation_L07_t) execute(cpu, 1.0);
620   action->generic_action.max_duration = duration;
621   action->suspended = 2;
622   lmm_update_variable_weight(ptask_maxmin_system, action->variable, 0.0);
623
624   XBT_OUT;
625   return (surf_action_t) action;
626 }
627
628 /* returns an array of network_link_L07_t */
629 static const void **get_route(void *src, void *dst)
630 {
631   cpu_L07_t card_src = src;
632   cpu_L07_t card_dst = dst;
633   route_L07_t route = &(ROUTE(card_src->id, card_dst->id));
634
635   return (const void **) route->links;
636 }
637
638 static int get_route_size(void *src, void *dst)
639 {
640   cpu_L07_t card_src = src;
641   cpu_L07_t card_dst = dst;
642   route_L07_t route = &(ROUTE(card_src->id, card_dst->id));
643   return route->size;
644 }
645
646 static const char *get_link_name(const void *link)
647 {
648   return ((network_link_L07_t) link)->name;
649 }
650
651 static double get_link_bandwidth(const void *link)
652 {
653   return ((network_link_L07_t) link)->bw_current;
654 }
655
656 static double get_link_latency(const void *link)
657 {
658   return ((network_link_L07_t) link)->lat_current;
659 }
660
661 /**************************************/
662 /*** Resource Creation & Destruction **/
663 /**************************************/
664
665 static void cpu_free(void *cpu)
666 {
667   free(((cpu_L07_t) cpu)->name);
668   free(cpu);
669 }
670
671 static cpu_L07_t cpu_new(const char *name, double power_scale,
672                          double power_initial,
673                          tmgr_trace_t power_trace,
674                          e_surf_cpu_state_t state_initial,
675                          tmgr_trace_t state_trace)
676 {
677   cpu_L07_t cpu = xbt_new0(s_cpu_L07_t, 1);
678
679   cpu->model = (surf_model_t) surf_workstation_model;
680   cpu->type = SURF_WORKSTATION_RESOURCE_CPU;
681   cpu->name = xbt_strdup(name);
682   cpu->id = nb_workstation++;
683
684   cpu->power_scale = power_scale;
685   xbt_assert0(cpu->power_scale > 0, "Power has to be >0");
686
687   cpu->power_current = power_initial;
688   if (power_trace)
689     cpu->power_event =
690         tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
691
692   cpu->state_current = state_initial;
693   if (state_trace)
694     cpu->state_event =
695         tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
696
697   cpu->constraint =
698       lmm_constraint_new(ptask_maxmin_system, cpu,
699                          cpu->power_current * cpu->power_scale);
700
701   xbt_dict_set(workstation_set, name, cpu, cpu_free);
702
703   return cpu;
704 }
705
706 static void parse_cpu(void)
707 {
708   double power_scale = 0.0;
709   double power_initial = 0.0;
710   tmgr_trace_t power_trace = NULL;
711   e_surf_cpu_state_t state_initial = SURF_CPU_OFF;
712   tmgr_trace_t state_trace = NULL;
713
714   surf_parse_get_double(&power_scale, A_surfxml_cpu_power);
715   surf_parse_get_double(&power_initial, A_surfxml_cpu_availability);
716   surf_parse_get_trace(&power_trace, A_surfxml_cpu_availability_file);
717
718   xbt_assert0((A_surfxml_cpu_state == A_surfxml_cpu_state_ON) ||
719               (A_surfxml_cpu_state == A_surfxml_cpu_state_OFF),
720               "Invalid state");
721   if (A_surfxml_cpu_state == A_surfxml_cpu_state_ON)
722     state_initial = SURF_CPU_ON;
723   if (A_surfxml_cpu_state == A_surfxml_cpu_state_OFF)
724     state_initial = SURF_CPU_OFF;
725   surf_parse_get_trace(&state_trace, A_surfxml_cpu_state_file);
726
727   cpu_new(A_surfxml_cpu_name, power_scale, power_initial, power_trace,
728           state_initial, state_trace);
729 }
730
731 static void create_routing_table(void)
732 {
733   routing_table = xbt_new0(s_route_L07_t, nb_workstation * nb_workstation);
734 }
735
736 static void network_link_free(void *nw_link)
737 {
738   free(((network_link_L07_t) nw_link)->name);
739   free(nw_link);
740 }
741
742 static network_link_L07_t network_link_new(char *name,
743                                            double bw_initial,
744                                            tmgr_trace_t bw_trace,
745                                            double lat_initial,
746                                            tmgr_trace_t lat_trace,
747                                            e_surf_network_link_state_t
748                                            state_initial,
749                                            tmgr_trace_t state_trace,
750                                            e_surf_network_link_sharing_policy_t
751                                            policy)
752 {
753   network_link_L07_t nw_link = xbt_new0(s_network_link_L07_t, 1);
754
755
756   nw_link->model = (surf_model_t) surf_workstation_model;
757   nw_link->type = SURF_WORKSTATION_RESOURCE_LINK;
758   nw_link->name = name;
759   nw_link->bw_current = bw_initial;
760   if (bw_trace)
761     nw_link->bw_event =
762         tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link);
763   nw_link->state_current = state_initial;
764   nw_link->lat_current = lat_initial;
765   if (lat_trace)
766     nw_link->lat_event =
767         tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link);
768   if (state_trace)
769     nw_link->state_event =
770         tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link);
771
772   nw_link->constraint =
773       lmm_constraint_new(ptask_maxmin_system, nw_link,
774                          nw_link->bw_current);
775
776   if (policy == SURF_NETWORK_LINK_FATPIPE)
777     lmm_constraint_shared(nw_link->constraint);
778
779   xbt_dict_set(network_link_set, name, nw_link, network_link_free);
780
781   return nw_link;
782 }
783
784 static void parse_network_link(void)
785 {
786   char *name;
787   double bw_initial;
788   tmgr_trace_t bw_trace;
789   double lat_initial;
790   tmgr_trace_t lat_trace;
791   e_surf_network_link_state_t state_initial = SURF_NETWORK_LINK_ON;
792   e_surf_network_link_sharing_policy_t policy_initial =
793       SURF_NETWORK_LINK_SHARED;
794   tmgr_trace_t state_trace;
795
796   name = xbt_strdup(A_surfxml_network_link_name);
797   surf_parse_get_double(&bw_initial, A_surfxml_network_link_bandwidth);
798   surf_parse_get_trace(&bw_trace, A_surfxml_network_link_bandwidth_file);
799   surf_parse_get_double(&lat_initial, A_surfxml_network_link_latency);
800   surf_parse_get_trace(&lat_trace, A_surfxml_network_link_latency_file);
801
802   xbt_assert0((A_surfxml_network_link_state ==
803                A_surfxml_network_link_state_ON)
804               || (A_surfxml_network_link_state ==
805                   A_surfxml_network_link_state_OFF), "Invalid state");
806   if (A_surfxml_network_link_state == A_surfxml_network_link_state_ON)
807     state_initial = SURF_NETWORK_LINK_ON;
808   else if (A_surfxml_network_link_state ==
809            A_surfxml_network_link_state_OFF)
810     state_initial = SURF_NETWORK_LINK_OFF;
811
812   if (A_surfxml_network_link_sharing_policy ==
813       A_surfxml_network_link_sharing_policy_SHARED)
814     policy_initial = SURF_NETWORK_LINK_SHARED;
815   else if (A_surfxml_network_link_sharing_policy ==
816            A_surfxml_network_link_sharing_policy_FATPIPE)
817     policy_initial = SURF_NETWORK_LINK_FATPIPE;
818
819   surf_parse_get_trace(&state_trace, A_surfxml_network_link_state_file);
820
821   network_link_new(name, bw_initial, bw_trace, lat_initial, lat_trace,
822                    state_initial, state_trace, policy_initial);
823 }
824
825 static void route_new(int src_id, int dst_id,
826                       network_link_L07_t * link_list, int nb_link)
827 {
828   route_L07_t route = &(ROUTE(src_id, dst_id));
829
830   route->size = nb_link;
831   route->links = link_list =
832       xbt_realloc(link_list, sizeof(network_link_L07_t) * nb_link);
833 }
834
835 static int nb_link;
836 static int link_list_capacity;
837 static network_link_L07_t *link_list = NULL;
838 static int src_id = -1;
839 static int dst_id = -1;
840
841 static void parse_route_set_endpoints(void)
842 {
843   cpu_L07_t cpu_tmp = NULL;
844
845   cpu_tmp = (cpu_L07_t) name_service(A_surfxml_route_src);
846   xbt_assert1(cpu_tmp, "Invalid cpu %s", A_surfxml_route_src);
847   if (cpu_tmp != NULL)
848     src_id = cpu_tmp->id;
849
850   cpu_tmp = (cpu_L07_t) name_service(A_surfxml_route_dst);
851   xbt_assert1(cpu_tmp, "Invalid cpu %s", A_surfxml_route_dst);
852   if (cpu_tmp != NULL)
853     dst_id = cpu_tmp->id;
854
855   nb_link = 0;
856   link_list_capacity = 1;
857   link_list = xbt_new(network_link_L07_t, link_list_capacity);
858 }
859
860 static void parse_route_elem(void)
861 {
862   xbt_ex_t e;
863   if (nb_link == link_list_capacity) {
864     link_list_capacity *= 2;
865     link_list =
866         xbt_realloc(link_list,
867                     (link_list_capacity) * sizeof(network_link_L07_t));
868   }
869   TRY {
870     link_list[nb_link++] =
871         xbt_dict_get(network_link_set, A_surfxml_route_element_name);
872   }
873   CATCH(e) {
874     RETHROW1("Link %s not found (dict raised this exception: %s)",
875              A_surfxml_route_element_name);
876   }
877 }
878
879 static void parse_route_set_route(void)
880 {
881   if (src_id != -1 && dst_id != -1)
882     route_new(src_id, dst_id, link_list, nb_link);
883 }
884
885 static void parse_file(const char *file)
886 {
887   int i;
888
889   /* Figuring out the cpus */
890   surf_parse_reset_parser();
891   ETag_surfxml_cpu_fun = parse_cpu;
892   surf_parse_open(file);
893   xbt_assert1((!surf_parse()), "Parse error in %s", file);
894   surf_parse_close();
895
896   create_routing_table();
897
898   /* Figuring out the network links */
899   surf_parse_reset_parser();
900   ETag_surfxml_network_link_fun = parse_network_link;
901   surf_parse_open(file);
902   xbt_assert1((!surf_parse()), "Parse error in %s", file);
903   surf_parse_close();
904
905   /* Building the routes */
906   surf_parse_reset_parser();
907   STag_surfxml_route_fun = parse_route_set_endpoints;
908   ETag_surfxml_route_element_fun = parse_route_elem;
909   ETag_surfxml_route_fun = parse_route_set_route;
910   surf_parse_open(file);
911   xbt_assert1((!surf_parse()), "Parse error in %s", file);
912   surf_parse_close();
913
914   /* Adding loopback if needed */
915   for (i = 0; i < nb_workstation; i++)
916     if (!ROUTE(i, i).size) {
917       if (!loopback)
918         loopback = network_link_new(xbt_strdup("__MSG_loopback__"),
919                                     498000000, NULL, 0.000015, NULL,
920                                     SURF_NETWORK_LINK_ON, NULL,
921                                     SURF_NETWORK_LINK_FATPIPE);
922
923       ROUTE(i, i).size = 1;
924       ROUTE(i, i).links = xbt_new0(network_link_L07_t, 1);
925       ROUTE(i, i).links[0] = loopback;
926     }
927 }
928
929 /**************************************/
930 /********* Module  creation ***********/
931 /**************************************/
932
933 static void model_init_internal(void)
934 {
935   s_surf_action_t action;
936
937   surf_workstation_model = xbt_new0(s_surf_workstation_model_t, 1);
938
939   surf_workstation_model->common_private =
940       xbt_new0(s_surf_model_private_t, 1);
941   surf_workstation_model->common_public =
942       xbt_new0(s_surf_model_public_t, 1);
943   surf_workstation_model->extension_public =
944       xbt_new0(s_surf_workstation_model_extension_public_t, 1);
945
946   surf_workstation_model->common_public->states.ready_action_set =
947       xbt_swag_new(xbt_swag_offset(action, state_hookup));
948   surf_workstation_model->common_public->states.running_action_set =
949       xbt_swag_new(xbt_swag_offset(action, state_hookup));
950   surf_workstation_model->common_public->states.failed_action_set =
951       xbt_swag_new(xbt_swag_offset(action, state_hookup));
952   surf_workstation_model->common_public->states.done_action_set =
953       xbt_swag_new(xbt_swag_offset(action, state_hookup));
954
955   surf_workstation_model->common_public->name_service = name_service;
956   surf_workstation_model->common_public->get_resource_name =
957       get_resource_name;
958   surf_workstation_model->common_public->action_get_state =
959       surf_action_get_state;
960   surf_workstation_model->common_public->action_get_start_time =
961       surf_action_get_start_time;
962   surf_workstation_model->common_public->action_get_finish_time =
963       surf_action_get_finish_time;
964   surf_workstation_model->common_public->action_use = action_use;
965   surf_workstation_model->common_public->action_free = action_free;
966   surf_workstation_model->common_public->action_cancel = action_cancel;
967   surf_workstation_model->common_public->action_recycle =
968       action_recycle;
969   surf_workstation_model->common_public->action_change_state =
970       surf_action_change_state;
971   surf_workstation_model->common_public->action_set_data =
972       surf_action_set_data;
973   surf_workstation_model->common_public->suspend = action_suspend;
974   surf_workstation_model->common_public->resume = action_resume;
975   surf_workstation_model->common_public->is_suspended =
976       action_is_suspended;
977   surf_workstation_model->common_public->set_max_duration =
978       action_set_max_duration;
979   surf_workstation_model->common_public->set_priority =
980       action_set_priority;
981   surf_workstation_model->common_public->name = "Workstation ptask_L07";
982
983   surf_workstation_model->common_private->resource_used = resource_used;
984   surf_workstation_model->common_private->share_resources =
985       share_resources;
986   surf_workstation_model->common_private->update_actions_state =
987       update_actions_state;
988   surf_workstation_model->common_private->update_resource_state =
989       update_resource_state;
990   surf_workstation_model->common_private->finalize = finalize;
991
992   surf_workstation_model->extension_public->execute = execute;
993   surf_workstation_model->extension_public->sleep = action_sleep;
994   surf_workstation_model->extension_public->get_state =
995       resource_get_state;
996   surf_workstation_model->extension_public->get_speed = get_speed;
997   surf_workstation_model->extension_public->get_available_speed =
998       get_available_speed;
999   surf_workstation_model->extension_public->communicate = communicate;
1000   surf_workstation_model->extension_public->execute_parallel_task =
1001       execute_parallel_task;
1002   surf_workstation_model->extension_public->get_route = get_route;
1003   surf_workstation_model->extension_public->get_route_size =
1004       get_route_size;
1005   surf_workstation_model->extension_public->get_link_name =
1006       get_link_name;
1007   surf_workstation_model->extension_public->get_link_bandwidth =
1008       get_link_bandwidth;
1009   surf_workstation_model->extension_public->get_link_latency =
1010       get_link_latency;
1011
1012   workstation_set = xbt_dict_new();
1013   network_link_set = xbt_dict_new();
1014
1015   if (!ptask_maxmin_system)
1016     ptask_maxmin_system = lmm_system_new();
1017 }
1018
1019 /**************************************/
1020 /*************** Generic **************/
1021 /**************************************/
1022 void surf_workstation_model_init_ptask_L07(const char *filename)
1023 {
1024   xbt_assert0(!surf_cpu_model, "CPU model type already defined");
1025   xbt_assert0(!surf_network_model,
1026               "network model type already defined");
1027   model_init_internal();
1028   parse_file(filename);
1029   WARN0("This model does not take latency into account.");
1030
1031   update_model_description(surf_workstation_model_description,
1032                               surf_workstation_model_description_size,
1033                               "ptask_L07",
1034                               (surf_model_t) surf_workstation_model);
1035   xbt_dynar_push(model_list, &surf_workstation_model);
1036 }