1 /* Copyright (c) 2004-2011. The SimGrid Team. All rights reserved. */
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. */
6 #include "msg_private.h"
7 #include "msg_mailbox.h"
10 #include "xbt/sysdep.h"
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_gos, msg,
13 "Logging specific to MSG (gos)");
15 /** \ingroup msg_gos_functions
16 * \brief Executes a task and waits for its termination.
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
22 * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
23 * or #MSG_HOST_FAILURE otherwise
25 MSG_error_t MSG_task_execute(m_task_t task)
27 simdata_task_t simdata = NULL;
28 simdata_process_t p_simdata;
29 e_smx_state_t comp_state;
32 simdata = task->simdata;
34 xbt_assert(simdata->host_nb == 0,
35 "This is a parallel task. Go to hell.");
38 TRACE_msg_task_execute_start(task);
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);
45 XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));
47 if (simdata->computation_amount == 0) {
49 TRACE_msg_task_execute_end(task);
54 m_process_t self = SIMIX_process_self();
55 p_simdata = SIMIX_process_self_get_data(self);
58 simcall_host_execute(task->name, p_simdata->m_host->simdata->smx_host,
59 simdata->computation_amount,
62 simcall_set_category(simdata->compute, task->category);
65 p_simdata->waiting_action = simdata->compute;
66 comp_state = simcall_host_execution_wait(simdata->compute);
67 p_simdata->waiting_action = NULL;
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;
76 simdata->compute = NULL;
78 TRACE_msg_task_execute_end(task);
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 */
84 simdata->compute = NULL;
86 TRACE_msg_task_execute_end(task);
88 MSG_RETURN(MSG_HOST_FAILURE);
90 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
92 simdata->compute = NULL;
94 TRACE_msg_task_execute_end(task);
96 MSG_RETURN(MSG_TASK_CANCELED);
100 /** \ingroup m_task_management
101 * \brief Creates a new #m_task_t (a parallel one....).
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
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.
117 * \return The new corresponding object.
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)
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;
131 task->name = xbt_strdup(name);
135 simdata->computation_amount = 0;
136 simdata->message_size = 0;
137 simdata->compute = NULL;
138 simdata->comm = NULL;
139 simdata->rate = -1.0;
141 simdata->sender = NULL;
142 simdata->receiver = NULL;
143 simdata->source = NULL;
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;
150 for (i = 0; i < host_nb; i++)
151 simdata->host_list[i] = host_list[i]->simdata->smx_host;
156 MSG_error_t MSG_parallel_task_execute(m_task_t task)
158 simdata_task_t simdata = NULL;
159 e_smx_state_t comp_state;
160 simdata_process_t p_simdata;
163 simdata = task->simdata;
164 p_simdata = SIMIX_process_self_get_data(SIMIX_process_self());
166 xbt_assert((!simdata->compute)
167 && (task->simdata->isused == 0),
168 "This task is executed somewhere else. Go fix your code!");
170 xbt_assert(simdata->host_nb,
171 "This is not a parallel task. Go to hell.");
173 XBT_DEBUG("Parallel computing on %s", p_simdata->m_host->name);
178 simcall_host_parallel_execute(task->name, simdata->host_nb,
180 simdata->comp_amount,
181 simdata->comm_amount, 1.0, -1.0);
182 XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
184 p_simdata->waiting_action = simdata->compute;
185 comp_state = simcall_host_execution_wait(simdata->compute);
186 p_simdata->waiting_action = NULL;
188 XBT_DEBUG("Finished waiting for execution of action %p, state = %d", simdata->compute, (int)comp_state);
192 if (comp_state == SIMIX_DONE) {
193 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
194 simdata->computation_amount = 0.0;
195 simdata->comm = NULL;
196 simdata->compute = NULL;
198 } else if (simcall_host_get_state(SIMIX_host_self()) == 0) {
199 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
200 simdata->comm = NULL;
201 simdata->compute = NULL;
202 MSG_RETURN(MSG_HOST_FAILURE);
204 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
205 simdata->comm = NULL;
206 simdata->compute = NULL;
207 MSG_RETURN(MSG_TASK_CANCELED);
212 /** \ingroup msg_gos_functions
213 * \brief Sleep for the specified number of seconds
215 * Makes the current process sleep until \a time seconds have elapsed.
217 * \param nb_sec a number of second
219 MSG_error_t MSG_process_sleep(double nb_sec)
222 /*m_process_t proc = MSG_process_self();*/
225 TRACE_msg_process_sleep_in(MSG_process_self());
228 /* create action to sleep */
229 state = simcall_process_sleep(nb_sec);
231 /*proc->simdata->waiting_action = act_sleep;
233 FIXME: check if not setting the waiting_action breaks something on msg
235 proc->simdata->waiting_action = NULL;*/
237 if (state == SIMIX_DONE) {
239 TRACE_msg_process_sleep_out(MSG_process_self());
244 TRACE_msg_process_sleep_out(MSG_process_self());
246 MSG_RETURN(MSG_HOST_FAILURE);
251 MSG_task_receive_from_host(m_task_t * task, const char *alias,
254 return MSG_task_receive_ext(task, alias, -1, host);
257 MSG_error_t MSG_task_receive(m_task_t * task, const char *alias)
259 return MSG_task_receive_with_timeout(task, alias, -1);
263 MSG_task_receive_with_timeout(m_task_t * task, const char *alias,
266 return MSG_task_receive_ext(task, alias, timeout, NULL);
270 MSG_task_receive_ext(m_task_t * task, const char *alias, double timeout,
274 ("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'",
276 return MSG_mailbox_get_task_ext(MSG_mailbox_get_by_alias(alias), task,
280 /** \ingroup msg_gos_functions
281 * \brief Sends a task on a mailbox.
283 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
284 * to end the communication.
286 * \param task a #m_task_t to send on another location.
287 * \param alias name of the mailbox to sent the task to
288 * \return the msg_comm_t communication created
290 msg_comm_t MSG_task_isend(m_task_t task, const char *alias)
292 return MSG_task_isend_with_matching(task,alias,NULL,NULL);
295 /** \ingroup msg_gos_functions
296 * \brief Sends a task on a mailbox, with support for matching requests
298 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
299 * to end the communication.
301 * \param task a #m_task_t to send on another location.
302 * \param alias name of the mailbox to sent the task to
303 * \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
304 * \param match_data user provided data passed to match_fun
305 * \return the msg_comm_t communication created
307 XBT_INLINE msg_comm_t MSG_task_isend_with_matching(m_task_t task, const char *alias,
308 int (*match_fun)(void*,void*),
311 simdata_task_t t_simdata = NULL;
312 m_process_t process = MSG_process_self();
313 msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
317 /* FIXME: these functions are not traceable */
319 /* Prepare the task to send */
320 t_simdata = task->simdata;
321 t_simdata->sender = process;
322 t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
324 xbt_assert(t_simdata->isused == 0,
325 "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
327 t_simdata->isused = 1;
328 t_simdata->comm = NULL;
329 msg_global->sent_msg++;
331 /* Send it by calling SIMIX network layer */
332 msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
333 comm->task_sent = task;
334 comm->task_received = NULL;
335 comm->status = MSG_OK;
337 simcall_comm_isend(mailbox, t_simdata->message_size,
338 t_simdata->rate, task, sizeof(void *), match_fun, NULL, match_data, 0);
339 t_simdata->comm = comm->s_comm; /* FIXME: is the field t_simdata->comm still useful? */
344 /** \ingroup msg_gos_functions
345 * \brief Sends a task on a mailbox.
347 * This is a non blocking detached send function.
348 * Think of it as a best effort send. Keep in mind that the third parameter
349 * is only called if the communication fails. If the communication does work,
350 * it is responsibility of the receiver code to free anything related to
351 * the task, as usual. More details on this can be obtained on
352 * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
353 * in the SimGrid-user mailing list archive.
355 * \param task a #m_task_t to send on another location.
356 * \param alias name of the mailbox to sent the task to
357 * \param cleanup a function to destroy the task if the
358 * communication fails, e.g. MSG_task_destroy
359 * (if NULL, no function will be called)
361 void MSG_task_dsend(m_task_t task, const char *alias, void_f_pvoid_t cleanup)
363 simdata_task_t t_simdata = NULL;
364 m_process_t process = MSG_process_self();
365 msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
369 /* FIXME: these functions are not traceable */
371 /* Prepare the task to send */
372 t_simdata = task->simdata;
373 t_simdata->sender = process;
374 t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
376 xbt_assert(t_simdata->isused == 0,
377 "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
379 t_simdata->isused = 1;
380 t_simdata->comm = NULL;
381 msg_global->sent_msg++;
383 /* Send it by calling SIMIX network layer */
384 smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size,
385 t_simdata->rate, task, sizeof(void *), NULL, cleanup, NULL, 1);
386 t_simdata->comm = comm;
389 /** \ingroup msg_gos_functions
390 * \brief Starts listening for receiving a task from an asynchronous communication.
392 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
393 * to end the communication.
395 * \param task a memory location for storing a #m_task_t.
396 * \param name of the mailbox to receive the task on
397 * \return the msg_comm_t communication created
399 msg_comm_t MSG_task_irecv(m_task_t *task, const char *name)
401 smx_rdv_t rdv = MSG_mailbox_get_by_alias(name);
405 /* FIXME: these functions are not traceable */
408 xbt_assert(task, "Null pointer for the task storage");
412 ("MSG_task_irecv() was asked to write in a non empty task struct.");
414 /* Try to receive it by calling SIMIX network layer */
415 msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
416 comm->task_sent = NULL;
417 comm->task_received = task;
418 comm->status = MSG_OK;
419 comm->s_comm = simcall_comm_irecv(rdv, task, NULL, NULL, NULL);
424 /** \ingroup msg_gos_functions
425 * \brief Checks whether a communication is done, and if yes, finalizes it.
426 * \param comm the communication to test
427 * \return TRUE if the communication is finished
428 * (but it may have failed, use MSG_comm_get_status() to know its status)
429 * or FALSE if the communication is not finished yet
430 * If the status is FALSE, don't forget to use MSG_process_sleep() after the test.
432 int MSG_comm_test(msg_comm_t comm)
437 finished = simcall_comm_test(comm->s_comm);
439 if (finished && comm->task_received != NULL) {
440 /* I am the receiver */
441 (*comm->task_received)->simdata->isused = 0;
445 switch (e.category) {
448 comm->status = MSG_HOST_FAILURE;
453 comm->status = MSG_TRANSFER_FAILURE;
458 comm->status = MSG_TIMEOUT;
471 /** \ingroup msg_gos_functions
472 * \brief This function checks if a communication is finished.
473 * \param comms a vector of communications
474 * \return the position of the finished communication if any
475 * (but it may have failed, use MSG_comm_get_status() to know its status),
476 * or -1 if none is finished
478 int MSG_comm_testany(xbt_dynar_t comms)
481 int finished_index = -1;
483 /* create the equivalent dynar with SIMIX objects */
484 xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
487 xbt_dynar_foreach(comms, cursor, comm) {
488 xbt_dynar_push(s_comms, &comm->s_comm);
491 MSG_error_t status = MSG_OK;
493 finished_index = simcall_comm_testany(s_comms);
496 switch (e.category) {
499 finished_index = e.value;
500 status = MSG_HOST_FAILURE;
504 finished_index = e.value;
505 status = MSG_TRANSFER_FAILURE;
509 finished_index = e.value;
510 status = MSG_TIMEOUT;
518 xbt_dynar_free(&s_comms);
520 if (finished_index != -1) {
521 comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
522 /* the communication is finished */
523 comm->status = status;
525 if (status == MSG_OK && comm->task_received != NULL) {
526 /* I am the receiver */
527 (*comm->task_received)->simdata->isused = 0;
531 return finished_index;
534 /** \ingroup msg_gos_functions
535 * \brief Destroys a communication.
536 * \param comm the communication to destroy.
538 void MSG_comm_destroy(msg_comm_t comm)
543 /** \ingroup msg_gos_functions
544 * \brief Wait for the completion of a communication.
546 * It takes two parameters.
547 * \param comm the communication to wait.
548 * \param timeout Wait until the communication terminates or the timeout occurs
549 * \return MSG_error_t
551 MSG_error_t MSG_comm_wait(msg_comm_t comm, double timeout)
555 simcall_comm_wait(comm->s_comm, timeout);
557 if (comm->task_received != NULL) {
558 /* I am the receiver */
559 (*comm->task_received)->simdata->isused = 0;
562 /* FIXME: these functions are not traceable */
565 switch (e.category) {
567 comm->status = MSG_HOST_FAILURE;
570 comm->status = MSG_TRANSFER_FAILURE;
573 comm->status = MSG_TIMEOUT;
584 /** \ingroup msg_gos_functions
585 * \brief This function is called by a sender and permit to wait for each communication
587 * \param comm a vector of communication
588 * \param nb_elem is the size of the comm vector
589 * \param timeout for each call of MSG_comm_wait
591 void MSG_comm_waitall(msg_comm_t * comm, int nb_elem, double timeout)
594 for (i = 0; i < nb_elem; i++) {
595 MSG_comm_wait(comm[i], timeout);
599 /** \ingroup msg_gos_functions
600 * \brief This function waits for the first communication finished in a list.
601 * \param comms a vector of communications
602 * \return the position of the first finished communication
603 * (but it may have failed, use MSG_comm_get_status() to know its status)
605 int MSG_comm_waitany(xbt_dynar_t comms)
608 int finished_index = -1;
610 /* create the equivalent dynar with SIMIX objects */
611 xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
614 xbt_dynar_foreach(comms, cursor, comm) {
615 xbt_dynar_push(s_comms, &comm->s_comm);
618 MSG_error_t status = MSG_OK;
620 finished_index = simcall_comm_waitany(s_comms);
623 switch (e.category) {
626 finished_index = e.value;
627 status = MSG_HOST_FAILURE;
631 finished_index = e.value;
632 status = MSG_TRANSFER_FAILURE;
636 finished_index = e.value;
637 status = MSG_TIMEOUT;
646 xbt_assert(finished_index != -1, "WaitAny returned -1");
647 xbt_dynar_free(&s_comms);
649 comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
650 /* the communication is finished */
651 comm->status = status;
653 if (comm->task_received != NULL) {
654 /* I am the receiver */
655 (*comm->task_received)->simdata->isused = 0;
658 return finished_index;
662 * \ingroup msg_gos_functions
663 * \brief Returns the error (if any) that occured during a finished communication.
664 * \param comm a finished communication
665 * \return the status of the communication, or MSG_OK if no error occured
666 * during the communication
668 MSG_error_t MSG_comm_get_status(msg_comm_t comm) {
673 m_task_t MSG_comm_get_task(msg_comm_t comm)
675 xbt_assert(comm, "Invalid parameter");
677 return comm->task_received ? *comm->task_received : comm->task_sent;
681 * \brief This function is called by SIMIX to copy the data of a comm.
682 * \param comm the comm
683 * \param buff the data copied
684 * \param buff_size size of the buffer
686 void MSG_comm_copy_data_from_SIMIX(smx_action_t comm, void* buff, size_t buff_size) {
689 SIMIX_comm_copy_pointer_callback(comm, buff, buff_size);
691 // notify the user callback if any
692 if (msg_global->task_copy_callback) {
693 m_task_t task = buff;
694 msg_global->task_copy_callback(task,
695 simcall_comm_get_src_proc(comm), simcall_comm_get_dst_proc(comm));
699 MSG_error_t MSG_task_send(m_task_t task, const char *alias)
701 XBT_DEBUG("MSG_task_send: Trying to send a message on mailbox '%s'", alias);
702 return MSG_task_send_with_timeout(task, alias, -1);
707 MSG_task_send_bounded(m_task_t task, const char *alias, double maxrate)
709 task->simdata->rate = maxrate;
710 return MSG_task_send(task, alias);
715 MSG_task_send_with_timeout(m_task_t task, const char *alias,
718 return MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_alias(alias),
722 int MSG_task_listen(const char *alias)
726 return !MSG_mailbox_is_empty(MSG_mailbox_get_by_alias(alias));
729 int MSG_task_listen_from_host(const char *alias, m_host_t host)
734 MSG_mailbox_get_count_host_waiting_tasks(MSG_mailbox_get_by_alias
738 int MSG_task_listen_from(const char *alias)
745 (task = MSG_mailbox_get_head(MSG_mailbox_get_by_alias(alias))))
748 return MSG_process_get_PID(task->simdata->sender);
751 #ifdef MSG_USE_DEPRECATED
752 /** \ingroup msg_gos_functions
754 * \brief Return the last value returned by a MSG function (except
757 MSG_error_t MSG_get_errno(void)
759 return PROCESS_GET_ERRNO();
762 /** \ingroup msg_gos_functions
763 * \brief Put a task on a channel of an host and waits for the end of the
766 * This function is used for describing the behavior of an agent. It
767 * takes three parameter.
768 * \param task a #m_task_t to send on another location. This task
769 will not be usable anymore when the function will return. There is
770 no automatic task duplication and you have to save your parameters
771 before calling this function. Tasks are unique and once it has been
772 sent to another location, you should not access it anymore. You do
773 not need to call MSG_task_destroy() but to avoid using, as an
774 effect of inattention, this task anymore, you definitely should
775 renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
776 can be transfered iff it has been correctly created with
778 * \param dest the destination of the message
779 * \param channel the channel on which the agent should put this
780 task. This value has to be >=0 and < than the maximal number of
781 channels fixed with MSG_set_channel_number().
782 * \return #MSG_HOST_FAILURE if the host on which
783 * this function was called was shut down,
784 * #MSG_TRANSFER_FAILURE if the transfer could not be properly done
785 * (network failure, dest failure) or #MSG_OK if it succeeded.
787 MSG_error_t MSG_task_put(m_task_t task, m_host_t dest, m_channel_t channel)
789 XBT_WARN("DEPRECATED! Now use MSG_task_send");
790 return MSG_task_put_with_timeout(task, dest, channel, -1.0);
793 /** \ingroup msg_gos_functions
794 * \brief Does exactly the same as MSG_task_put but with a bounded transmition
800 MSG_task_put_bounded(m_task_t task, m_host_t dest, m_channel_t channel,
803 XBT_WARN("DEPRECATED! Now use MSG_task_send_bounded");
804 task->simdata->rate = maxrate;
805 return MSG_task_put(task, dest, channel);
808 /** \ingroup msg_gos_functions \brief Put a task on a channel of an
809 * host (with a timeout on the waiting of the destination host) and
810 * waits for the end of the transmission.
812 * This function is used for describing the behavior of an agent. It
813 * takes four parameter.
814 * \param task a #m_task_t to send on another location. This task
815 will not be usable anymore when the function will return. There is
816 no automatic task duplication and you have to save your parameters
817 before calling this function. Tasks are unique and once it has been
818 sent to another location, you should not access it anymore. You do
819 not need to call MSG_task_destroy() but to avoid using, as an
820 effect of inattention, this task anymore, you definitely should
821 renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
822 can be transfered iff it has been correctly created with
824 * \param dest the destination of the message
825 * \param channel the channel on which the agent should put this
826 task. This value has to be >=0 and < than the maximal number of
827 channels fixed with MSG_set_channel_number().
828 * \param timeout the maximum time to wait for a task before giving
829 up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
831 * \return #MSG_HOST_FAILURE if the host on which
832 this function was called was shut down,
833 #MSG_TRANSFER_FAILURE if the transfer could not be properly done
834 (network failure, dest failure, timeout...) or #MSG_OK if the communication succeeded.
837 MSG_task_put_with_timeout(m_task_t task, m_host_t dest,
838 m_channel_t channel, double timeout)
840 XBT_WARN("DEPRECATED! Now use MSG_task_send_with_timeout");
841 xbt_assert((channel >= 0)
842 && (channel < msg_global->max_channel), "Invalid channel %d",
845 XBT_DEBUG("MSG_task_put_with_timout: Trying to send a task to '%s'", dest->name);
847 MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_channel
848 (dest, channel), task, timeout);
851 /** \ingroup msg_gos_functions
852 * \brief Test whether there is a pending communication on a channel, and who sent it.
854 * It takes one parameter.
855 * \param channel the channel on which the agent should be
856 listening. This value has to be >=0 and < than the maximal
857 number of channels fixed with MSG_set_channel_number().
858 * \return -1 if there is no pending communication and the PID of the process who sent it otherwise
860 int MSG_task_probe_from(m_channel_t channel)
862 XBT_WARN("DEPRECATED! Now use MSG_task_listen_from");
867 xbt_assert((channel >= 0)
868 && (channel < msg_global->max_channel), "Invalid channel %d",
873 MSG_mailbox_get_head(MSG_mailbox_get_by_channel
874 (MSG_host_self(), channel))))
877 return MSG_process_get_PID(task->simdata->sender);
880 /** \ingroup msg_gos_functions
881 * \brief Test whether there is a pending communication on a channel.
883 * It takes one parameter.
884 * \param channel the channel on which the agent should be
885 listening. This value has to be >=0 and < than the maximal
886 number of channels fixed with MSG_set_channel_number().
887 * \return 1 if there is a pending communication and 0 otherwise
889 int MSG_task_Iprobe(m_channel_t channel)
891 XBT_WARN("DEPRECATED!");
892 xbt_assert((channel >= 0)
893 && (channel < msg_global->max_channel), "Invalid channel %d",
899 !MSG_mailbox_is_empty(MSG_mailbox_get_by_channel
900 (MSG_host_self(), channel));
903 /** \ingroup msg_gos_functions
905 * \brief Return the number of tasks waiting to be received on a \a
906 channel and sent by \a host.
908 * It takes two parameters.
909 * \param channel the channel on which the agent should be
910 listening. This value has to be >=0 and < than the maximal
911 number of channels fixed with MSG_set_channel_number().
912 * \param host the host that is to be watched.
913 * \return the number of tasks waiting to be received on \a channel
916 int MSG_task_probe_from_host(int channel, m_host_t host)
918 XBT_WARN("DEPRECATED! Now use MSG_task_listen_from_host");
919 xbt_assert((channel >= 0)
920 && (channel < msg_global->max_channel), "Invalid channel %d",
926 MSG_mailbox_get_count_host_waiting_tasks(MSG_mailbox_get_by_channel
927 (MSG_host_self(), channel),
932 /** \ingroup msg_gos_functions
933 * \brief Listen on \a channel and waits for receiving a task from \a host.
935 * It takes three parameters.
936 * \param task a memory location for storing a #m_task_t. It will
937 hold a task when this function will return. Thus \a task should not
938 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
939 those two condition does not hold, there will be a warning message.
940 * \param channel the channel on which the agent should be
941 listening. This value has to be >=0 and < than the maximal
942 number of channels fixed with MSG_set_channel_number().
943 * \param host the host that is to be watched.
944 * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
947 MSG_task_get_from_host(m_task_t * task, m_channel_t channel, m_host_t host)
949 XBT_WARN("DEPRECATED! Now use MSG_task_receive_from_host");
950 return MSG_task_get_ext(task, channel, -1, host);
953 /** \ingroup msg_gos_functions
954 * \brief Listen on a channel and wait for receiving a task.
956 * It takes two parameters.
957 * \param task a memory location for storing a #m_task_t. It will
958 hold a task when this function will return. Thus \a task should not
959 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
960 those two condition does not hold, there will be a warning message.
961 * \param channel the channel on which the agent should be
962 listening. This value has to be >=0 and < than the maximal
963 number of channels fixed with MSG_set_channel_number().
964 * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
966 MSG_error_t MSG_task_get(m_task_t * task, m_channel_t channel)
968 XBT_WARN("DEPRECATED! Now use MSG_task_receive");
969 return MSG_task_get_with_timeout(task, channel, -1);
972 /** \ingroup msg_gos_functions
973 * \brief Listen on a channel and wait for receiving a task with a timeout.
975 * It takes three parameters.
976 * \param task a memory location for storing a #m_task_t. It will
977 hold a task when this function will return. Thus \a task should not
978 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
979 those two condition does not hold, there will be a warning message.
980 * \param channel the channel on which the agent should be
981 listening. This value has to be >=0 and < than the maximal
982 number of channels fixed with MSG_set_channel_number().
983 * \param max_duration the maximum time to wait for a task before giving
984 up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
985 will not be modified and will still be
986 equal to \c NULL when returning.
987 * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
990 MSG_task_get_with_timeout(m_task_t * task, m_channel_t channel,
993 XBT_WARN("DEPRECATED! Now use MSG_task_receive_with_timeout");
994 return MSG_task_get_ext(task, channel, max_duration, NULL);
997 /** \defgroup msg_gos_functions MSG Operating System Functions
998 * \brief This section describes the functions that can be used
999 * by an agent for handling some task.
1003 MSG_task_get_ext(m_task_t * task, m_channel_t channel, double timeout,
1006 XBT_WARN("DEPRECATED! Now use MSG_task_receive_ext");
1007 xbt_assert((channel >= 0)
1008 && (channel < msg_global->max_channel), "Invalid channel %d",
1012 MSG_mailbox_get_task_ext(MSG_mailbox_get_by_channel
1013 (MSG_host_self(), channel), task, host,