Logo AND Algorithmique Numérique Distribuée

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