Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
6508e38abd5df701d510c88868bc9f08273e2340
[simgrid.git] / src / surf / surf.cpp
1 #include "surf.hpp"
2 #include "cpu.hpp"
3 #include "simix/smx_host_private.h"
4
5 XBT_LOG_NEW_CATEGORY(surfpp, "All SURF categories");
6 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surfpp_kernel, surfpp,
7                                 "Logging specific to SURF (kernel)");
8
9 /*********
10  * Utils *
11  *********/
12
13 double NOWW = 0;
14
15 XBT_INLINE double surf_get_clock(void)
16 {
17   return NOWW;
18 }
19
20 /* This function is a pimple that we ought to fix. But it won't be easy.
21  *
22  * The surf_solve() function does properly return the set of actions that changed.
23  * Instead, each model change a global data, and then the caller of surf_solve must
24  * pick into these sets of action_failed and action_done.
25  *
26  * This was not clean but ok as long as we didn't had to restart the processes when the resource comes back up.
27  * We worked by putting sentinel actions on every resources we are interested in,
28  * so that surf informs us if/when the corresponding resource fails.
29  *
30  * But this does not work to get Simix informed of when a resource comes back up, and this is where this pimple comes.
31  * We have a set of resources that are currently down and for which simix needs to know when it comes back up.
32  * And the current function is called *at every simulation step* to sweep over that set, searching for a resource
33  * that was turned back up in the meanwhile. This is UGLY and slow.
34  *
35  * The proper solution would be to not rely on globals for the action_failed and action_done swags.
36  * They must be passed as parameter by the caller (the handling of these actions in simix may let you
37  * think that these two sets can be merged, but their handling in SimDag induce the contrary unless this
38  * simdag code can check by itself whether the action is done of failed -- seems very doable, but yet more
39  * cleanup to do).
40  *
41  * Once surf_solve() is passed the set of actions that changed, you want to add a new set of resources back up
42  * as parameter to this function. You also want to add a boolean field "restart_watched" to each resource, and
43  * make sure that whenever a resource with this field enabled comes back up, it's added to that set so that Simix
44  * sees it and react accordingly. This would kill that need for surf to call simix.
45  *
46  */
47
48 static void remove_watched_host(void *key)
49 {
50   xbt_dict_remove(watched_hosts_lib, *(char**)key);
51 }
52
53 /*TODO: keepit void surf_watched_hosts(void)
54 {
55   char *key;
56   void *_host;
57   smx_host_t host;
58   xbt_dict_cursor_t cursor;
59   xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL);
60
61   XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib");
62   xbt_dict_foreach(watched_hosts_lib,cursor,key,_host)
63   {
64     host = (smx_host_t) host;
65     if(SIMIX_host_get_state(host) == SURF_RESOURCE_ON){
66       XBT_INFO("Restart processes on host: %s",SIMIX_host_get_name(host));
67       SIMIX_host_autorestart(host);
68       xbt_dynar_push_as(hosts, char*, key);
69     }
70     else
71       XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key);
72   }
73   xbt_dynar_map(hosts, remove_watched_host);
74   xbt_dynar_free(&hosts);
75 }*/
76
77 /*********
78  * Model *
79  *********/
80
81 double Model::shareResourcesLazy(double now)
82 {
83   ActionLmmPtr action = NULL;
84   double min = -1;
85   double value;
86
87   XBT_DEBUG
88       ("Before share resources, the size of modified actions set is %d",
89        xbt_swag_size(p_modifiedSet));
90
91   lmm_solve(p_maxminSystem);
92
93   XBT_DEBUG
94       ("After share resources, The size of modified actions set is %d",
95        xbt_swag_size(p_modifiedSet));
96
97   while((action = (ActionLmmPtr) xbt_swag_extract(p_modifiedSet))) {
98     int max_dur_flag = 0;
99
100     if (action->p_stateSet != p_runningActionSet)
101       continue;
102
103     /* bogus priority, skip it */
104     if (action->m_priority <= 0)
105       continue;
106
107     action->updateRemainingLazy(now);
108
109     min = -1;
110     value = lmm_variable_getvalue(action->p_variable);
111     if (value > 0) {
112       if (action->m_remains > 0) {
113         value = action->m_remains / value;
114         min = now + value;
115       } else {
116         value = 0.0;
117         min = now;
118       }
119     }
120
121     if ((action->m_maxDuration != NO_MAX_DURATION)
122         && (min == -1
123             || action->m_start +
124             action->m_maxDuration < min)) {
125       min = action->m_start +
126           action->m_maxDuration;
127       max_dur_flag = 1;
128     }
129
130     XBT_DEBUG("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
131         action->m_start, now + value,
132         action->m_maxDuration);
133
134     if (min != -1) {
135       action->heapRemove(p_actionHeap);
136       action->heapInsert(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
137       XBT_DEBUG("Insert at heap action(%p) min %lf now %lf", action, min,
138                 now);
139     } else DIE_IMPOSSIBLE;
140   }
141
142   //hereafter must have already the min value for this resource model
143   if (xbt_heap_size(p_actionHeap) > 0)
144     min = xbt_heap_maxkey(p_actionHeap) - now;
145   else
146     min = -1;
147
148   XBT_DEBUG("The minimum with the HEAP %lf", min);
149
150   return min;
151 }
152
153 double Model::shareResourcesFull(xbt_swag_t running_actions,
154                           size_t offset,
155                           lmm_system_t sys,
156                           void (*solve) (lmm_system_t))
157 {
158   void *_action = NULL;
159   ActionPtr action = NULL;
160   double min = -1;
161   double value = -1;
162 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
163
164   solve(sys);
165
166   xbt_swag_foreach(_action, running_actions) {
167     action = (ActionPtr)_action;
168     value = lmm_variable_getvalue(VARIABLE(action));
169     if ((value > 0) || (action->m_maxDuration >= 0))
170       break;
171   }
172
173   if (!action)
174     return -1.0;
175
176   if (value > 0) {
177     if (action->m_remains > 0)
178       min = action->m_remains / value;
179     else
180       min = 0.0;
181     if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min))
182       min = action->m_maxDuration;
183   } else
184     min = action->m_maxDuration;
185
186
187   for (action = (ActionPtr) xbt_swag_getNext(action, running_actions->offset);
188        action;
189        action = (ActionPtr) xbt_swag_getNext(action, running_actions->offset)) {
190     value = lmm_variable_getvalue(VARIABLE(action));
191     if (value > 0) {
192       if (action->m_remains > 0)
193         value = action->m_remains / value;
194       else
195         value = 0.0;
196       if (value < min) {
197         min = value;
198         XBT_DEBUG("Updating min (value) with %p: %f", action, min);
199       }
200     }
201     if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min)) {
202       min = action->m_maxDuration;
203       XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
204     }
205   }
206   XBT_DEBUG("min value : %f", min);
207
208 #undef VARIABLE
209   return min;
210 }
211
212 void Model::gapRemove(ActionLmmPtr action) {}
213
214
215 void Model::updateActionsStateLazy(double now, double delta)
216 {
217
218 }
219
220 void Model::updateActionsStateFull(double now, double delta)
221 {
222
223 }
224
225
226 void Model::addTurnedOnCallback(ResourceCallback rc)
227 {
228   m_resOnCB = rc;
229 }
230
231 void Model::notifyResourceTurnedOn(ResourcePtr r)
232 {
233   m_resOnCB(r);
234 }
235
236 void Model::addTurnedOffCallback(ResourceCallback rc)
237 {
238   m_resOffCB = rc;
239 }
240
241 void Model::notifyResourceTurnedOff(ResourcePtr r)
242 {
243   m_resOffCB(r);
244 }
245
246 void Model::addActionCancelCallback(ActionCallback ac)
247 {
248   m_actCancelCB = ac;
249 }
250
251 void Model::notifyActionCancel(ActionPtr a)
252 {
253   m_actCancelCB(a);
254 }
255
256 void Model::addActionResumeCallback(ActionCallback ac)
257 {
258   m_actResumeCB = ac;
259 }
260
261 void Model::notifyActionResume(ActionPtr a)
262 {
263   m_actResumeCB(a);
264 }
265
266 void Model::addActionSuspendCallback(ActionCallback ac)
267 {
268   m_actSuspendCB = ac;
269 }
270
271 void Model::notifyActionSuspend(ActionPtr a)
272 {
273   m_actSuspendCB(a);
274 }
275
276
277 /************
278  * Resource *
279  ************/
280
281 string Resource::getName() {
282   return m_name;
283 }
284
285 e_surf_resource_state_t Resource::getState()
286 {
287   return m_stateCurrent;
288 }
289
290 bool Resource::isOn()
291 {
292   return m_running;
293 }
294
295 void Resource::turnOn()
296 {
297   if (!m_running) {
298     m_running = true;
299     p_model->notifyResourceTurnedOn(this);
300   }
301 }
302
303 void Resource::turnOff()
304 {
305   if (m_running) {
306     m_running = false;
307     p_model->notifyResourceTurnedOff(this);
308   }
309 }
310
311 /**********
312  * Action *
313  **********/
314 /* added to manage the communication action's heap */
315 void surf_action_lmm_update_index_heap(void *action, int i) {
316   ((ActionLmmPtr)action)->updateIndexHeap(i);
317 }
318
319 void ActionLmm::updateIndexHeap(int i)
320 {
321   m_indexHeap = i;
322 }
323
324 /*TODO/const char *surf_action_state_names[6] = {
325   "SURF_ACTION_READY",
326   "SURF_ACTION_RUNNING",
327   "SURF_ACTION_FAILED",
328   "SURF_ACTION_DONE",
329   "SURF_ACTION_TO_FREE",
330   "SURF_ACTION_NOT_IN_THE_SYSTEM"
331 };*/
332
333 e_surf_action_state_t Action::getState()
334 {
335   if (p_stateSet ==  p_model->p_readyActionSet)
336     return SURF_ACTION_READY;
337   if (p_stateSet ==  p_model->p_runningActionSet)
338     return SURF_ACTION_RUNNING;
339   if (p_stateSet ==  p_model->p_failedActionSet)
340     return SURF_ACTION_FAILED;
341   if (p_stateSet ==  p_model->p_doneActionSet)
342     return SURF_ACTION_DONE;
343   return SURF_ACTION_NOT_IN_THE_SYSTEM;
344 }
345
346 void Action::setState(e_surf_action_state_t state)
347 {
348   //surf_action_state_t action_state = &(action->model_type->states);
349   XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
350   xbt_swag_remove(this, p_stateSet);
351
352   if (state == SURF_ACTION_READY)
353     p_stateSet = p_model->p_readyActionSet;
354   else if (state == SURF_ACTION_RUNNING)
355     p_stateSet = p_model->p_runningActionSet;
356   else if (state == SURF_ACTION_FAILED)
357     p_stateSet = p_model->p_failedActionSet;
358   else if (state == SURF_ACTION_DONE)
359     p_stateSet = p_model->p_doneActionSet;
360   else
361     p_stateSet = NULL;
362
363   if (p_stateSet)
364     xbt_swag_insert(this, p_stateSet);
365   XBT_OUT();
366 }
367
368 double Action::getStartTime()
369 {
370   return m_start;
371 }
372
373 double Action::getFinishTime()
374 {
375   /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
376   return m_remains == 0 ? m_finish : -1;
377 }
378
379 void Action::setData(void* data)
380 {
381   p_data = data;
382 }
383
384 #ifdef HAVE_TRACING
385 void Action::setCategory(const char *category)
386 {
387   XBT_IN("(%p,%s)", this, category);
388   p_category = xbt_strdup(category);
389   XBT_OUT();
390 }
391 #endif
392
393 /* insert action on heap using a given key and a hat (heap_action_type)
394  * a hat can be of three types for communications:
395  *
396  * NORMAL = this is a normal heap entry stating the date to finish transmitting
397  * LATENCY = this is a heap entry to warn us when the latency is payed
398  * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
399  */
400 void ActionLmm::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
401 {
402   m_hat = hat;
403   xbt_heap_push(heap, this, key);
404 }
405
406 void ActionLmm::heapRemove(xbt_heap_t heap)
407 {
408   m_hat = NOTSET;
409   if (m_indexHeap >= 0) {
410     xbt_heap_remove(heap, m_indexHeap);
411   }
412 }
413
414 double ActionLmm::getRemains()
415 {
416   XBT_IN("(%p)", this);
417   /* update remains before return it */
418   if (p_updateMechanism == UM_LAZY)      /* update remains before return it */
419     updateRemainingLazy(surf_get_clock());
420   XBT_OUT();
421   return m_remains;
422 }
423
424 /*void Action::cancel()
425 {
426   p_model->notifyActionCancel(this);
427 }
428
429 void Action::suspend()
430 {
431   p_model->notifyActionSuspend(this);
432 }
433
434 void Action::resume()
435 {
436   p_model->notifyActionResume(this);
437 }
438
439 bool Action::isSuspended()
440 {
441   return false;
442 }*/
443