Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ce3ba8af366253184781a14b809dd1771cac44b3
[simgrid.git] / src / simix / smx_action.c
1 /* Copyright (c) 2007, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "private.h"
8 #include "xbt/log.h"
9 #include "xbt/ex.h"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_action, simix,
12                                 "Logging specific to SIMIX (action)");
13
14 /************************************* Actions *********************************/
15 /** \brief Creates a new SIMIX action to communicate two hosts.
16  *
17  *      This function creates a SURF action and allocates the data necessary to create the SIMIX action. It can raise a network_error exception if the host is unavailable.
18  *      \param sender SIMIX host sender
19  *      \param receiver SIMIX host receiver
20  *      \param name Action name
21  *      \param size Communication size (in bytes)
22  *      \param rate Communication rate between hosts.
23  *      \return A new SIMIX action
24  * */
25 smx_action_t SIMIX_action_communicate(smx_host_t sender,
26                                       smx_host_t receiver, const char *name,
27                                       double size, double rate)
28 {
29   smx_action_t act;
30
31   /* check if the host is active */
32   if (surf_workstation_model->extension.workstation.get_state(sender->host) !=
33       SURF_RESOURCE_ON) {
34     THROW1(network_error, 0, "Host %s failed, you cannot call this function",
35            sender->name);
36   }
37   if (surf_workstation_model->extension.workstation.
38       get_state(receiver->host) != SURF_RESOURCE_ON) {
39     THROW1(network_error, 0, "Host %s failed, you cannot call this function",
40            receiver->name);
41   }
42
43   /* alloc structures */
44   act = xbt_new0(s_smx_action_t, 1);
45   act->cond_list = xbt_fifo_new();
46   act->sem_list = xbt_fifo_new();
47
48   /* initialize them */
49   act->name = xbt_strdup(name);
50   act->source = sender;
51 #ifdef HAVE_TRACING
52   act->category = NULL;
53 #endif
54
55   act->surf_action =
56     surf_workstation_model->extension.workstation.communicate(sender->host,
57                                                               receiver->host,
58                                                               size, rate);
59   surf_workstation_model->action_data_set(act->surf_action, act);
60
61   DEBUG1("Create communicate action %p", act);
62   return act;
63 }
64
65 /** \brief Creates a new SIMIX action to execute an action.
66  *
67  *      This function creates a SURF action and allocates the data necessary to create the SIMIX action. It can raise a host_error exception if the host crashed.
68  *      \param host SIMIX host where the action will be executed
69  *      \param name Action name
70  *      \param amount Task amount (in bytes)
71  *      \return A new SIMIX action
72  * */
73 smx_action_t SIMIX_action_execute(smx_host_t host, const char *name,
74                                   double amount)
75 {
76   smx_action_t act;
77
78   /* check if the host is active */
79   if (surf_workstation_model->extension.workstation.get_state(host->host) !=
80       SURF_RESOURCE_ON) {
81     THROW1(host_error, 0, "Host %s failed, you cannot call this function",
82            host->name);
83   }
84
85   /* alloc structures */
86   act = xbt_new0(s_smx_action_t, 1);
87   act->cond_list = xbt_fifo_new();
88   act->sem_list = xbt_fifo_new();
89
90   /* initialize them */
91   act->source = host;
92   act->name = xbt_strdup(name);
93 #ifdef HAVE_TRACING
94   act->category = NULL;
95 #endif
96
97   /* set communication */
98   act->surf_action =
99     surf_workstation_model->extension.workstation.execute(host->host, amount);
100
101   surf_workstation_model->action_data_set(act->surf_action, act);
102
103   DEBUG1("Create execute action %p", act);
104 #ifdef HAVE_TRACING
105   TRACE_smx_action_execute (act);
106 #endif
107   return act;
108 }
109
110 /** \brief Creates a new sleep SIMIX action.
111  *
112  * This function creates a SURF action and allocates the data necessary
113  * to create the SIMIX action. It can raise a host_error exception if the
114  * host crashed. The default SIMIX name of the action is "sleep".
115  *
116  *      \param host SIMIX host where the sleep will run.
117  *      \param duration Time duration of the sleep.
118  *      \return A new SIMIX action
119  * */
120 smx_action_t SIMIX_action_sleep(smx_host_t host, double duration)
121 {
122   char name[] = "sleep";
123   smx_action_t act;
124
125   /* check if the host is active */
126   if (surf_workstation_model->extension.workstation.get_state(host->host) !=
127       SURF_RESOURCE_ON) {
128     THROW1(host_error, 0, "Host %s failed, you cannot call this function",
129            host->name);
130   }
131
132   /* alloc structures */
133   act = xbt_new0(s_smx_action_t, 1);
134   act->cond_list = xbt_fifo_new();
135   act->sem_list = xbt_fifo_new();
136
137   /* initialize them */
138   act->source = host;
139   act->name = xbt_strdup(name);
140 #ifdef HAVE_TRACING
141   act->category = NULL;
142 #endif
143
144   act->surf_action =
145     surf_workstation_model->extension.workstation.sleep(host->host, duration);
146
147   surf_workstation_model->action_data_set(act->surf_action, act);
148
149   DEBUG1("Create sleep action %p", act);
150   return act;
151 }
152
153 /**
154  *      \brief Cancels an action.
155  *
156  *      This functions stops the execution of an action. It calls a surf functions.
157  *      \param action The SIMIX action
158  */
159 XBT_INLINE void SIMIX_action_cancel(smx_action_t action)
160 {
161   xbt_assert0((action != NULL), "Invalid parameter");
162
163   DEBUG1("Cancel action %p", action);
164   if (action->surf_action) {
165     surf_workstation_model->action_cancel(action->surf_action);
166   }
167   return;
168 }
169
170 /**
171  *      \brief Changes the action's priority
172  *
173  *      This functions changes the priority only. It calls a surf functions.
174  *      \param action The SIMIX action
175  *      \param priority The new priority
176  */
177 XBT_INLINE void SIMIX_action_set_priority(smx_action_t action, double priority)
178 {
179   xbt_assert0((action != NULL), "Invalid parameter");
180
181   surf_workstation_model->set_priority(action->surf_action, priority);
182   return;
183 }
184
185 /**
186  *      \brief Resumes the execution of an action.
187  *
188  *  This functions restarts the execution of an action. It just calls the right SURF function.
189  *  \param action The SIMIX action
190  *  \param priority The new priority
191  */
192 XBT_INLINE void SIMIX_action_resume(smx_action_t action)
193 {
194   xbt_assert0((action != NULL), "Invalid parameter");
195
196   surf_workstation_model->resume(action->surf_action);
197   return;
198 }
199
200 /**
201  *  \brief Suspends the execution of an action.
202  *
203  *  This functions suspends the execution of an action. It just calls the right SURF function.
204  *  \param action The SIMIX action
205  *  \param priority The new priority
206  */
207 XBT_INLINE void SIMIX_action_suspend(smx_action_t action)
208 {
209   xbt_assert0((action != NULL), "Invalid parameter");
210
211   surf_workstation_model->suspend(action->surf_action);
212   return;
213 }
214
215 /**
216  *      \brief Destroys an action
217  *
218  *      Destroys an action, freing its memory. This function cannot be called if there are a conditional waiting for it.
219  *      \param action The SIMIX action
220  */
221 int SIMIX_action_destroy(smx_action_t action)
222 {
223   XBT_IN3("(%p:'%s',%d)", action, action->name, action->refcount);
224   xbt_assert0((action != NULL), "Invalid parameter");
225
226   action->refcount--;
227   if (action->refcount > 0)
228     return 0;
229
230   xbt_assert1((xbt_fifo_size(action->cond_list) == 0),
231               "Conditional list not empty %d. There is a problem. Cannot destroy it now!",
232               xbt_fifo_size(action->cond_list));
233
234   xbt_assert1((xbt_fifo_size(action->sem_list) == 0),
235               "Semaphore list not empty %d. There is a problem. Cannot destroy it now!",
236               xbt_fifo_size(action->sem_list));
237
238   DEBUG1("Destroy action %p", action);
239   if (action->name)
240     xbt_free(action->name);
241
242   xbt_fifo_free(action->cond_list);
243   xbt_fifo_free(action->sem_list);
244
245   if (action->surf_action)
246     action->surf_action->model_type->action_unref(action->surf_action);
247 #ifdef HAVE_TRACING
248   TRACE_smx_action_destroy (action);
249 #endif
250   xbt_free(action);
251   return 1;
252 }
253
254 /**
255  *      \brief Increase refcount of anan action
256  *
257  *      \param action The SIMIX action
258  */
259 XBT_INLINE void SIMIX_action_use(smx_action_t action)
260 {
261   XBT_IN3("(%p:'%s',%d)", action, action->name, action->refcount);
262   xbt_assert0((action != NULL), "Invalid parameter");
263
264   action->refcount++;
265
266   return;
267 }
268
269 /**
270  *      \brief Decrease refcount of anan action
271  *
272  *      \param action The SIMIX action
273  */
274 XBT_INLINE void SIMIX_action_release(smx_action_t action)
275 {
276   xbt_assert0((action != NULL), "Invalid parameter");
277
278   action->refcount--;
279
280   return;
281 }
282
283 /**
284  *  \brief Set an action to a condition
285  *
286  *  Creates the "link" between an action and a condition. You have to call this function when you create an action and want to wait its ending.
287  *  \param action SIMIX action
288  *  \param cond SIMIX cond
289  */
290 void SIMIX_register_action_to_condition(smx_action_t action, smx_cond_t cond)
291 {
292   xbt_assert0((action != NULL) && (cond != NULL), "Invalid parameters");
293
294   DEBUG2("Register action %p to cond %p", action, cond);
295   if(XBT_LOG_ISENABLED(simix_action, xbt_log_priority_debug))
296     __SIMIX_cond_display_actions(cond);
297
298   xbt_fifo_push(cond->actions, action);
299
300   if(XBT_LOG_ISENABLED(simix_action, xbt_log_priority_debug))
301     __SIMIX_cond_display_actions(cond);
302
303   DEBUG2("Register condition %p to action %p", cond, action);
304
305   if(XBT_LOG_ISENABLED(simix_action, xbt_log_priority_debug))
306     __SIMIX_action_display_conditions(action);
307
308   xbt_fifo_push(action->cond_list, cond);
309
310   if(XBT_LOG_ISENABLED(simix_action, xbt_log_priority_debug))
311     __SIMIX_action_display_conditions(action);
312 }
313
314 /**
315  *  \brief Unset an action to a condition.
316  *
317  *  Destroys the "links" from the condition to this action.
318  *  \param action SIMIX action
319  *  \param cond SIMIX cond
320  */
321 void SIMIX_unregister_action_to_condition(smx_action_t action,
322                                           smx_cond_t cond)
323 {
324   xbt_assert0((action != NULL) && (cond != NULL), "Invalid parameters");
325
326   if(XBT_LOG_ISENABLED(simix_action, xbt_log_priority_debug))
327     __SIMIX_cond_display_actions(cond);
328
329   xbt_fifo_remove_all(cond->actions, action);
330
331   if(XBT_LOG_ISENABLED(simix_action, xbt_log_priority_debug))
332     __SIMIX_cond_display_actions(cond);
333
334   if(XBT_LOG_ISENABLED(simix_action, xbt_log_priority_debug))
335     __SIMIX_action_display_conditions(action);
336
337   xbt_fifo_remove_all(action->cond_list, cond);
338
339   if(XBT_LOG_ISENABLED(simix_action, xbt_log_priority_debug))
340     __SIMIX_action_display_conditions(action);
341 }
342 /**
343  *  \brief Link an action to a semaphore
344  *
345  *  When the action terminates, the semaphore gets signaled automatically.
346  */
347 XBT_INLINE void SIMIX_register_action_to_semaphore(smx_action_t action, smx_sem_t sem) {
348
349   DEBUG2("Register action %p to semaphore %p (and otherwise)", action, sem);
350   xbt_fifo_push(sem->actions, action);
351   xbt_fifo_push(action->sem_list, sem);
352 }
353 /**
354  *  \brief Unset an action to a semaphore.
355  *
356  *  Destroys the "links" from the semaphore to this action.
357  */
358 XBT_INLINE void SIMIX_unregister_action_to_semaphore(smx_action_t action,
359                                           smx_sem_t sem)
360 {
361   xbt_fifo_remove_all(sem->actions, action);
362   xbt_fifo_remove_all(action->sem_list, sem);
363 }
364
365 /**
366  *      \brief Return how much remais to be done in the action.
367  *
368  *      \param action The SIMIX action
369  *      \return Remains cost
370  */
371 XBT_INLINE double SIMIX_action_get_remains(smx_action_t action)
372 {
373   xbt_assert0((action != NULL), "Invalid parameter");
374   return surf_workstation_model->get_remains(action->surf_action);
375 }
376
377 XBT_INLINE int SIMIX_action_is_latency_bounded(smx_action_t action)
378 {
379   xbt_assert0((action != NULL), "Invalid parameter");
380   return surf_workstation_model->get_latency_limited(action->surf_action);
381 }
382
383 smx_action_t SIMIX_action_parallel_execute(char *name, int host_nb,
384                                            smx_host_t * host_list,
385                                            double *computation_amount,
386                                            double *communication_amount,
387                                            double amount, double rate)
388 {
389   void **workstation_list = NULL;
390   smx_action_t act;
391   int i;
392
393   /* alloc structures */
394   act = xbt_new0(s_smx_action_t, 1);
395   act->cond_list = xbt_fifo_new();
396   act->sem_list = xbt_fifo_new();
397
398   /* initialize them */
399   act->name = xbt_strdup(name);
400 #ifdef HAVE_TRACING
401   act->category = NULL;
402 #endif
403
404   /* set action */
405
406   workstation_list = xbt_new0(void *, host_nb);
407   for (i = 0; i < host_nb; i++)
408     workstation_list[i] = host_list[i]->host;
409
410   act->surf_action =
411     surf_workstation_model->extension.workstation.
412     execute_parallel_task(host_nb, workstation_list, computation_amount,
413                           communication_amount, amount, rate);
414
415   surf_workstation_model->action_data_set(act->surf_action, act);
416
417   return act;
418 }
419
420 XBT_INLINE e_surf_action_state_t SIMIX_action_get_state(smx_action_t action)
421 {
422   xbt_assert0((action != NULL), "Invalid parameter");
423   return surf_workstation_model->action_state_get(action->surf_action);
424 }
425
426 void __SIMIX_cond_display_actions(smx_cond_t cond)
427 {
428   xbt_fifo_item_t item = NULL;
429   smx_action_t action = NULL;
430
431   DEBUG1("Actions for condition %p", cond);
432   xbt_fifo_foreach(cond->actions, item, action, smx_action_t)
433     DEBUG2("\t %p [%s]", action, action->name);
434 }
435
436 void __SIMIX_action_display_conditions(smx_action_t action)
437 {
438   xbt_fifo_item_t item = NULL;
439   smx_cond_t cond = NULL;
440
441   DEBUG1("Conditions for action %p", action);
442   xbt_fifo_foreach(action->cond_list, item, cond, smx_cond_t)
443     DEBUG1("\t %p", cond);
444 }
445
446 XBT_INLINE char *SIMIX_action_get_name(smx_action_t action)
447 {
448   xbt_assert0((action != NULL), "Invalid parameter");
449   return action->name;
450 }
451 /** @brief Change the name of the action. Warning, the string you provide is not strdup()ed */
452 XBT_INLINE void SIMIX_action_set_name(smx_action_t action,char *name)
453 {
454   xbt_free(action->name);
455   action->name = name;
456 }
457
458 /** @brief broadcast any condition and release any semaphore including this action */
459 void SIMIX_action_signal_all(smx_action_t action){
460   smx_cond_t cond;
461   smx_sem_t sem;
462
463   while ((cond = xbt_fifo_pop(action->cond_list)))
464     SIMIX_cond_broadcast(cond);
465
466   while ((sem = xbt_fifo_pop(action->sem_list)))
467     SIMIX_sem_release(sem);
468 }