Logo AND Algorithmique Numérique Distribuée

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