Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
e6bd45af50200b810d17365d5a902a99de8e9dc4
[simgrid.git] / src / msg / msg_gos.c
1 /* Copyright (c) 2004-2012. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "msg_private.h"
7 #include "msg_mailbox.h"
8 #include "mc/mc.h"
9 #include "xbt/log.h"
10 #include "xbt/sysdep.h"
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_gos, msg,
13                                 "Logging specific to MSG (gos)");
14
15 /** \ingroup msg_task_usage
16  * \brief Executes a task and waits for its termination.
17  *
18  * This function is used for describing the behavior of a process. It
19  * takes only one parameter.
20  * \param task a #msg_task_t to execute on the location on which the process is running.
21  * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
22  * or #MSG_HOST_FAILURE otherwise
23  */
24 msg_error_t MSG_task_execute(msg_task_t task)
25 {
26   /* TODO: add this to other locations */
27   msg_host_t host = MSG_process_get_host(MSG_process_self());
28   MSG_host_add_task(host, task);
29
30   msg_error_t ret = MSG_parallel_task_execute(task);
31
32   MSG_host_del_task(host, task);
33
34   return ret;
35 }
36
37 /** \ingroup msg_task_usage
38  * \brief Executes a parallel task and waits for its termination.
39  *
40  * \param task a #msg_task_t to execute on the location on which the process is running.
41  *
42  * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
43  * or #MSG_HOST_FAILURE otherwise
44  */
45 msg_error_t MSG_parallel_task_execute(msg_task_t task)
46 {
47   xbt_ex_t e;
48   simdata_task_t simdata = task->simdata;
49   msg_process_t self = SIMIX_process_self();
50   simdata_process_t p_simdata = SIMIX_process_self_get_data(self);
51   e_smx_state_t comp_state;
52   msg_error_t status = MSG_OK;
53
54 #ifdef HAVE_TRACING
55   TRACE_msg_task_execute_start(task);
56 #endif
57
58   xbt_assert((!simdata->compute) && (task->simdata->isused == 0),
59              "This task is executed somewhere else. Go fix your code! %d",
60              task->simdata->isused);
61
62   XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));
63
64   if (simdata->computation_amount == 0 && !simdata->host_nb) {
65 #ifdef HAVE_TRACING
66     TRACE_msg_task_execute_end(task);
67 #endif
68     return MSG_OK;
69   }
70
71
72   TRY {
73
74     simdata->isused=1;
75
76     if (simdata->host_nb > 0) {
77       simdata->compute = simcall_host_parallel_execute(task->name,
78                                                        simdata->host_nb,
79                                                        simdata->host_list,
80                                                        simdata->comp_amount,
81                                                        simdata->comm_amount,
82                                                        1.0, -1.0);
83       XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
84     } else {
85       simdata->compute = simcall_host_execute(task->name,
86                                               p_simdata->m_host,
87                                               simdata->computation_amount,
88                                               simdata->priority);
89
90     }
91 #ifdef HAVE_TRACING
92     simcall_set_category(simdata->compute, task->category);
93 #endif
94     p_simdata->waiting_action = simdata->compute;
95     comp_state = simcall_host_execution_wait(simdata->compute);
96
97     p_simdata->waiting_action = NULL;
98
99     simdata->isused=0;
100
101     XBT_DEBUG("Execution task '%s' finished in state %d",
102               task->name, (int)comp_state);
103   }
104   CATCH(e) {
105     switch (e.category) {
106     case cancel_error:
107       status = MSG_TASK_CANCELED;
108       break;
109     default:
110       RETHROW;
111     }
112     xbt_ex_free(e);
113   }
114   /* action ended, set comm and compute = NULL, the actions is already destroyed
115    * in the main function */
116   simdata->computation_amount = 0.0;
117   simdata->comm = NULL;
118   simdata->compute = NULL;
119 #ifdef HAVE_TRACING
120   TRACE_msg_task_execute_end(task);
121 #endif
122
123   MSG_RETURN(status);
124 }
125
126
127 /** \ingroup msg_task_usage
128  * \brief Sleep for the specified number of seconds
129  *
130  * Makes the current process sleep until \a time seconds have elapsed.
131  *
132  * \param nb_sec a number of second
133  */
134 msg_error_t MSG_process_sleep(double nb_sec)
135 {
136   xbt_ex_t e;
137   msg_error_t status = MSG_OK;
138   /*msg_process_t proc = MSG_process_self();*/
139
140 #ifdef HAVE_TRACING
141   TRACE_msg_process_sleep_in(MSG_process_self());
142 #endif
143
144   /* create action to sleep */
145
146   /*proc->simdata->waiting_action = act_sleep;
147
148   FIXME: check if not setting the waiting_action breaks something on msg
149   
150   proc->simdata->waiting_action = NULL;*/
151
152   TRY {
153     simcall_process_sleep(nb_sec);
154   }
155   CATCH(e) {
156     switch (e.category) {
157     case cancel_error:
158       status = MSG_TASK_CANCELED;
159       break;
160     default:
161       RETHROW;
162     }
163     xbt_ex_free(e);
164   }
165
166   #ifdef HAVE_TRACING
167     TRACE_msg_process_sleep_out(MSG_process_self());
168   #endif
169   MSG_RETURN(status);
170 }
171
172 /** \ingroup msg_task_usage
173  * \brief Deprecated function that used to receive a task from a mailbox from a specific host.
174  *
175  * Sorry, this function is not supported anymore. That wouldn't be
176  * impossible to reimplement it, but we are lacking the time to do so ourselves.
177  * If you need this functionality, you can either:
178  *
179  *  - implement the buffering mechanism on the user-level by queuing all messages
180  *    received in the mailbox that do not match your expectation
181  *  - change your application logic to leverage the mailboxes features. For example,
182  *    if you have A receiving messages from B and C, you could have A waiting on
183  *    mailbox "A" most of the time, but on "A#B" when it's waiting for specific
184  *    messages from B and "A#C" when waiting for messages from C. You could even get A
185  *    sometime waiting on all these mailboxes using @ref MSG_comm_waitany. You can find
186  *    an example of use of this function in the @ref MSG_examples section.
187  *  - Provide a proper patch to implement this functionality back in MSG. That wouldn't be
188  *    very difficult actually. Check the function @ref MSG_mailbox_get_task_ext. During its call to
189  *    simcall_comm_recv(), the 5th argument, match_fun, is NULL. Create a function that filters
190  *    messages according to the host (that you will pass as sixth argument to simcall_comm_recv()
191  *    and that your filtering function will receive as first parameter, and then, the filter could
192  *    simply compare the host names, for example. After sufficient testing, provide an example that
193  *    we could add to the distribution, and your first contribution to SimGrid is ready. Thanks in advance.
194  *
195  * \param task a memory location for storing a #msg_task_t.
196  * \param alias name of the mailbox to receive the task from
197  * \param host a #msg_host_t host from where the task was sent
198  *
199  * \return Returns
200  * #MSG_OK if the task was successfully received,
201  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
202  */
203 msg_error_t
204 MSG_task_receive_from_host(msg_task_t * task, const char *alias,
205                            msg_host_t host)
206 {
207   return MSG_task_receive_ext(task, alias, -1, host);
208 }
209
210 /** msg_task_usage
211  *\brief Deprecated function that used to receive a task from a mailbox from a specific host
212  *\brief at a given rate
213  *
214  * \param task a memory location for storing a #msg_task_t.
215  * \param alias name of the mailbox to receive the task from
216  * \param host a #msg_host_t host from where the task was sent
217  * \param rate limit the reception to rate bandwidth
218  *
219  * \return Returns
220  * #MSG_OK if the task was successfully received,
221  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
222  */
223 msg_error_t
224 MSG_task_receive_from_host_bounded(msg_task_t * task, const char *alias,
225                            msg_host_t host, double rate)
226 {
227   return MSG_task_receive_ext_bounded(task, alias, -1, host, rate);
228 }
229
230 /** \ingroup msg_task_usage
231  * \brief Receives a task from a mailbox.
232  *
233  * This is a blocking function, the execution flow will be blocked
234  * until the task is received. See #MSG_task_irecv
235  * for receiving tasks asynchronously.
236  *
237  * \param task a memory location for storing a #msg_task_t.
238  * \param alias name of the mailbox to receive the task from
239  *
240  * \return Returns
241  * #MSG_OK if the task was successfully received,
242  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
243  */
244 msg_error_t MSG_task_receive(msg_task_t * task, const char *alias)
245 {
246   return MSG_task_receive_with_timeout(task, alias, -1);
247 }
248
249 /** \ingroup msg_task_usage
250  * \brief Receives a task from a mailbox at a given rate.
251  *
252  * \param task a memory location for storing a #msg_task_t.
253  * \param alias name of the mailbox to receive the task from
254  *  \param rate limit the reception to rate bandwidth
255  *
256  * \return Returns
257  * #MSG_OK if the task was successfully received,
258  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
259  */
260 msg_error_t MSG_task_receive_bounded(msg_task_t * task, const char *alias, double rate)
261 {
262   return MSG_task_receive_with_timeout_bounded(task, alias, -1, rate);
263 }
264
265 /** \ingroup msg_task_usage
266  * \brief Receives a task from a mailbox with a given timeout.
267  *
268  * This is a blocking function with a timeout, the execution flow will be blocked
269  * until the task is received or the timeout is achieved. See #MSG_task_irecv
270  * for receiving tasks asynchronously.  You can provide a -1 timeout
271  * to obtain an infinite timeout.
272  *
273  * \param task a memory location for storing a #msg_task_t.
274  * \param alias name of the mailbox to receive the task from
275  * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_receive)
276  *
277  * \return Returns
278  * #MSG_OK if the task was successfully received,
279  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
280  */
281 msg_error_t
282 MSG_task_receive_with_timeout(msg_task_t * task, const char *alias,
283                               double timeout)
284 {
285   return MSG_task_receive_ext(task, alias, timeout, NULL);
286 }
287
288 /** \ingroup msg_task_usage
289  * \brief Receives a task from a mailbox with a given timeout and at a given rate.
290  *
291  * \param task a memory location for storing a #msg_task_t.
292  * \param alias name of the mailbox to receive the task from
293  * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_receive)
294  *  \param rate limit the reception to rate bandwidth
295  *
296  * \return Returns
297  * #MSG_OK if the task was successfully received,
298  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
299  */
300 msg_error_t
301 MSG_task_receive_with_timeout_bounded(msg_task_t * task, const char *alias,
302                               double timeout,double rate)
303 {
304   return MSG_task_receive_ext_bounded(task, alias, timeout, NULL,rate);
305 }
306
307 /** \ingroup msg_task_usage
308  * \brief Receives a task from a mailbox from a specific host with a given timeout.
309  *
310  * This is a blocking function with a timeout, the execution flow will be blocked
311  * until the task is received or the timeout is achieved. See #MSG_task_irecv
312  * for receiving tasks asynchronously. You can provide a -1 timeout
313  * to obtain an infinite timeout.
314  *
315  * \param task a memory location for storing a #msg_task_t.
316  * \param alias name of the mailbox to receive the task from
317  * \param timeout is the maximum wait time for completion (provide -1 for no timeout)
318  * \param host a #msg_host_t host from where the task was sent
319  *
320  * \return Returns
321  * #MSG_OK if the task was successfully received,
322 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
323  */
324 msg_error_t
325 MSG_task_receive_ext(msg_task_t * task, const char *alias, double timeout,
326                      msg_host_t host)
327 {
328   xbt_ex_t e;
329   msg_error_t ret = MSG_OK;
330   XBT_DEBUG
331       ("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'",
332        alias);
333   TRY {
334     ret = MSG_mailbox_get_task_ext(MSG_mailbox_get_by_alias(alias), task,
335                                    host, timeout);
336   }
337   CATCH(e) {
338     switch (e.category) {
339     case cancel_error:          /* may be thrown by MSG_mailbox_get_by_alias */
340       ret = MSG_HOST_FAILURE;
341       break;
342     default:
343       RETHROW;
344     }
345     xbt_ex_free(e);
346   }
347   return ret;
348 }
349
350 /** \ingroup msg_task_usage
351  * \brief Receives a task from a mailbox from a specific host with a given timeout
352  *  and at a given rate.
353  *
354  * \param task a memory location for storing a #msg_task_t.
355  * \param alias name of the mailbox to receive the task from
356  * \param timeout is the maximum wait time for completion (provide -1 for no timeout)
357  * \param host a #msg_host_t host from where the task was sent
358  * \param rate limit the reception to rate bandwidth
359  *
360  * \return Returns
361  * #MSG_OK if the task was successfully received,
362 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
363  */
364 msg_error_t
365 MSG_task_receive_ext_bounded(msg_task_t * task, const char *alias, double timeout,
366                      msg_host_t host, double rate)
367 {
368   XBT_DEBUG
369       ("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'",
370        alias);
371   return MSG_mailbox_get_task_ext_bounded(MSG_mailbox_get_by_alias(alias), task,
372                                   host, timeout, rate);
373 }
374
375 /** \ingroup msg_task_usage
376  * \brief Sends a task on a mailbox.
377  *
378  * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
379  * to end the communication.
380  *
381  * \param task a #msg_task_t to send on another location.
382  * \param alias name of the mailbox to sent the task to
383  * \return the msg_comm_t communication created
384  */
385 msg_comm_t MSG_task_isend(msg_task_t task, const char *alias)
386 {
387   return MSG_task_isend_with_matching(task,alias,NULL,NULL);
388 }
389
390 /** \ingroup msg_task_usage
391  * \brief Sends a task on a mailbox with a maximum rate
392  *
393  * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
394  * to end the communication. The maxrate parameter allows the application
395  * to limit the bandwidth utilization of network links when sending the task.
396  *
397  * \param task a #msg_task_t to send on another location.
398  * \param alias name of the mailbox to sent the task to
399  * \param maxrate the maximum communication rate for sending this task .
400  * \return the msg_comm_t communication created
401  */
402 msg_comm_t MSG_task_isend_bounded(msg_task_t task, const char *alias, double maxrate)
403 {
404   task->simdata->rate = maxrate;
405   return MSG_task_isend_with_matching(task,alias,NULL,NULL);
406 }
407
408
409 /** \ingroup msg_task_usage
410  * \brief Sends a task on a mailbox, with support for matching requests
411  *
412  * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
413  * to end the communication.
414  *
415  * \param task a #msg_task_t to send on another location.
416  * \param alias name of the mailbox to sent the task to
417  * \param match_fun boolean function which parameters are:
418  *        - match_data_provided_here
419  *        - match_data_provided_by_other_side_if_any
420  *        - the_smx_action_describing_the_other_side
421  * \param match_data user provided data passed to match_fun
422  * \return the msg_comm_t communication created
423  */
424 XBT_INLINE msg_comm_t MSG_task_isend_with_matching(msg_task_t task, const char *alias,
425     int (*match_fun)(void*,void*, smx_action_t),
426     void *match_data)
427 {
428   simdata_task_t t_simdata = NULL;
429   msg_process_t process = MSG_process_self();
430   msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
431
432 #ifdef HAVE_TRACING
433   int call_end = TRACE_msg_task_put_start(task);
434 #endif
435
436   /* Prepare the task to send */
437   t_simdata = task->simdata;
438   t_simdata->sender = process;
439   t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
440
441   xbt_assert(t_simdata->isused == 0,
442               "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
443
444   t_simdata->isused = 1;
445   t_simdata->comm = NULL;
446   msg_global->sent_msg++;
447
448   /* Send it by calling SIMIX network layer */
449   msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
450   comm->task_sent = task;
451   comm->task_received = NULL;
452   comm->status = MSG_OK;
453   comm->s_comm =
454     simcall_comm_isend(mailbox, t_simdata->message_size,
455                          t_simdata->rate, task, sizeof(void *), match_fun, NULL, match_data, 0);
456   t_simdata->comm = comm->s_comm; /* FIXME: is the field t_simdata->comm still useful? */
457 #ifdef HAVE_TRACING
458     if (TRACE_is_enabled()) {
459       simcall_set_category(comm->s_comm, task->category);
460     }
461 #endif
462
463 #ifdef HAVE_TRACING
464   if (call_end)
465     TRACE_msg_task_put_end();
466 #endif
467
468   return comm;
469 }
470
471 /** \ingroup msg_task_usage
472  * \brief Sends a task on a mailbox.
473  *
474  * This is a non blocking detached send function.
475  * Think of it as a best effort send. Keep in mind that the third parameter
476  * is only called if the communication fails. If the communication does work,
477  * it is responsibility of the receiver code to free anything related to
478  * the task, as usual. More details on this can be obtained on
479  * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
480  * in the SimGrid-user mailing list archive.
481  *
482  * \param task a #msg_task_t to send on another location.
483  * \param alias name of the mailbox to sent the task to
484  * \param cleanup a function to destroy the task if the
485  * communication fails, e.g. MSG_task_destroy
486  * (if NULL, no function will be called)
487  */
488 void MSG_task_dsend(msg_task_t task, const char *alias, void_f_pvoid_t cleanup)
489 {
490   simdata_task_t t_simdata = NULL;
491   msg_process_t process = MSG_process_self();
492   msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
493
494   /* Prepare the task to send */
495   t_simdata = task->simdata;
496   t_simdata->sender = process;
497   t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
498
499   xbt_assert(t_simdata->isused == 0,
500               "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
501
502   t_simdata->isused = 1;
503   t_simdata->comm = NULL;
504   msg_global->sent_msg++;
505
506 #ifdef HAVE_TRACING
507   int call_end = TRACE_msg_task_put_start(task);
508 #endif
509
510   /* Send it by calling SIMIX network layer */
511   smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size,
512                        t_simdata->rate, task, sizeof(void *), NULL, cleanup, NULL, 1);
513   t_simdata->comm = comm;
514 #ifdef HAVE_TRACING
515     if (TRACE_is_enabled()) {
516       simcall_set_category(comm, task->category);
517     }
518 #endif
519
520 #ifdef HAVE_TRACING
521   if (call_end)
522     TRACE_msg_task_put_end();
523 #endif
524 }
525
526
527 /** \ingroup msg_task_usage
528  * \brief Sends a task on a mailbox with a maximal rate.
529  *
530  * This is a non blocking detached send function.
531  * Think of it as a best effort send. Keep in mind that the third parameter
532  * is only called if the communication fails. If the communication does work,
533  * it is responsibility of the receiver code to free anything related to
534  * the task, as usual. More details on this can be obtained on
535  * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
536  * in the SimGrid-user mailing list archive.
537  *
538  * \param task a #msg_task_t to send on another location.
539  * \param alias name of the mailbox to sent the task to
540  * \param cleanup a function to destroy the task if the
541  * communication fails, e.g. MSG_task_destroy
542  * (if NULL, no function will be called)
543  * \param maxrate the maximum communication rate for sending this task
544  * 
545  */
546 void MSG_task_dsend_bounded(msg_task_t task, const char *alias, void_f_pvoid_t cleanup, double maxrate)
547 {
548   task->simdata->rate = maxrate;
549   
550   simdata_task_t t_simdata = NULL;
551   msg_process_t process = MSG_process_self();
552   msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
553
554   /* Prepare the task to send */
555   t_simdata = task->simdata;
556   t_simdata->sender = process;
557   t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
558
559   xbt_assert(t_simdata->isused == 0,
560               "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
561
562   t_simdata->isused = 1;
563   t_simdata->comm = NULL;
564   msg_global->sent_msg++;
565
566 #ifdef HAVE_TRACING
567   int call_end = TRACE_msg_task_put_start(task);
568 #endif
569
570   /* Send it by calling SIMIX network layer */
571   smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size,
572                        t_simdata->rate, task, sizeof(void *), NULL, cleanup, NULL, 1);
573   t_simdata->comm = comm;
574 #ifdef HAVE_TRACING
575     if (TRACE_is_enabled()) {
576       simcall_set_category(comm, task->category);
577     }
578 #endif
579
580 #ifdef HAVE_TRACING
581   if (call_end)
582     TRACE_msg_task_put_end();
583 #endif
584 }
585
586 /** \ingroup msg_task_usage
587  * \brief Starts listening for receiving a task from an asynchronous communication.
588  *
589  * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
590  * to end the communication.
591  * 
592  * \param task a memory location for storing a #msg_task_t. has to be valid until the end of the communication.
593  * \param name of the mailbox to receive the task on
594  * \return the msg_comm_t communication created
595  */
596 msg_comm_t MSG_task_irecv(msg_task_t *task, const char *name)
597 {
598   smx_rdv_t rdv = MSG_mailbox_get_by_alias(name);
599
600   /* FIXME: these functions are not traceable */
601
602   /* Sanity check */
603   xbt_assert(task, "Null pointer for the task storage");
604
605   if (*task)
606     XBT_CRITICAL
607         ("MSG_task_irecv() was asked to write in a non empty task struct.");
608
609   /* Try to receive it by calling SIMIX network layer */
610   msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
611   comm->task_sent = NULL;
612   comm->task_received = task;
613   comm->status = MSG_OK;
614   comm->s_comm = simcall_comm_irecv(rdv, task, NULL, NULL, NULL);
615
616   return comm;
617 }
618
619 /** \ingroup msg_task_usage
620  * \brief Starts listening for receiving a task from an asynchronous communication
621  * at a given rate.
622  *
623  * \param task a memory location for storing a #msg_task_t. has to be valid until the end of the communication.
624  * \param name of the mailbox to receive the task on
625  * \param rate limit the bandwidth to the given rate
626  * \return the msg_comm_t communication created
627  */
628 msg_comm_t MSG_task_irecv_bounded(msg_task_t *task, const char *name, double rate)
629 {
630
631
632   smx_rdv_t rdv = MSG_mailbox_get_by_alias(name);
633
634   /* FIXME: these functions are not traceable */
635
636   /* Sanity check */
637   xbt_assert(task, "Null pointer for the task storage");
638
639   if (*task)
640     XBT_CRITICAL
641         ("MSG_task_irecv() was asked to write in a non empty task struct.");
642
643   /* Try to receive it by calling SIMIX network layer */
644   msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
645   comm->task_sent = NULL;
646   comm->task_received = task;
647   comm->status = MSG_OK;
648   comm->s_comm = simcall_comm_irecv_bounded(rdv, task, NULL, NULL, NULL, rate);
649
650   return comm;
651 }
652
653 /** \ingroup msg_task_usage
654  * \brief Checks whether a communication is done, and if yes, finalizes it.
655  * \param comm the communication to test
656  * \return TRUE if the communication is finished
657  * (but it may have failed, use MSG_comm_get_status() to know its status)
658  * or FALSE if the communication is not finished yet
659  * If the status is FALSE, don't forget to use MSG_process_sleep() after the test.
660  */
661 int MSG_comm_test(msg_comm_t comm)
662 {
663   xbt_ex_t e;
664   int finished = 0;
665
666   TRY {
667     finished = simcall_comm_test(comm->s_comm);
668
669     if (finished && comm->task_received != NULL) {
670       /* I am the receiver */
671       (*comm->task_received)->simdata->isused = 0;
672     }
673   }
674   CATCH(e) {
675     switch (e.category) {
676       case network_error:
677         comm->status = MSG_TRANSFER_FAILURE;
678         finished = 1;
679         break;
680
681       case timeout_error:
682         comm->status = MSG_TIMEOUT;
683         finished = 1;
684         break;
685
686       default:
687         RETHROW;
688     }
689     xbt_ex_free(e);
690   }
691
692   return finished;
693 }
694
695 /** \ingroup msg_task_usage
696  * \brief This function checks if a communication is finished.
697  * \param comms a vector of communications
698  * \return the position of the finished communication if any
699  * (but it may have failed, use MSG_comm_get_status() to know its status),
700  * or -1 if none is finished
701  */
702 int MSG_comm_testany(xbt_dynar_t comms)
703 {
704   xbt_ex_t e;
705   int finished_index = -1;
706
707   /* create the equivalent dynar with SIMIX objects */
708   xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
709   msg_comm_t comm;
710   unsigned int cursor;
711   xbt_dynar_foreach(comms, cursor, comm) {
712     xbt_dynar_push(s_comms, &comm->s_comm);
713   }
714
715   msg_error_t status = MSG_OK;
716   TRY {
717     finished_index = simcall_comm_testany(s_comms);
718   }
719   CATCH(e) {
720     switch (e.category) {
721       case network_error:
722         finished_index = e.value;
723         status = MSG_TRANSFER_FAILURE;
724         break;
725
726       case timeout_error:
727         finished_index = e.value;
728         status = MSG_TIMEOUT;
729         break;
730
731       default:
732         RETHROW;
733     }
734     xbt_ex_free(e);
735   }
736   xbt_dynar_free(&s_comms);
737
738   if (finished_index != -1) {
739     comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
740     /* the communication is finished */
741     comm->status = status;
742
743     if (status == MSG_OK && comm->task_received != NULL) {
744       /* I am the receiver */
745       (*comm->task_received)->simdata->isused = 0;
746     }
747   }
748
749   return finished_index;
750 }
751
752 /** \ingroup msg_task_usage
753  * \brief Destroys a communication.
754  * \param comm the communication to destroy.
755  */
756 void MSG_comm_destroy(msg_comm_t comm)
757 {
758   xbt_free(comm);
759 }
760
761 /** \ingroup msg_task_usage
762  * \brief Wait for the completion of a communication.
763  *
764  * It takes two parameters.
765  * \param comm the communication to wait.
766  * \param timeout Wait until the communication terminates or the timeout 
767  * occurs. You can provide a -1 timeout to obtain an infinite timeout.
768  * \return msg_error_t
769  */
770 msg_error_t MSG_comm_wait(msg_comm_t comm, double timeout)
771 {
772   xbt_ex_t e;
773   TRY {
774     simcall_comm_wait(comm->s_comm, timeout);
775
776     if (comm->task_received != NULL) {
777       /* I am the receiver */
778       (*comm->task_received)->simdata->isused = 0;
779     }
780
781     /* FIXME: these functions are not traceable */
782   }
783   CATCH(e) {
784     switch (e.category) {
785     case network_error:
786       comm->status = MSG_TRANSFER_FAILURE;
787       break;
788     case timeout_error:
789       comm->status = MSG_TIMEOUT;
790       break;
791     default:
792       RETHROW;
793     }
794     xbt_ex_free(e);
795   }
796
797   return comm->status;
798 }
799
800 /** \ingroup msg_task_usage
801 * \brief This function is called by a sender and permit to wait for each communication
802 *
803 * \param comm a vector of communication
804 * \param nb_elem is the size of the comm vector
805 * \param timeout for each call of MSG_comm_wait
806 */
807 void MSG_comm_waitall(msg_comm_t * comm, int nb_elem, double timeout)
808 {
809   int i = 0;
810   for (i = 0; i < nb_elem; i++) {
811     MSG_comm_wait(comm[i], timeout);
812   }
813 }
814
815 /** \ingroup msg_task_usage
816  * \brief This function waits for the first communication finished in a list.
817  * \param comms a vector of communications
818  * \return the position of the first finished communication
819  * (but it may have failed, use MSG_comm_get_status() to know its status)
820  */
821 int MSG_comm_waitany(xbt_dynar_t comms)
822 {
823   xbt_ex_t e;
824   int finished_index = -1;
825
826   /* create the equivalent dynar with SIMIX objects */
827   xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
828   msg_comm_t comm;
829   unsigned int cursor;
830   xbt_dynar_foreach(comms, cursor, comm) {
831     xbt_dynar_push(s_comms, &comm->s_comm);
832   }
833
834   msg_error_t status = MSG_OK;
835   TRY {
836     finished_index = simcall_comm_waitany(s_comms);
837   }
838   CATCH(e) {
839     switch (e.category) {
840       case network_error:
841         finished_index = e.value;
842         status = MSG_TRANSFER_FAILURE;
843         break;
844
845       case timeout_error:
846         finished_index = e.value;
847         status = MSG_TIMEOUT;
848         break;
849
850       default:
851         RETHROW;
852     }
853     xbt_ex_free(e);
854   }
855
856   xbt_assert(finished_index != -1, "WaitAny returned -1");
857   xbt_dynar_free(&s_comms);
858
859   comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
860   /* the communication is finished */
861   comm->status = status;
862
863   if (comm->task_received != NULL) {
864     /* I am the receiver */
865     (*comm->task_received)->simdata->isused = 0;
866   }
867
868   return finished_index;
869 }
870
871 /**
872  * \ingroup msg_task_usage
873  * \brief Returns the error (if any) that occured during a finished communication.
874  * \param comm a finished communication
875  * \return the status of the communication, or #MSG_OK if no error occured
876  * during the communication
877  */
878 msg_error_t MSG_comm_get_status(msg_comm_t comm) {
879
880   return comm->status;
881 }
882
883 /** \ingroup msg_task_usage
884  * \brief Get a task (#msg_task_t) from a communication
885  *
886  * \param comm the communication where to get the task
887  * \return the task from the communication
888  */
889 msg_task_t MSG_comm_get_task(msg_comm_t comm)
890 {
891   xbt_assert(comm, "Invalid parameter");
892
893   return comm->task_received ? *comm->task_received : comm->task_sent;
894 }
895
896 /**
897  * \brief This function is called by SIMIX in kernel mode to copy the data of a comm.
898  * \param comm the comm
899  * \param buff the data copied
900  * \param buff_size size of the buffer
901  */
902 void MSG_comm_copy_data_from_SIMIX(smx_action_t comm, void* buff, size_t buff_size) {
903
904   // copy the task
905   SIMIX_comm_copy_pointer_callback(comm, buff, buff_size);
906
907   // notify the user callback if any
908   if (msg_global->task_copy_callback) {
909     msg_task_t task = buff;
910     msg_global->task_copy_callback(task,
911         simcall_comm_get_src_proc(comm), simcall_comm_get_dst_proc(comm));
912   }
913 }
914
915 /** \ingroup msg_task_usage
916  * \brief Sends a task to a mailbox
917  *
918  * This is a blocking function, the execution flow will be blocked
919  * until the task is sent (and received in the other side if #MSG_task_receive is used).
920  * See #MSG_task_isend for sending tasks asynchronously.
921  *
922  * \param task the task to be sent
923  * \param alias the mailbox name to where the task is sent
924  *
925  * \return Returns #MSG_OK if the task was successfully sent,
926  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
927  */
928 msg_error_t MSG_task_send(msg_task_t task, const char *alias)
929 {
930   XBT_DEBUG("MSG_task_send: Trying to send a message on mailbox '%s'", alias);
931   return MSG_task_send_with_timeout(task, alias, -1);
932 }
933
934 /** \ingroup msg_task_usage
935  * \brief Sends a task to a mailbox with a maximum rate
936  *
937  * This is a blocking function, the execution flow will be blocked
938  * until the task is sent. The maxrate parameter allows the application
939  * to limit the bandwidth utilization of network links when sending the task.
940  *
941  * \param task the task to be sent
942  * \param alias the mailbox name to where the task is sent
943  * \param maxrate the maximum communication rate for sending this task
944  *
945  * \return Returns #MSG_OK if the task was successfully sent,
946  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
947  */
948 msg_error_t
949 MSG_task_send_bounded(msg_task_t task, const char *alias, double maxrate)
950 {
951   task->simdata->rate = maxrate;
952   return MSG_task_send(task, alias);
953 }
954
955 /** \ingroup msg_task_usage
956  * \brief Sends a task to a mailbox with a timeout
957  *
958  * This is a blocking function, the execution flow will be blocked
959  * until the task is sent or the timeout is achieved.
960  *
961  * \param task the task to be sent
962  * \param alias the mailbox name to where the task is sent
963  * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_send)
964  *
965  * \return Returns #MSG_OK if the task was successfully sent,
966  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
967  */
968 msg_error_t
969 MSG_task_send_with_timeout(msg_task_t task, const char *alias,
970                            double timeout)
971 {
972   return MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_alias(alias),
973                                       task, timeout);
974 }
975
976 /** \ingroup msg_task_usage
977  * \brief Sends a task to a mailbox with a timeout and with a maximum rate
978  *
979  * This is a blocking function, the execution flow will be blocked
980  * until the task is sent or the timeout is achieved.
981  *
982  * \param task the task to be sent
983  * \param alias the mailbox name to where the task is sent
984  * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_send)
985  * \param maxrate the maximum communication rate for sending this task
986  *
987  * \return Returns #MSG_OK if the task was successfully sent,
988  * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
989  */
990 msg_error_t
991 MSG_task_send_with_timeout_bounded(msg_task_t task, const char *alias,
992                            double timeout, double maxrate)
993 {
994   task->simdata->rate = maxrate;
995   return MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_alias(alias),
996                                       task, timeout);
997 }
998
999 /** \ingroup msg_task_usage
1000  * \brief Check if there is a communication going on in a mailbox.
1001  *
1002  * \param alias the name of the mailbox to be considered
1003  *
1004  * \return Returns 1 if there is a communication, 0 otherwise
1005  */
1006 int MSG_task_listen(const char *alias)
1007 {
1008   return !MSG_mailbox_is_empty(MSG_mailbox_get_by_alias(alias));
1009 }
1010
1011 /** \ingroup msg_task_usage
1012  * \brief Check the number of communication actions of a given host pending in a mailbox.
1013  *
1014  * \param alias the name of the mailbox to be considered
1015  * \param host the host to check for communication
1016  *
1017  * \return Returns the number of pending communication actions of the host in the
1018  * given mailbox, 0 if there is no pending communication actions.
1019  *
1020  */
1021 int MSG_task_listen_from_host(const char *alias, msg_host_t host)
1022 {
1023   return
1024       MSG_mailbox_get_count_host_waiting_tasks(MSG_mailbox_get_by_alias
1025                                                (alias), host);
1026 }
1027
1028 /** \ingroup msg_task_usage
1029  * \brief Look if there is a communication on a mailbox and return the
1030  * PID of the sender process.
1031  *
1032  * \param alias the name of the mailbox to be considered
1033  *
1034  * \return Returns the PID of sender process,
1035  * -1 if there is no communication in the mailbox.
1036  */
1037 int MSG_task_listen_from(const char *alias)
1038 {
1039   msg_task_t task;
1040
1041   if (NULL ==
1042       (task = MSG_mailbox_get_head(MSG_mailbox_get_by_alias(alias))))
1043     return -1;
1044
1045   return MSG_process_get_PID(task->simdata->sender);
1046 }
1047
1048 /** \ingroup msg_task_usage
1049  * \brief Sets the tracing category of a task.
1050  *
1051  * This function should be called after the creation of
1052  * a MSG task, to define the category of that task. The
1053  * first parameter task must contain a task that was
1054  * created with the function #MSG_task_create. The second
1055  * parameter category must contain a category that was
1056  * previously declared with the function #TRACE_category
1057  * (or with #TRACE_category_with_color).
1058  *
1059  * See \ref tracing for details on how to trace
1060  * the (categorized) resource utilization.
1061  *
1062  * \param task the task that is going to be categorized
1063  * \param category the name of the category to be associated to the task
1064  *
1065  * \see MSG_task_get_category, TRACE_category, TRACE_category_with_color
1066  */
1067 void MSG_task_set_category (msg_task_t task, const char *category)
1068 {
1069 #ifdef HAVE_TRACING
1070   TRACE_msg_set_task_category (task, category);
1071 #endif
1072 }
1073
1074 /** \ingroup msg_task_usage
1075  *
1076  * \brief Gets the current tracing category of a task.
1077  *
1078  * \param task the task to be considered
1079  *
1080  * \see MSG_task_set_category
1081  *
1082  * \return Returns the name of the tracing category of the given task, NULL otherwise
1083  */
1084 const char *MSG_task_get_category (msg_task_t task)
1085 {
1086 #ifdef HAVE_TRACING
1087   return task->category;
1088 #else
1089   return NULL;
1090 #endif
1091 }
1092
1093 /**
1094  * \brief Returns the value of a given AS or router property
1095  *
1096  * \param asr the name of a router or AS
1097  * \param name a property name
1098  * \return value of a property (or NULL if property not set)
1099  */
1100 const char *MSG_as_router_get_property_value(const char* asr, const char *name)
1101 {
1102   return xbt_dict_get_or_null(MSG_as_router_get_properties(asr), name);
1103 }
1104
1105 /**
1106  * \brief Returns a xbt_dict_t consisting of the list of properties assigned to
1107  * a the AS or router
1108  *
1109  * \param asr the name of a router or AS
1110  * \return a dict containing the properties
1111  */
1112 xbt_dict_t MSG_as_router_get_properties(const char* asr)
1113 {
1114   return (simcall_asr_get_properties(asr));
1115 }
1116
1117 /**
1118  * \brief Change the value of a given AS or router
1119  *
1120  * \param asr the name of a router or AS
1121  * \param name a property name
1122  * \param value what to change the property to
1123  * \param free_ctn the freeing function to use to kill the value on need
1124  */
1125 void MSG_as_router_set_property_value(const char* asr, const char *name, char *value,void_f_pvoid_t free_ctn) {
1126   xbt_dict_set(MSG_as_router_get_properties(asr), name, value,free_ctn);
1127 }
1128
1129 #ifdef MSG_USE_DEPRECATED
1130 /** \ingroup msg_deprecated_functions
1131  *
1132  * \brief Return the last value returned by a MSG function (except
1133  * MSG_get_errno...).
1134  */
1135 msg_error_t MSG_get_errno(void)
1136 {
1137   return PROCESS_GET_ERRNO();
1138 }
1139
1140 /** \ingroup msg_deprecated_functions
1141  * \brief Put a task on a channel of an host and waits for the end of the
1142  * transmission.
1143  *
1144  * This function is used for describing the behavior of a process. It
1145  * takes three parameter.
1146  * \param task a #msg_task_t to send on another location. This task
1147  will not be usable anymore when the function will return. There is
1148  no automatic task duplication and you have to save your parameters
1149  before calling this function. Tasks are unique and once it has been
1150  sent to another location, you should not access it anymore. You do
1151  not need to call MSG_task_destroy() but to avoid using, as an
1152  effect of inattention, this task anymore, you definitely should
1153  renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
1154  can be transfered iff it has been correctly created with
1155  MSG_task_create().
1156  * \param dest the destination of the message
1157  * \param channel the channel on which the process should put this
1158  task. This value has to be >=0 and < than the maximal number of
1159  channels fixed with MSG_set_channel_number().
1160  * \return #MSG_HOST_FAILURE if the host on which
1161  * this function was called was shut down,
1162  * #MSG_TRANSFER_FAILURE if the transfer could not be properly done
1163  * (network failure, dest failure) or #MSG_OK if it succeeded.
1164  */
1165 msg_error_t MSG_task_put(msg_task_t task, msg_host_t dest, m_channel_t channel)
1166 {
1167   XBT_WARN("DEPRECATED! Now use MSG_task_send");
1168   return MSG_task_put_with_timeout(task, dest, channel, -1.0);
1169 }
1170
1171 /** \ingroup msg_deprecated_functions
1172  * \brief Does exactly the same as MSG_task_put but with a bounded transmition
1173  * rate.
1174  *
1175  * \sa MSG_task_put
1176  */
1177 msg_error_t
1178 MSG_task_put_bounded(msg_task_t task, msg_host_t dest, m_channel_t channel,
1179                      double maxrate)
1180 {
1181   XBT_WARN("DEPRECATED! Now use MSG_task_send_bounded");
1182   task->simdata->rate = maxrate;
1183   return MSG_task_put(task, dest, channel);
1184 }
1185
1186 /** \ingroup msg_deprecated_functions
1187  *
1188  * \brief Put a task on a channel of an
1189  * host (with a timeout on the waiting of the destination host) and
1190  * waits for the end of the transmission.
1191  *
1192  * This function is used for describing the behavior of a process. It
1193  * takes four parameter.
1194  * \param task a #msg_task_t to send on another location. This task
1195  will not be usable anymore when the function will return. There is
1196  no automatic task duplication and you have to save your parameters
1197  before calling this function. Tasks are unique and once it has been
1198  sent to another location, you should not access it anymore. You do
1199  not need to call MSG_task_destroy() but to avoid using, as an
1200  effect of inattention, this task anymore, you definitely should
1201  renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
1202  can be transfered iff it has been correctly created with
1203  MSG_task_create().
1204  * \param dest the destination of the message
1205  * \param channel the channel on which the process should put this
1206  task. This value has to be >=0 and < than the maximal number of
1207  channels fixed with MSG_set_channel_number().
1208  * \param timeout the maximum time to wait for a task before giving
1209  up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
1210  will not be modified
1211  * \return #MSG_HOST_FAILURE if the host on which
1212 this function was called was shut down,
1213 #MSG_TRANSFER_FAILURE if the transfer could not be properly done
1214 (network failure, dest failure, timeout...) or #MSG_OK if the communication succeeded.
1215  */
1216 msg_error_t
1217 MSG_task_put_with_timeout(msg_task_t task, msg_host_t dest,
1218                           m_channel_t channel, double timeout)
1219 {
1220   XBT_WARN("DEPRECATED! Now use MSG_task_send_with_timeout");
1221   xbt_assert((channel >= 0)
1222               && (channel < msg_global->max_channel), "Invalid channel %d",
1223               channel);
1224
1225   XBT_DEBUG("MSG_task_put_with_timout: Trying to send a task to '%s'", SIMIX_host_get_name(dest->smx_host));
1226   return
1227       MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_channel
1228                                    (dest, channel), task, timeout);
1229 }
1230
1231 /** \ingroup msg_deprecated_functions
1232  * \brief Test whether there is a pending communication on a channel, and who sent it.
1233  *
1234  * It takes one parameter.
1235  * \param channel the channel on which the process should be
1236  listening. This value has to be >=0 and < than the maximal
1237  number of channels fixed with MSG_set_channel_number().
1238  * \return -1 if there is no pending communication and the PID of the process who sent it otherwise
1239  */
1240 int MSG_task_probe_from(m_channel_t channel)
1241 {
1242   XBT_WARN("DEPRECATED! Now use MSG_task_listen_from");
1243   msg_task_t task;
1244
1245   xbt_assert((channel >= 0)
1246               && (channel < msg_global->max_channel), "Invalid channel %d",
1247               channel);
1248
1249   if (NULL ==
1250       (task =
1251        MSG_mailbox_get_head(MSG_mailbox_get_by_channel
1252                             (MSG_host_self(), channel))))
1253     return -1;
1254
1255   return MSG_process_get_PID(task->simdata->sender);
1256 }
1257
1258 /** \ingroup msg_deprecated_functions
1259  * \brief Test whether there is a pending communication on a channel.
1260  *
1261  * It takes one parameter.
1262  * \param channel the channel on which the process should be
1263  listening. This value has to be >=0 and < than the maximal
1264  number of channels fixed with MSG_set_channel_number().
1265  * \return 1 if there is a pending communication and 0 otherwise
1266  */
1267 int MSG_task_Iprobe(m_channel_t channel)
1268 {
1269   XBT_WARN("DEPRECATED!");
1270   xbt_assert((channel >= 0)
1271               && (channel < msg_global->max_channel), "Invalid channel %d",
1272               channel);
1273
1274   return
1275       !MSG_mailbox_is_empty(MSG_mailbox_get_by_channel
1276                             (MSG_host_self(), channel));
1277 }
1278
1279 /** \ingroup msg_deprecated_functions
1280
1281  * \brief Return the number of tasks waiting to be received on a \a
1282  channel and sent by \a host.
1283  *
1284  * It takes two parameters.
1285  * \param channel the channel on which the process should be
1286  listening. This value has to be >=0 and < than the maximal
1287  number of channels fixed with MSG_set_channel_number().
1288  * \param host the host that is to be watched.
1289  * \return the number of tasks waiting to be received on \a channel
1290  and sent by \a host.
1291  */
1292 int MSG_task_probe_from_host(int channel, msg_host_t host)
1293 {
1294   XBT_WARN("DEPRECATED! Now use MSG_task_listen_from_host");
1295   xbt_assert((channel >= 0)
1296               && (channel < msg_global->max_channel), "Invalid channel %d",
1297               channel);
1298
1299   return
1300       MSG_mailbox_get_count_host_waiting_tasks(MSG_mailbox_get_by_channel
1301                                                (MSG_host_self(), channel),
1302                                                host);
1303
1304 }
1305
1306 /** \ingroup msg_deprecated_functions
1307  * \brief Listen on \a channel and waits for receiving a task from \a host.
1308  *
1309  * It takes three parameters.
1310  * \param task a memory location for storing a #msg_task_t. It will
1311  hold a task when this function will return. Thus \a task should not
1312  be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1313  those two condition does not hold, there will be a warning message.
1314  * \param channel the channel on which the process should be
1315  listening. This value has to be >=0 and < than the maximal
1316  number of channels fixed with MSG_set_channel_number().
1317  * \param host the host that is to be watched.
1318  * \return a #msg_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1319  */
1320 msg_error_t
1321 MSG_task_get_from_host(msg_task_t * task, m_channel_t channel, msg_host_t host)
1322 {
1323   XBT_WARN("DEPRECATED! Now use MSG_task_receive_from_host");
1324   return MSG_task_get_ext(task, channel, -1, host);
1325 }
1326
1327 /** \ingroup msg_deprecated_functions
1328  * \brief Listen on a channel and wait for receiving a task.
1329  *
1330  * It takes two parameters.
1331  * \param task a memory location for storing a #msg_task_t. It will
1332  hold a task when this function will return. Thus \a task should not
1333  be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1334  those two condition does not hold, there will be a warning message.
1335  * \param channel the channel on which the process should be
1336  listening. This value has to be >=0 and < than the maximal
1337  number of channels fixed with MSG_set_channel_number().
1338  * \return a #msg_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1339  */
1340 msg_error_t MSG_task_get(msg_task_t * task, m_channel_t channel)
1341 {
1342   XBT_WARN("DEPRECATED! Now use MSG_task_receive");
1343   return MSG_task_get_with_timeout(task, channel, -1);
1344 }
1345
1346 /** \ingroup msg_deprecated_functions
1347  * \brief Listen on a channel and wait for receiving a task with a timeout.
1348  *
1349  * It takes three parameters.
1350  * \param task a memory location for storing a #msg_task_t. It will
1351  hold a task when this function will return. Thus \a task should not
1352  be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1353  those two condition does not hold, there will be a warning message.
1354  * \param channel the channel on which the process should be
1355  listening. This value has to be >=0 and < than the maximal
1356  number of channels fixed with MSG_set_channel_number().
1357  * \param max_duration the maximum time to wait for a task before giving
1358  up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
1359  will not be modified and will still be
1360  equal to \c NULL when returning.
1361  * \return a #msg_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1362  */
1363 msg_error_t
1364 MSG_task_get_with_timeout(msg_task_t * task, m_channel_t channel,
1365                           double max_duration)
1366 {
1367   XBT_WARN("DEPRECATED! Now use MSG_task_receive_with_timeout");
1368   return MSG_task_get_ext(task, channel, max_duration, NULL);
1369 }
1370
1371 msg_error_t
1372 MSG_task_get_ext(msg_task_t * task, m_channel_t channel, double timeout,
1373                  msg_host_t host)
1374 {
1375   XBT_WARN("DEPRECATED! Now use MSG_task_receive_ext");
1376   xbt_assert((channel >= 0)
1377               && (channel < msg_global->max_channel), "Invalid channel %d",
1378               channel);
1379
1380   return
1381       MSG_mailbox_get_task_ext(MSG_mailbox_get_by_channel
1382                                (MSG_host_self(), channel), task, host,
1383                                timeout);
1384 }
1385
1386 #endif