Logo AND Algorithmique Numérique Distribuée

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