Logo AND Algorithmique Numérique Distribuée

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