Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
missing documentation for these functions
[simgrid.git] / src / msg / msg_gos.c
1 /* Copyright (c) 2004-2011. 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_gos_functions
16  * \brief Executes a task and waits for its termination.
17  *
18  * This function is used for describing the behavior of an agent. It
19  * takes only one parameter.
20  * \param task a #m_task_t to execute on the location on which the
21  agent 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(m_task_t task)
26 {
27   simdata_task_t simdata = NULL;
28   simdata_process_t p_simdata;
29   e_smx_state_t comp_state;
30   CHECK_HOST();
31
32   simdata = task->simdata;
33
34   xbt_assert(simdata->host_nb == 0,
35               "This is a parallel task. Go to hell.");
36
37 #ifdef HAVE_TRACING
38   TRACE_msg_task_execute_start(task);
39 #endif
40
41   xbt_assert((!simdata->compute) && (task->simdata->isused == 0),
42               "This task is executed somewhere else. Go fix your code! %d",
43               task->simdata->isused);
44
45   XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));
46
47   if (simdata->computation_amount == 0) {
48 #ifdef HAVE_TRACING
49     TRACE_msg_task_execute_end(task);
50 #endif
51     return MSG_OK;
52   }
53
54   m_process_t self = SIMIX_process_self();
55   p_simdata = SIMIX_process_self_get_data(self);
56   simdata->isused=1;
57   simdata->compute =
58       simcall_host_execute(task->name, p_simdata->m_host->simdata->smx_host,
59                            simdata->computation_amount,
60                            simdata->priority);
61 #ifdef HAVE_TRACING
62   simcall_set_category(simdata->compute, task->category);
63 #endif
64
65   p_simdata->waiting_action = simdata->compute;
66   comp_state = simcall_host_execution_wait(simdata->compute);
67   p_simdata->waiting_action = NULL;
68
69   simdata->isused=0;
70
71   XBT_DEBUG("Execution task '%s' finished in state %d", task->name, (int)comp_state);
72   if (comp_state == SIMIX_DONE) {
73     /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
74     simdata->computation_amount = 0.0;
75     simdata->comm = NULL;
76     simdata->compute = NULL;
77 #ifdef HAVE_TRACING
78     TRACE_msg_task_execute_end(task);
79 #endif
80     MSG_RETURN(MSG_OK);
81   } else if (simcall_host_get_state(SIMIX_host_self()) == 0) {
82     /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
83     simdata->comm = NULL;
84     simdata->compute = NULL;
85 #ifdef HAVE_TRACING
86     TRACE_msg_task_execute_end(task);
87 #endif
88     MSG_RETURN(MSG_HOST_FAILURE);
89   } else {
90     /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
91     simdata->comm = NULL;
92     simdata->compute = NULL;
93 #ifdef HAVE_TRACING
94     TRACE_msg_task_execute_end(task);
95 #endif
96     MSG_RETURN(MSG_TASK_CANCELED);
97   }
98 }
99
100 /** \ingroup m_task_management
101  * \brief Creates a new #m_task_t (a parallel one....).
102  *
103  * A constructor for #m_task_t taking six arguments and returning the
104  corresponding object.
105  * \param name a name for the object. It is for user-level information
106  and can be NULL.
107  * \param host_nb the number of hosts implied in the parallel task.
108  * \param host_list an array of \p host_nb m_host_t.
109  * \param computation_amount an array of \p host_nb
110  doubles. computation_amount[i] is the total number of operations
111  that have to be performed on host_list[i].
112  * \param communication_amount an array of \p host_nb* \p host_nb doubles.
113  * \param data a pointer to any data may want to attach to the new
114  object.  It is for user-level information and can be NULL. It can
115  be retrieved with the function \ref MSG_task_get_data.
116  * \see m_task_t
117  * \return The new corresponding object.
118  */
119 m_task_t
120 MSG_parallel_task_create(const char *name, int host_nb,
121                          const m_host_t * host_list,
122                          double *computation_amount,
123                          double *communication_amount, void *data)
124 {
125   int i;
126   simdata_task_t simdata = xbt_new0(s_simdata_task_t, 1);
127   m_task_t task = xbt_new0(s_m_task_t, 1);
128   task->simdata = simdata;
129
130   /* Task structure */
131   task->name = xbt_strdup(name);
132   task->data = data;
133
134   /* Simulator Data */
135   simdata->computation_amount = 0;
136   simdata->message_size = 0;
137   simdata->compute = NULL;
138   simdata->comm = NULL;
139   simdata->rate = -1.0;
140   simdata->isused = 0;
141   simdata->sender = NULL;
142   simdata->receiver = NULL;
143   simdata->source = NULL;
144
145   simdata->host_nb = host_nb;
146   simdata->host_list = xbt_new0(smx_host_t, host_nb);
147   simdata->comp_amount = computation_amount;
148   simdata->comm_amount = communication_amount;
149
150   for (i = 0; i < host_nb; i++)
151     simdata->host_list[i] = host_list[i]->simdata->smx_host;
152
153   return task;
154 }
155
156 /** \ingroup msg_gos_functions
157  * \brief Description forthcoming (FIXME)
158  *
159  * \param task
160  * \return
161  */
162 MSG_error_t MSG_parallel_task_execute(m_task_t task)
163 {
164   simdata_task_t simdata = NULL;
165   e_smx_state_t comp_state;
166   simdata_process_t p_simdata;
167   CHECK_HOST();
168
169   simdata = task->simdata;
170   p_simdata = SIMIX_process_self_get_data(SIMIX_process_self());
171
172   xbt_assert((!simdata->compute)
173               && (task->simdata->isused == 0),
174               "This task is executed somewhere else. Go fix your code!");
175
176   xbt_assert(simdata->host_nb,
177               "This is not a parallel task. Go to hell.");
178
179   XBT_DEBUG("Parallel computing on %s", p_simdata->m_host->name);
180
181   simdata->isused=1;
182
183   simdata->compute =
184       simcall_host_parallel_execute(task->name, simdata->host_nb,
185                                   simdata->host_list,
186                                   simdata->comp_amount,
187                                   simdata->comm_amount, 1.0, -1.0);
188   XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
189
190   p_simdata->waiting_action = simdata->compute;
191   comp_state = simcall_host_execution_wait(simdata->compute);
192   p_simdata->waiting_action = NULL;
193
194   XBT_DEBUG("Finished waiting for execution of action %p, state = %d", simdata->compute, (int)comp_state);
195
196   simdata->isused=0;
197
198   if (comp_state == SIMIX_DONE) {
199     /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
200     simdata->computation_amount = 0.0;
201     simdata->comm = NULL;
202     simdata->compute = NULL;
203     MSG_RETURN(MSG_OK);
204   } else if (simcall_host_get_state(SIMIX_host_self()) == 0) {
205     /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
206     simdata->comm = NULL;
207     simdata->compute = NULL;
208     MSG_RETURN(MSG_HOST_FAILURE);
209   } else {
210     /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
211     simdata->comm = NULL;
212     simdata->compute = NULL;
213     MSG_RETURN(MSG_TASK_CANCELED);
214   }
215 }
216
217
218 /** \ingroup msg_gos_functions
219  * \brief Sleep for the specified number of seconds
220  *
221  * Makes the current process sleep until \a time seconds have elapsed.
222  *
223  * \param nb_sec a number of second
224  */
225 MSG_error_t MSG_process_sleep(double nb_sec)
226 {
227   e_smx_state_t state;
228   /*m_process_t proc = MSG_process_self();*/
229
230 #ifdef HAVE_TRACING
231   TRACE_msg_process_sleep_in(MSG_process_self());
232 #endif
233
234   /* create action to sleep */
235   state = simcall_process_sleep(nb_sec);
236
237   /*proc->simdata->waiting_action = act_sleep;
238
239   FIXME: check if not setting the waiting_action breaks something on msg
240   
241   proc->simdata->waiting_action = NULL;*/
242   
243   if (state == SIMIX_DONE) {
244 #ifdef HAVE_TRACING
245   TRACE_msg_process_sleep_out(MSG_process_self());
246 #endif
247     MSG_RETURN(MSG_OK);
248   } else {
249 #ifdef HAVE_TRACING
250     TRACE_msg_process_sleep_out(MSG_process_self());
251 #endif
252     MSG_RETURN(MSG_HOST_FAILURE);
253   }
254 }
255
256 /** \ingroup msg_gos_functions
257  * \brief Description forthcoming (FIXME)
258  *
259  * \param task
260  * \param alias
261  * \param host
262  * \return
263  */
264 MSG_error_t
265 MSG_task_receive_from_host(m_task_t * task, const char *alias,
266                            m_host_t host)
267 {
268   return MSG_task_receive_ext(task, alias, -1, host);
269 }
270
271 /** \ingroup msg_gos_functions
272  * \brief Description forthcoming (FIXME)
273  *
274  * \param task
275  * \param alias
276  * \return
277  */
278 MSG_error_t MSG_task_receive(m_task_t * task, const char *alias)
279 {
280   return MSG_task_receive_with_timeout(task, alias, -1);
281 }
282
283 /** \ingroup msg_gos_functions
284  * \brief Description forthcoming (FIXME)
285  *
286  * \param task
287  * \param alias
288  * \param timeout
289  * \return
290  */
291 MSG_error_t
292 MSG_task_receive_with_timeout(m_task_t * task, const char *alias,
293                               double timeout)
294 {
295   return MSG_task_receive_ext(task, alias, timeout, NULL);
296 }
297
298 /** \ingroup msg_gos_functions
299  * \brief Description forthcoming (FIXME)
300  *
301  * \param task
302  * \param alias
303  * \param timeout
304  * \param host
305  * \return
306  */
307 MSG_error_t
308 MSG_task_receive_ext(m_task_t * task, const char *alias, double timeout,
309                      m_host_t host)
310 {
311   XBT_DEBUG
312       ("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'",
313        alias);
314   return MSG_mailbox_get_task_ext(MSG_mailbox_get_by_alias(alias), task,
315                                   host, timeout);
316 }
317
318 /** \ingroup msg_gos_functions
319  * \brief Sends a task on a mailbox.
320  *
321  * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
322  * to end the communication.
323  *
324  * \param task a #m_task_t to send on another location.
325  * \param alias name of the mailbox to sent the task to
326  * \return the msg_comm_t communication created
327  */
328 msg_comm_t MSG_task_isend(m_task_t task, const char *alias)
329 {
330   return MSG_task_isend_with_matching(task,alias,NULL,NULL);
331 }
332
333 /** \ingroup msg_gos_functions
334  * \brief Sends a task on a mailbox, with support for matching requests
335  *
336  * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
337  * to end the communication.
338  *
339  * \param task a #m_task_t to send on another location.
340  * \param alias name of the mailbox to sent the task to
341  * \param match_fun boolean function taking the match_data provided by sender (here), and the one of the receiver (if any) and returning whether they match
342  * \param match_data user provided data passed to match_fun
343  * \return the msg_comm_t communication created
344  */
345 XBT_INLINE msg_comm_t MSG_task_isend_with_matching(m_task_t task, const char *alias,
346     int (*match_fun)(void*,void*),
347     void *match_data)
348 {
349   simdata_task_t t_simdata = NULL;
350   m_process_t process = MSG_process_self();
351   msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
352
353   CHECK_HOST();
354
355   /* FIXME: these functions are not traceable */
356
357   /* Prepare the task to send */
358   t_simdata = task->simdata;
359   t_simdata->sender = process;
360   t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
361
362   xbt_assert(t_simdata->isused == 0,
363               "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
364
365   t_simdata->isused = 1;
366   t_simdata->comm = NULL;
367   msg_global->sent_msg++;
368
369   /* Send it by calling SIMIX network layer */
370   msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
371   comm->task_sent = task;
372   comm->task_received = NULL;
373   comm->status = MSG_OK;
374   comm->s_comm =
375     simcall_comm_isend(mailbox, t_simdata->message_size,
376                          t_simdata->rate, task, sizeof(void *), match_fun, NULL, match_data, 0);
377   t_simdata->comm = comm->s_comm; /* FIXME: is the field t_simdata->comm still useful? */
378
379   return comm;
380 }
381
382 /** \ingroup msg_gos_functions
383  * \brief Sends a task on a mailbox.
384  *
385  * This is a non blocking detached send function.
386  * Think of it as a best effort send. Keep in mind that the third parameter
387  * is only called if the communication fails. If the communication does work,
388  * it is responsibility of the receiver code to free anything related to
389  * the task, as usual. More details on this can be obtained on
390  * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
391  * in the SimGrid-user mailing list archive.
392  *
393  * \param task a #m_task_t to send on another location.
394  * \param alias name of the mailbox to sent the task to
395  * \param cleanup a function to destroy the task if the
396  * communication fails, e.g. MSG_task_destroy
397  * (if NULL, no function will be called)
398  */
399 void MSG_task_dsend(m_task_t task, const char *alias, void_f_pvoid_t cleanup)
400 {
401   simdata_task_t t_simdata = NULL;
402   m_process_t process = MSG_process_self();
403   msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
404
405   CHECK_HOST();
406
407   /* FIXME: these functions are not traceable */
408
409   /* Prepare the task to send */
410   t_simdata = task->simdata;
411   t_simdata->sender = process;
412   t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
413
414   xbt_assert(t_simdata->isused == 0,
415               "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
416
417   t_simdata->isused = 1;
418   t_simdata->comm = NULL;
419   msg_global->sent_msg++;
420
421   /* Send it by calling SIMIX network layer */
422   smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size,
423                        t_simdata->rate, task, sizeof(void *), NULL, cleanup, NULL, 1);
424   t_simdata->comm = comm;
425 }
426
427 /** \ingroup msg_gos_functions
428  * \brief Starts listening for receiving a task from an asynchronous communication.
429  *
430  * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
431  * to end the communication.
432  *
433  * \param task a memory location for storing a #m_task_t.
434  * \param name of the mailbox to receive the task on
435  * \return the msg_comm_t communication created
436  */
437 msg_comm_t MSG_task_irecv(m_task_t *task, const char *name)
438 {
439   smx_rdv_t rdv = MSG_mailbox_get_by_alias(name);
440
441   CHECK_HOST();
442
443   /* FIXME: these functions are not traceable */
444
445   /* Sanity check */
446   xbt_assert(task, "Null pointer for the task storage");
447
448   if (*task)
449     XBT_CRITICAL
450         ("MSG_task_irecv() was asked to write in a non empty task struct.");
451
452   /* Try to receive it by calling SIMIX network layer */
453   msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
454   comm->task_sent = NULL;
455   comm->task_received = task;
456   comm->status = MSG_OK;
457   comm->s_comm = simcall_comm_irecv(rdv, task, NULL, NULL, NULL);
458
459   return comm;
460 }
461
462 /** \ingroup msg_gos_functions
463  * \brief Checks whether a communication is done, and if yes, finalizes it.
464  * \param comm the communication to test
465  * \return TRUE if the communication is finished
466  * (but it may have failed, use MSG_comm_get_status() to know its status)
467  * or FALSE if the communication is not finished yet
468  * If the status is FALSE, don't forget to use MSG_process_sleep() after the test.
469  */
470 int MSG_comm_test(msg_comm_t comm)
471 {
472   xbt_ex_t e;
473   int finished = 0;
474   TRY {
475     finished = simcall_comm_test(comm->s_comm);
476
477     if (finished && comm->task_received != NULL) {
478       /* I am the receiver */
479       (*comm->task_received)->simdata->isused = 0;
480     }
481   }
482   CATCH(e) {
483     switch (e.category) {
484
485       case host_error:
486         comm->status = MSG_HOST_FAILURE;
487         finished = 1;
488         break;
489
490       case network_error:
491         comm->status = MSG_TRANSFER_FAILURE;
492         finished = 1;
493         break;
494
495       case timeout_error:
496         comm->status = MSG_TIMEOUT;
497         finished = 1;
498         break;
499
500       default:
501         RETHROW;
502     }
503     xbt_ex_free(e);
504   }
505
506   return finished;
507 }
508
509 /** \ingroup msg_gos_functions
510  * \brief This function checks if a communication is finished.
511  * \param comms a vector of communications
512  * \return the position of the finished communication if any
513  * (but it may have failed, use MSG_comm_get_status() to know its status),
514  * or -1 if none is finished
515  */
516 int MSG_comm_testany(xbt_dynar_t comms)
517 {
518   xbt_ex_t e;
519   int finished_index = -1;
520
521   /* create the equivalent dynar with SIMIX objects */
522   xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
523   msg_comm_t comm;
524   unsigned int cursor;
525   xbt_dynar_foreach(comms, cursor, comm) {
526     xbt_dynar_push(s_comms, &comm->s_comm);
527   }
528
529   MSG_error_t status = MSG_OK;
530   TRY {
531     finished_index = simcall_comm_testany(s_comms);
532   }
533   CATCH(e) {
534     switch (e.category) {
535
536       case host_error:
537         finished_index = e.value;
538         status = MSG_HOST_FAILURE;
539         break;
540
541       case network_error:
542         finished_index = e.value;
543         status = MSG_TRANSFER_FAILURE;
544         break;
545
546       case timeout_error:
547         finished_index = e.value;
548         status = MSG_TIMEOUT;
549         break;
550
551       default:
552         RETHROW;
553     }
554     xbt_ex_free(e);
555   }
556   xbt_dynar_free(&s_comms);
557
558   if (finished_index != -1) {
559     comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
560     /* the communication is finished */
561     comm->status = status;
562
563     if (status == MSG_OK && comm->task_received != NULL) {
564       /* I am the receiver */
565       (*comm->task_received)->simdata->isused = 0;
566     }
567   }
568
569   return finished_index;
570 }
571
572 /** \ingroup msg_gos_functions
573  * \brief Destroys a communication.
574  * \param comm the communication to destroy.
575  */
576 void MSG_comm_destroy(msg_comm_t comm)
577 {
578   xbt_free(comm);
579 }
580
581 /** \ingroup msg_gos_functions
582  * \brief Wait for the completion of a communication.
583  *
584  * It takes two parameters.
585  * \param comm the communication to wait.
586  * \param timeout Wait until the communication terminates or the timeout occurs
587  * \return MSG_error_t
588  */
589 MSG_error_t MSG_comm_wait(msg_comm_t comm, double timeout)
590 {
591   xbt_ex_t e;
592   TRY {
593     simcall_comm_wait(comm->s_comm, timeout);
594
595     if (comm->task_received != NULL) {
596       /* I am the receiver */
597       (*comm->task_received)->simdata->isused = 0;
598     }
599
600     /* FIXME: these functions are not traceable */
601   }
602   CATCH(e) {
603     switch (e.category) {
604     case host_error:
605       comm->status = MSG_HOST_FAILURE;
606       break;
607     case network_error:
608       comm->status = MSG_TRANSFER_FAILURE;
609       break;
610     case timeout_error:
611       comm->status = MSG_TIMEOUT;
612       break;
613     default:
614       RETHROW;
615     }
616     xbt_ex_free(e);
617   }
618
619   return comm->status;
620 }
621
622 /** \ingroup msg_gos_functions
623 * \brief This function is called by a sender and permit to wait for each communication
624 *
625 * \param comm a vector of communication
626 * \param nb_elem is the size of the comm vector
627 * \param timeout for each call of MSG_comm_wait
628 */
629 void MSG_comm_waitall(msg_comm_t * comm, int nb_elem, double timeout)
630 {
631   int i = 0;
632   for (i = 0; i < nb_elem; i++) {
633     MSG_comm_wait(comm[i], timeout);
634   }
635 }
636
637 /** \ingroup msg_gos_functions
638  * \brief This function waits for the first communication finished in a list.
639  * \param comms a vector of communications
640  * \return the position of the first finished communication
641  * (but it may have failed, use MSG_comm_get_status() to know its status)
642  */
643 int MSG_comm_waitany(xbt_dynar_t comms)
644 {
645   xbt_ex_t e;
646   int finished_index = -1;
647
648   /* create the equivalent dynar with SIMIX objects */
649   xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
650   msg_comm_t comm;
651   unsigned int cursor;
652   xbt_dynar_foreach(comms, cursor, comm) {
653     xbt_dynar_push(s_comms, &comm->s_comm);
654   }
655
656   MSG_error_t status = MSG_OK;
657   TRY {
658     finished_index = simcall_comm_waitany(s_comms);
659   }
660   CATCH(e) {
661     switch (e.category) {
662
663       case host_error:
664         finished_index = e.value;
665         status = MSG_HOST_FAILURE;
666         break;
667
668       case network_error:
669         finished_index = e.value;
670         status = MSG_TRANSFER_FAILURE;
671         break;
672
673       case timeout_error:
674         finished_index = e.value;
675         status = MSG_TIMEOUT;
676         break;
677
678       default:
679         RETHROW;
680     }
681     xbt_ex_free(e);
682   }
683
684   xbt_assert(finished_index != -1, "WaitAny returned -1");
685   xbt_dynar_free(&s_comms);
686
687   comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
688   /* the communication is finished */
689   comm->status = status;
690
691   if (comm->task_received != NULL) {
692     /* I am the receiver */
693     (*comm->task_received)->simdata->isused = 0;
694   }
695
696   return finished_index;
697 }
698
699 /**
700  * \ingroup msg_gos_functions
701  * \brief Returns the error (if any) that occured during a finished communication.
702  * \param comm a finished communication
703  * \return the status of the communication, or MSG_OK if no error occured
704  * during the communication
705  */
706 MSG_error_t MSG_comm_get_status(msg_comm_t comm) {
707
708   return comm->status;
709 }
710
711 /** \ingroup msg_gos_functions
712  * \brief Description forthcoming (FIXME)
713  *
714  * \param comm
715  * \return
716  */
717 m_task_t MSG_comm_get_task(msg_comm_t comm)
718 {
719   xbt_assert(comm, "Invalid parameter");
720
721   return comm->task_received ? *comm->task_received : comm->task_sent;
722 }
723
724 /**
725  * \brief This function is called by SIMIX to copy the data of a comm.
726  * \param comm the comm
727  * \param buff the data copied
728  * \param buff_size size of the buffer
729  */
730 void MSG_comm_copy_data_from_SIMIX(smx_action_t comm, void* buff, size_t buff_size) {
731
732   // copy the task
733   SIMIX_comm_copy_pointer_callback(comm, buff, buff_size);
734
735   // notify the user callback if any
736   if (msg_global->task_copy_callback) {
737     m_task_t task = buff;
738     msg_global->task_copy_callback(task,
739         simcall_comm_get_src_proc(comm), simcall_comm_get_dst_proc(comm));
740   }
741 }
742
743 /** \ingroup msg_gos_functions
744  * \brief Description forthcoming (FIXME)
745  *
746  * \param task
747  * \param alias
748  * \return
749  */
750 MSG_error_t MSG_task_send(m_task_t task, const char *alias)
751 {
752   XBT_DEBUG("MSG_task_send: Trying to send a message on mailbox '%s'", alias);
753   return MSG_task_send_with_timeout(task, alias, -1);
754 }
755
756 /** \ingroup msg_gos_functions
757  * \brief Description forthcoming (FIXME)
758  *
759  * \param task
760  * \param alias
761  * \param maxrate
762  * \return
763  */
764 MSG_error_t
765 MSG_task_send_bounded(m_task_t task, const char *alias, double maxrate)
766 {
767   task->simdata->rate = maxrate;
768   return MSG_task_send(task, alias);
769 }
770
771 /** \ingroup msg_gos_functions
772  * \brief Description forthcoming (FIXME)
773  *
774  * \param task
775  * \param alias
776  * \param timeout
777  * \return
778  */
779 MSG_error_t
780 MSG_task_send_with_timeout(m_task_t task, const char *alias,
781                            double timeout)
782 {
783   return MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_alias(alias),
784                                       task, timeout);
785 }
786
787 /** \ingroup msg_gos_functions
788  * \brief Description forthcoming (FIXME)
789  *
790  * \param alias
791  * \return
792  */
793 int MSG_task_listen(const char *alias)
794 {
795   CHECK_HOST();
796
797   return !MSG_mailbox_is_empty(MSG_mailbox_get_by_alias(alias));
798 }
799
800 /** \ingroup msg_gos_functions
801  * \brief Description forthcoming (FIXME)
802  *
803  * \param alias
804  * \param host
805  * \return
806  */
807 int MSG_task_listen_from_host(const char *alias, m_host_t host)
808 {
809   CHECK_HOST();
810
811   return
812       MSG_mailbox_get_count_host_waiting_tasks(MSG_mailbox_get_by_alias
813                                                (alias), host);
814 }
815
816 /** \ingroup msg_gos_functions
817  * \brief Description forthcoming (FIXME)
818  *
819  * \param alias
820  * \return
821  */
822 int MSG_task_listen_from(const char *alias)
823 {
824   m_task_t task;
825
826   CHECK_HOST();
827
828   if (NULL ==
829       (task = MSG_mailbox_get_head(MSG_mailbox_get_by_alias(alias))))
830     return -1;
831
832   return MSG_process_get_PID(task->simdata->sender);
833 }
834
835 #ifdef MSG_USE_DEPRECATED
836 /** \ingroup msg_gos_functions
837  *
838  * \brief Return the last value returned by a MSG function (except
839  * MSG_get_errno...).
840  */
841 MSG_error_t MSG_get_errno(void)
842 {
843   return PROCESS_GET_ERRNO();
844 }
845
846 /** \ingroup msg_gos_functions
847  * \brief Put a task on a channel of an host and waits for the end of the
848  * transmission.
849  *
850  * This function is used for describing the behavior of an agent. It
851  * takes three parameter.
852  * \param task a #m_task_t to send on another location. This task
853  will not be usable anymore when the function will return. There is
854  no automatic task duplication and you have to save your parameters
855  before calling this function. Tasks are unique and once it has been
856  sent to another location, you should not access it anymore. You do
857  not need to call MSG_task_destroy() but to avoid using, as an
858  effect of inattention, this task anymore, you definitely should
859  renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
860  can be transfered iff it has been correctly created with
861  MSG_task_create().
862  * \param dest the destination of the message
863  * \param channel the channel on which the agent should put this
864  task. This value has to be >=0 and < than the maximal number of
865  channels fixed with MSG_set_channel_number().
866  * \return #MSG_HOST_FAILURE if the host on which
867  * this function was called was shut down,
868  * #MSG_TRANSFER_FAILURE if the transfer could not be properly done
869  * (network failure, dest failure) or #MSG_OK if it succeeded.
870  */
871 MSG_error_t MSG_task_put(m_task_t task, m_host_t dest, m_channel_t channel)
872 {
873   XBT_WARN("DEPRECATED! Now use MSG_task_send");
874   return MSG_task_put_with_timeout(task, dest, channel, -1.0);
875 }
876
877 /** \ingroup msg_gos_functions
878  * \brief Does exactly the same as MSG_task_put but with a bounded transmition
879  * rate.
880  *
881  * \sa MSG_task_put
882  */
883 MSG_error_t
884 MSG_task_put_bounded(m_task_t task, m_host_t dest, m_channel_t channel,
885                      double maxrate)
886 {
887   XBT_WARN("DEPRECATED! Now use MSG_task_send_bounded");
888   task->simdata->rate = maxrate;
889   return MSG_task_put(task, dest, channel);
890 }
891
892 /** \ingroup msg_gos_functions \brief Put a task on a channel of an
893  * host (with a timeout on the waiting of the destination host) and
894  * waits for the end of the transmission.
895  *
896  * This function is used for describing the behavior of an agent. It
897  * takes four parameter.
898  * \param task a #m_task_t to send on another location. This task
899  will not be usable anymore when the function will return. There is
900  no automatic task duplication and you have to save your parameters
901  before calling this function. Tasks are unique and once it has been
902  sent to another location, you should not access it anymore. You do
903  not need to call MSG_task_destroy() but to avoid using, as an
904  effect of inattention, this task anymore, you definitely should
905  renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
906  can be transfered iff it has been correctly created with
907  MSG_task_create().
908  * \param dest the destination of the message
909  * \param channel the channel on which the agent should put this
910  task. This value has to be >=0 and < than the maximal number of
911  channels fixed with MSG_set_channel_number().
912  * \param timeout the maximum time to wait for a task before giving
913  up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
914  will not be modified
915  * \return #MSG_HOST_FAILURE if the host on which
916 this function was called was shut down,
917 #MSG_TRANSFER_FAILURE if the transfer could not be properly done
918 (network failure, dest failure, timeout...) or #MSG_OK if the communication succeeded.
919  */
920 MSG_error_t
921 MSG_task_put_with_timeout(m_task_t task, m_host_t dest,
922                           m_channel_t channel, double timeout)
923 {
924   XBT_WARN("DEPRECATED! Now use MSG_task_send_with_timeout");
925   xbt_assert((channel >= 0)
926               && (channel < msg_global->max_channel), "Invalid channel %d",
927               channel);
928
929   XBT_DEBUG("MSG_task_put_with_timout: Trying to send a task to '%s'", dest->name);
930   return
931       MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_channel
932                                    (dest, channel), task, timeout);
933 }
934
935 /** \ingroup msg_gos_functions
936  * \brief Test whether there is a pending communication on a channel, and who sent it.
937  *
938  * It takes one parameter.
939  * \param channel the channel on which the agent should be
940  listening. This value has to be >=0 and < than the maximal
941  number of channels fixed with MSG_set_channel_number().
942  * \return -1 if there is no pending communication and the PID of the process who sent it otherwise
943  */
944 int MSG_task_probe_from(m_channel_t channel)
945 {
946   XBT_WARN("DEPRECATED! Now use MSG_task_listen_from");
947   m_task_t task;
948
949   CHECK_HOST();
950
951   xbt_assert((channel >= 0)
952               && (channel < msg_global->max_channel), "Invalid channel %d",
953               channel);
954
955   if (NULL ==
956       (task =
957        MSG_mailbox_get_head(MSG_mailbox_get_by_channel
958                             (MSG_host_self(), channel))))
959     return -1;
960
961   return MSG_process_get_PID(task->simdata->sender);
962 }
963
964 /** \ingroup msg_gos_functions
965  * \brief Test whether there is a pending communication on a channel.
966  *
967  * It takes one parameter.
968  * \param channel the channel on which the agent should be
969  listening. This value has to be >=0 and < than the maximal
970  number of channels fixed with MSG_set_channel_number().
971  * \return 1 if there is a pending communication and 0 otherwise
972  */
973 int MSG_task_Iprobe(m_channel_t channel)
974 {
975   XBT_WARN("DEPRECATED!");
976   xbt_assert((channel >= 0)
977               && (channel < msg_global->max_channel), "Invalid channel %d",
978               channel);
979
980   CHECK_HOST();
981
982   return
983       !MSG_mailbox_is_empty(MSG_mailbox_get_by_channel
984                             (MSG_host_self(), channel));
985 }
986
987 /** \ingroup msg_gos_functions
988
989  * \brief Return the number of tasks waiting to be received on a \a
990  channel and sent by \a host.
991  *
992  * It takes two parameters.
993  * \param channel the channel on which the agent should be
994  listening. This value has to be >=0 and < than the maximal
995  number of channels fixed with MSG_set_channel_number().
996  * \param host the host that is to be watched.
997  * \return the number of tasks waiting to be received on \a channel
998  and sent by \a host.
999  */
1000 int MSG_task_probe_from_host(int channel, m_host_t host)
1001 {
1002   XBT_WARN("DEPRECATED! Now use MSG_task_listen_from_host");
1003   xbt_assert((channel >= 0)
1004               && (channel < msg_global->max_channel), "Invalid channel %d",
1005               channel);
1006
1007   CHECK_HOST();
1008
1009   return
1010       MSG_mailbox_get_count_host_waiting_tasks(MSG_mailbox_get_by_channel
1011                                                (MSG_host_self(), channel),
1012                                                host);
1013
1014 }
1015
1016 /** \ingroup msg_gos_functions
1017  * \brief Listen on \a channel and waits for receiving a task from \a host.
1018  *
1019  * It takes three parameters.
1020  * \param task a memory location for storing a #m_task_t. It will
1021  hold a task when this function will return. Thus \a task should not
1022  be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1023  those two condition does not hold, there will be a warning message.
1024  * \param channel the channel on which the agent should be
1025  listening. This value has to be >=0 and < than the maximal
1026  number of channels fixed with MSG_set_channel_number().
1027  * \param host the host that is to be watched.
1028  * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1029  */
1030 MSG_error_t
1031 MSG_task_get_from_host(m_task_t * task, m_channel_t channel, m_host_t host)
1032 {
1033   XBT_WARN("DEPRECATED! Now use MSG_task_receive_from_host");
1034   return MSG_task_get_ext(task, channel, -1, host);
1035 }
1036
1037 /** \ingroup msg_gos_functions
1038  * \brief Listen on a channel and wait for receiving a task.
1039  *
1040  * It takes two parameters.
1041  * \param task a memory location for storing a #m_task_t. It will
1042  hold a task when this function will return. Thus \a task should not
1043  be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1044  those two condition does not hold, there will be a warning message.
1045  * \param channel the channel on which the agent should be
1046  listening. This value has to be >=0 and < than the maximal
1047  number of channels fixed with MSG_set_channel_number().
1048  * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1049  */
1050 MSG_error_t MSG_task_get(m_task_t * task, m_channel_t channel)
1051 {
1052   XBT_WARN("DEPRECATED! Now use MSG_task_receive");
1053   return MSG_task_get_with_timeout(task, channel, -1);
1054 }
1055
1056 /** \ingroup msg_gos_functions
1057  * \brief Listen on a channel and wait for receiving a task with a timeout.
1058  *
1059  * It takes three parameters.
1060  * \param task a memory location for storing a #m_task_t. It will
1061  hold a task when this function will return. Thus \a task should not
1062  be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1063  those two condition does not hold, there will be a warning message.
1064  * \param channel the channel on which the agent should be
1065  listening. This value has to be >=0 and < than the maximal
1066  number of channels fixed with MSG_set_channel_number().
1067  * \param max_duration the maximum time to wait for a task before giving
1068  up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
1069  will not be modified and will still be
1070  equal to \c NULL when returning.
1071  * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1072  */
1073 MSG_error_t
1074 MSG_task_get_with_timeout(m_task_t * task, m_channel_t channel,
1075                           double max_duration)
1076 {
1077   XBT_WARN("DEPRECATED! Now use MSG_task_receive_with_timeout");
1078   return MSG_task_get_ext(task, channel, max_duration, NULL);
1079 }
1080
1081 MSG_error_t
1082 MSG_task_get_ext(m_task_t * task, m_channel_t channel, double timeout,
1083                  m_host_t host)
1084 {
1085   XBT_WARN("DEPRECATED! Now use MSG_task_receive_ext");
1086   xbt_assert((channel >= 0)
1087               && (channel < msg_global->max_channel), "Invalid channel %d",
1088               channel);
1089
1090   return
1091       MSG_mailbox_get_task_ext(MSG_mailbox_get_by_channel
1092                                (MSG_host_self(), channel), task, host,
1093                                timeout);
1094 }
1095
1096 #endif