1 /* Copyright (c) 2004-2013. The SimGrid Team.
2 * All rights reserved. */
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. */
7 #include "msg_private.h"
8 #include "msg_mailbox.h"
11 #include "xbt/sysdep.h"
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_gos, msg,
14 "Logging specific to MSG (gos)");
16 /** \ingroup msg_task_usage
17 * \brief Executes a task and waits for its termination.
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
25 msg_error_t MSG_task_execute(msg_task_t task)
27 return MSG_parallel_task_execute(task);
30 /** \ingroup msg_task_usage
31 * \brief Executes a parallel task and waits for its termination.
33 * \param task a #msg_task_t to execute on the location on which the process is running.
35 * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
36 * or #MSG_HOST_FAILURE otherwise
38 msg_error_t MSG_parallel_task_execute(msg_task_t task)
41 simdata_task_t simdata = task->simdata;
42 msg_process_t self = SIMIX_process_self();
43 simdata_process_t p_simdata = SIMIX_process_self_get_data(self);
44 e_smx_state_t comp_state;
45 msg_error_t status = MSG_OK;
48 TRACE_msg_task_execute_start(task);
51 xbt_assert((!simdata->compute) && (task->simdata->isused == 0),
52 "This task is executed somewhere else. Go fix your code! %d",
53 task->simdata->isused);
55 XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));
57 if (simdata->computation_amount == 0 && !simdata->host_nb) {
59 TRACE_msg_task_execute_end(task);
69 if (simdata->host_nb > 0) {
70 simdata->compute = simcall_host_parallel_execute(task->name,
76 XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
78 simdata->compute = simcall_host_execute(task->name,
80 simdata->computation_amount,
85 simcall_set_category(simdata->compute, task->category);
87 p_simdata->waiting_action = simdata->compute;
88 comp_state = simcall_host_execution_wait(simdata->compute);
90 p_simdata->waiting_action = NULL;
94 XBT_DEBUG("Execution task '%s' finished in state %d",
95 task->name, (int)comp_state);
100 status = MSG_TASK_CANCELED;
103 status = MSG_HOST_FAILURE;
110 /* action ended, set comm and compute = NULL, the actions is already destroyed
111 * in the main function */
112 simdata->computation_amount = 0.0;
113 simdata->comm = NULL;
114 simdata->compute = NULL;
116 TRACE_msg_task_execute_end(task);
123 /** \ingroup msg_task_usage
124 * \brief Sleep for the specified number of seconds
126 * Makes the current process sleep until \a time seconds have elapsed.
128 * \param nb_sec a number of second
130 msg_error_t MSG_process_sleep(double nb_sec)
133 msg_error_t status = MSG_OK;
134 /*msg_process_t proc = MSG_process_self();*/
137 TRACE_msg_process_sleep_in(MSG_process_self());
140 /* create action to sleep */
142 /*proc->simdata->waiting_action = act_sleep;
144 FIXME: check if not setting the waiting_action breaks something on msg
146 proc->simdata->waiting_action = NULL;*/
149 simcall_process_sleep(nb_sec);
152 switch (e.category) {
154 status = MSG_TASK_CANCELED;
163 TRACE_msg_process_sleep_out(MSG_process_self());
168 /** \ingroup msg_task_usage
169 * \brief Deprecated function that used to receive a task from a mailbox from a specific host.
171 * Sorry, this function is not supported anymore. That wouldn't be
172 * impossible to reimplement it, but we are lacking the time to do so ourselves.
173 * If you need this functionality, you can either:
175 * - implement the buffering mechanism on the user-level by queuing all messages
176 * received in the mailbox that do not match your expectation
177 * - change your application logic to leverage the mailboxes features. For example,
178 * if you have A receiving messages from B and C, you could have A waiting on
179 * mailbox "A" most of the time, but on "A#B" when it's waiting for specific
180 * messages from B and "A#C" when waiting for messages from C. You could even get A
181 * sometime waiting on all these mailboxes using @ref MSG_comm_waitany. You can find
182 * an example of use of this function in the @ref MSG_examples section.
183 * - Provide a proper patch to implement this functionality back in MSG. That wouldn't be
184 * very difficult actually. Check the function @ref MSG_mailbox_get_task_ext. During its call to
185 * simcall_comm_recv(), the 5th argument, match_fun, is NULL. Create a function that filters
186 * messages according to the host (that you will pass as sixth argument to simcall_comm_recv()
187 * and that your filtering function will receive as first parameter, and then, the filter could
188 * simply compare the host names, for example. After sufficient testing, provide an example that
189 * we could add to the distribution, and your first contribution to SimGrid is ready. Thanks in advance.
191 * \param task a memory location for storing a #msg_task_t.
192 * \param alias name of the mailbox to receive the task from
193 * \param host a #msg_host_t host from where the task was sent
196 * #MSG_OK if the task was successfully received,
197 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
200 MSG_task_receive_from_host(msg_task_t * task, const char *alias,
203 return MSG_task_receive_ext(task, alias, -1, host);
207 *\brief Deprecated function that used to receive a task from a mailbox from a specific host
208 *\brief at a given rate
210 * \param task a memory location for storing a #msg_task_t.
211 * \param alias name of the mailbox to receive the task from
212 * \param host a #msg_host_t host from where the task was sent
213 * \param rate limit the reception to rate bandwidth
216 * #MSG_OK if the task was successfully received,
217 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
220 MSG_task_receive_from_host_bounded(msg_task_t * task, const char *alias,
221 msg_host_t host, double rate)
223 return MSG_task_receive_ext_bounded(task, alias, -1, host, rate);
226 /** \ingroup msg_task_usage
227 * \brief Receives a task from a mailbox.
229 * This is a blocking function, the execution flow will be blocked
230 * until the task is received. See #MSG_task_irecv
231 * for receiving tasks asynchronously.
233 * \param task a memory location for storing a #msg_task_t.
234 * \param alias name of the mailbox to receive the task from
237 * #MSG_OK if the task was successfully received,
238 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
240 msg_error_t MSG_task_receive(msg_task_t * task, const char *alias)
242 return MSG_task_receive_with_timeout(task, alias, -1);
245 /** \ingroup msg_task_usage
246 * \brief Receives a task from a mailbox at a given rate.
248 * \param task a memory location for storing a #msg_task_t.
249 * \param alias name of the mailbox to receive the task from
250 * \param rate limit the reception to rate bandwidth
253 * #MSG_OK if the task was successfully received,
254 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
256 msg_error_t MSG_task_receive_bounded(msg_task_t * task, const char *alias, double rate)
258 return MSG_task_receive_with_timeout_bounded(task, alias, -1, rate);
261 /** \ingroup msg_task_usage
262 * \brief Receives a task from a mailbox with a given timeout.
264 * This is a blocking function with a timeout, the execution flow will be blocked
265 * until the task is received or the timeout is achieved. See #MSG_task_irecv
266 * for receiving tasks asynchronously. You can provide a -1 timeout
267 * to obtain an infinite timeout.
269 * \param task a memory location for storing a #msg_task_t.
270 * \param alias name of the mailbox to receive the task from
271 * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_receive)
274 * #MSG_OK if the task was successfully received,
275 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
278 MSG_task_receive_with_timeout(msg_task_t * task, const char *alias,
281 return MSG_task_receive_ext(task, alias, timeout, NULL);
284 /** \ingroup msg_task_usage
285 * \brief Receives a task from a mailbox with a given timeout and at a given rate.
287 * \param task a memory location for storing a #msg_task_t.
288 * \param alias name of the mailbox to receive the task from
289 * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_receive)
290 * \param rate limit the reception to rate bandwidth
293 * #MSG_OK if the task was successfully received,
294 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
297 MSG_task_receive_with_timeout_bounded(msg_task_t * task, const char *alias,
298 double timeout,double rate)
300 return MSG_task_receive_ext_bounded(task, alias, timeout, NULL,rate);
303 /** \ingroup msg_task_usage
304 * \brief Receives a task from a mailbox from a specific host with a given timeout.
306 * This is a blocking function with a timeout, the execution flow will be blocked
307 * until the task is received or the timeout is achieved. See #MSG_task_irecv
308 * for receiving tasks asynchronously. You can provide a -1 timeout
309 * to obtain an infinite timeout.
311 * \param task a memory location for storing a #msg_task_t.
312 * \param alias name of the mailbox to receive the task from
313 * \param timeout is the maximum wait time for completion (provide -1 for no timeout)
314 * \param host a #msg_host_t host from where the task was sent
317 * #MSG_OK if the task was successfully received,
318 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
321 MSG_task_receive_ext(msg_task_t * task, const char *alias, double timeout,
325 msg_error_t ret = MSG_OK;
327 ("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'",
330 ret = MSG_mailbox_get_task_ext(MSG_mailbox_get_by_alias(alias), task,
334 switch (e.category) {
335 case cancel_error: /* may be thrown by MSG_mailbox_get_by_alias */
336 ret = MSG_HOST_FAILURE;
346 /** \ingroup msg_task_usage
347 * \brief Receives a task from a mailbox from a specific host with a given timeout
348 * and at a given rate.
350 * \param task a memory location for storing a #msg_task_t.
351 * \param alias name of the mailbox to receive the task from
352 * \param timeout is the maximum wait time for completion (provide -1 for no timeout)
353 * \param host a #msg_host_t host from where the task was sent
354 * \param rate limit the reception to rate bandwidth
357 * #MSG_OK if the task was successfully received,
358 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
361 MSG_task_receive_ext_bounded(msg_task_t * task, const char *alias, double timeout,
362 msg_host_t host, double rate)
365 ("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'",
367 return MSG_mailbox_get_task_ext_bounded(MSG_mailbox_get_by_alias(alias), task,
368 host, timeout, rate);
371 /** \ingroup msg_task_usage
372 * \brief Sends a task on a mailbox.
374 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
375 * to end the communication.
377 * \param task a #msg_task_t to send on another location.
378 * \param alias name of the mailbox to sent the task to
379 * \return the msg_comm_t communication created
381 msg_comm_t MSG_task_isend(msg_task_t task, const char *alias)
383 return MSG_task_isend_with_matching(task,alias,NULL,NULL);
386 /** \ingroup msg_task_usage
387 * \brief Sends a task on a mailbox with a maximum rate
389 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
390 * to end the communication. The maxrate parameter allows the application
391 * to limit the bandwidth utilization of network links when sending the task.
393 * \param task a #msg_task_t to send on another location.
394 * \param alias name of the mailbox to sent the task to
395 * \param maxrate the maximum communication rate for sending this task .
396 * \return the msg_comm_t communication created
398 msg_comm_t MSG_task_isend_bounded(msg_task_t task, const char *alias, double maxrate)
400 task->simdata->rate = maxrate;
401 return MSG_task_isend_with_matching(task,alias,NULL,NULL);
405 /** \ingroup msg_task_usage
406 * \brief Sends a task on a mailbox, with support for matching requests
408 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
409 * to end the communication.
411 * \param task a #msg_task_t to send on another location.
412 * \param alias name of the mailbox to sent the task to
413 * \param match_fun boolean function which parameters are:
414 * - match_data_provided_here
415 * - match_data_provided_by_other_side_if_any
416 * - the_smx_action_describing_the_other_side
417 * \param match_data user provided data passed to match_fun
418 * \return the msg_comm_t communication created
420 XBT_INLINE msg_comm_t MSG_task_isend_with_matching(msg_task_t task, const char *alias,
421 int (*match_fun)(void*,void*, smx_action_t),
424 simdata_task_t t_simdata = NULL;
425 msg_process_t process = MSG_process_self();
426 msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
429 int call_end = TRACE_msg_task_put_start(task);
432 /* Prepare the task to send */
433 t_simdata = task->simdata;
434 t_simdata->sender = process;
435 t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
437 xbt_assert(t_simdata->isused == 0,
438 "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
440 t_simdata->isused = 1;
441 t_simdata->comm = NULL;
442 msg_global->sent_msg++;
444 /* Send it by calling SIMIX network layer */
445 msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
446 comm->task_sent = task;
447 comm->task_received = NULL;
448 comm->status = MSG_OK;
450 simcall_comm_isend(mailbox, t_simdata->message_size,
451 t_simdata->rate, task, sizeof(void *), match_fun, NULL, match_data, 0);
452 t_simdata->comm = comm->s_comm; /* FIXME: is the field t_simdata->comm still useful? */
454 if (TRACE_is_enabled()) {
455 simcall_set_category(comm->s_comm, task->category);
461 TRACE_msg_task_put_end();
467 /** \ingroup msg_task_usage
468 * \brief Sends a task on a mailbox.
470 * This is a non blocking detached send function.
471 * Think of it as a best effort send. Keep in mind that the third parameter
472 * is only called if the communication fails. If the communication does work,
473 * it is responsibility of the receiver code to free anything related to
474 * the task, as usual. More details on this can be obtained on
475 * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
476 * in the SimGrid-user mailing list archive.
478 * \param task a #msg_task_t to send on another location.
479 * \param alias name of the mailbox to sent the task to
480 * \param cleanup a function to destroy the task if the
481 * communication fails, e.g. MSG_task_destroy
482 * (if NULL, no function will be called)
484 void MSG_task_dsend(msg_task_t task, const char *alias, void_f_pvoid_t cleanup)
486 simdata_task_t t_simdata = NULL;
487 msg_process_t process = MSG_process_self();
488 msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
490 /* Prepare the task to send */
491 t_simdata = task->simdata;
492 t_simdata->sender = process;
493 t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
495 xbt_assert(t_simdata->isused == 0,
496 "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
498 t_simdata->isused = 1;
499 t_simdata->comm = NULL;
500 msg_global->sent_msg++;
503 int call_end = TRACE_msg_task_put_start(task);
506 /* Send it by calling SIMIX network layer */
507 smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size,
508 t_simdata->rate, task, sizeof(void *), NULL, cleanup, NULL, 1);
509 t_simdata->comm = comm;
511 if (TRACE_is_enabled()) {
512 simcall_set_category(comm, task->category);
518 TRACE_msg_task_put_end();
523 /** \ingroup msg_task_usage
524 * \brief Sends a task on a mailbox with a maximal rate.
526 * This is a non blocking detached send function.
527 * Think of it as a best effort send. Keep in mind that the third parameter
528 * is only called if the communication fails. If the communication does work,
529 * it is responsibility of the receiver code to free anything related to
530 * the task, as usual. More details on this can be obtained on
531 * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
532 * in the SimGrid-user mailing list archive.
534 * \param task a #msg_task_t to send on another location.
535 * \param alias name of the mailbox to sent the task to
536 * \param cleanup a function to destroy the task if the
537 * communication fails, e.g. MSG_task_destroy
538 * (if NULL, no function will be called)
539 * \param maxrate the maximum communication rate for sending this task
542 void MSG_task_dsend_bounded(msg_task_t task, const char *alias, void_f_pvoid_t cleanup, double maxrate)
544 task->simdata->rate = maxrate;
546 simdata_task_t t_simdata = NULL;
547 msg_process_t process = MSG_process_self();
548 msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
550 /* Prepare the task to send */
551 t_simdata = task->simdata;
552 t_simdata->sender = process;
553 t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
555 xbt_assert(t_simdata->isused == 0,
556 "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
558 t_simdata->isused = 1;
559 t_simdata->comm = NULL;
560 msg_global->sent_msg++;
563 int call_end = TRACE_msg_task_put_start(task);
566 /* Send it by calling SIMIX network layer */
567 smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size,
568 t_simdata->rate, task, sizeof(void *), NULL, cleanup, NULL, 1);
569 t_simdata->comm = comm;
571 if (TRACE_is_enabled()) {
572 simcall_set_category(comm, task->category);
578 TRACE_msg_task_put_end();
582 /** \ingroup msg_task_usage
583 * \brief Starts listening for receiving a task from an asynchronous communication.
585 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test()
586 * to end the communication.
588 * \param task a memory location for storing a #msg_task_t. has to be valid until the end of the communication.
589 * \param name of the mailbox to receive the task on
590 * \return the msg_comm_t communication created
592 msg_comm_t MSG_task_irecv(msg_task_t *task, const char *name)
594 smx_rdv_t rdv = MSG_mailbox_get_by_alias(name);
596 /* FIXME: these functions are not traceable */
599 xbt_assert(task, "Null pointer for the task storage");
603 ("MSG_task_irecv() was asked to write in a non empty task struct.");
605 /* Try to receive it by calling SIMIX network layer */
606 msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
607 comm->task_sent = NULL;
608 comm->task_received = task;
609 comm->status = MSG_OK;
610 comm->s_comm = simcall_comm_irecv(rdv, task, NULL, NULL, NULL);
615 /** \ingroup msg_task_usage
616 * \brief Starts listening for receiving a task from an asynchronous communication
619 * \param task a memory location for storing a #msg_task_t. has to be valid until the end of the communication.
620 * \param name of the mailbox to receive the task on
621 * \param rate limit the bandwidth to the given rate
622 * \return the msg_comm_t communication created
624 msg_comm_t MSG_task_irecv_bounded(msg_task_t *task, const char *name, double rate)
628 smx_rdv_t rdv = MSG_mailbox_get_by_alias(name);
630 /* FIXME: these functions are not traceable */
633 xbt_assert(task, "Null pointer for the task storage");
637 ("MSG_task_irecv() was asked to write in a non empty task struct.");
639 /* Try to receive it by calling SIMIX network layer */
640 msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
641 comm->task_sent = NULL;
642 comm->task_received = task;
643 comm->status = MSG_OK;
644 comm->s_comm = simcall_comm_irecv_bounded(rdv, task, NULL, NULL, NULL, rate);
649 /** \ingroup msg_task_usage
650 * \brief Checks whether a communication is done, and if yes, finalizes it.
651 * \param comm the communication to test
652 * \return TRUE if the communication is finished
653 * (but it may have failed, use MSG_comm_get_status() to know its status)
654 * or FALSE if the communication is not finished yet
655 * If the status is FALSE, don't forget to use MSG_process_sleep() after the test.
657 int MSG_comm_test(msg_comm_t comm)
663 finished = simcall_comm_test(comm->s_comm);
665 if (finished && comm->task_received != NULL) {
666 /* I am the receiver */
667 (*comm->task_received)->simdata->isused = 0;
671 switch (e.category) {
673 comm->status = MSG_TRANSFER_FAILURE;
678 comm->status = MSG_TIMEOUT;
691 /** \ingroup msg_task_usage
692 * \brief This function checks if a communication is finished.
693 * \param comms a vector of communications
694 * \return the position of the finished communication if any
695 * (but it may have failed, use MSG_comm_get_status() to know its status),
696 * or -1 if none is finished
698 int MSG_comm_testany(xbt_dynar_t comms)
701 int finished_index = -1;
703 /* create the equivalent dynar with SIMIX objects */
704 xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
707 xbt_dynar_foreach(comms, cursor, comm) {
708 xbt_dynar_push(s_comms, &comm->s_comm);
711 msg_error_t status = MSG_OK;
713 finished_index = simcall_comm_testany(s_comms);
716 switch (e.category) {
718 finished_index = e.value;
719 status = MSG_TRANSFER_FAILURE;
723 finished_index = e.value;
724 status = MSG_TIMEOUT;
732 xbt_dynar_free(&s_comms);
734 if (finished_index != -1) {
735 comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
736 /* the communication is finished */
737 comm->status = status;
739 if (status == MSG_OK && comm->task_received != NULL) {
740 /* I am the receiver */
741 (*comm->task_received)->simdata->isused = 0;
745 return finished_index;
748 /** \ingroup msg_task_usage
749 * \brief Destroys a communication.
750 * \param comm the communication to destroy.
752 void MSG_comm_destroy(msg_comm_t comm)
757 /** \ingroup msg_task_usage
758 * \brief Wait for the completion of a communication.
760 * It takes two parameters.
761 * \param comm the communication to wait.
762 * \param timeout Wait until the communication terminates or the timeout
763 * occurs. You can provide a -1 timeout to obtain an infinite timeout.
764 * \return msg_error_t
766 msg_error_t MSG_comm_wait(msg_comm_t comm, double timeout)
770 simcall_comm_wait(comm->s_comm, timeout);
772 if (comm->task_received != NULL) {
773 /* I am the receiver */
774 (*comm->task_received)->simdata->isused = 0;
777 /* FIXME: these functions are not traceable */
780 switch (e.category) {
782 comm->status = MSG_TRANSFER_FAILURE;
785 comm->status = MSG_TIMEOUT;
796 /** \ingroup msg_task_usage
797 * \brief This function is called by a sender and permit to wait for each communication
799 * \param comm a vector of communication
800 * \param nb_elem is the size of the comm vector
801 * \param timeout for each call of MSG_comm_wait
803 void MSG_comm_waitall(msg_comm_t * comm, int nb_elem, double timeout)
806 for (i = 0; i < nb_elem; i++) {
807 MSG_comm_wait(comm[i], timeout);
811 /** \ingroup msg_task_usage
812 * \brief This function waits for the first communication finished in a list.
813 * \param comms a vector of communications
814 * \return the position of the first finished communication
815 * (but it may have failed, use MSG_comm_get_status() to know its status)
817 int MSG_comm_waitany(xbt_dynar_t comms)
820 int finished_index = -1;
822 /* create the equivalent dynar with SIMIX objects */
823 xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
826 xbt_dynar_foreach(comms, cursor, comm) {
827 xbt_dynar_push(s_comms, &comm->s_comm);
830 msg_error_t status = MSG_OK;
832 finished_index = simcall_comm_waitany(s_comms);
835 switch (e.category) {
837 finished_index = e.value;
838 status = MSG_TRANSFER_FAILURE;
842 finished_index = e.value;
843 status = MSG_TIMEOUT;
852 xbt_assert(finished_index != -1, "WaitAny returned -1");
853 xbt_dynar_free(&s_comms);
855 comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
856 /* the communication is finished */
857 comm->status = status;
859 if (comm->task_received != NULL) {
860 /* I am the receiver */
861 (*comm->task_received)->simdata->isused = 0;
864 return finished_index;
868 * \ingroup msg_task_usage
869 * \brief Returns the error (if any) that occured during a finished communication.
870 * \param comm a finished communication
871 * \return the status of the communication, or #MSG_OK if no error occured
872 * during the communication
874 msg_error_t MSG_comm_get_status(msg_comm_t comm) {
879 /** \ingroup msg_task_usage
880 * \brief Get a task (#msg_task_t) from a communication
882 * \param comm the communication where to get the task
883 * \return the task from the communication
885 msg_task_t MSG_comm_get_task(msg_comm_t comm)
887 xbt_assert(comm, "Invalid parameter");
889 return comm->task_received ? *comm->task_received : comm->task_sent;
893 * \brief This function is called by SIMIX in kernel mode to copy the data of a comm.
894 * \param comm the comm
895 * \param buff the data copied
896 * \param buff_size size of the buffer
898 void MSG_comm_copy_data_from_SIMIX(smx_action_t comm, void* buff, size_t buff_size) {
901 SIMIX_comm_copy_pointer_callback(comm, buff, buff_size);
903 // notify the user callback if any
904 if (msg_global->task_copy_callback) {
905 msg_task_t task = buff;
906 msg_global->task_copy_callback(task,
907 simcall_comm_get_src_proc(comm), simcall_comm_get_dst_proc(comm));
911 /** \ingroup msg_task_usage
912 * \brief Sends a task to a mailbox
914 * This is a blocking function, the execution flow will be blocked
915 * until the task is sent (and received in the other side if #MSG_task_receive is used).
916 * See #MSG_task_isend for sending tasks asynchronously.
918 * \param task the task to be sent
919 * \param alias the mailbox name to where the task is sent
921 * \return Returns #MSG_OK if the task was successfully sent,
922 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
924 msg_error_t MSG_task_send(msg_task_t task, const char *alias)
926 XBT_DEBUG("MSG_task_send: Trying to send a message on mailbox '%s'", alias);
927 return MSG_task_send_with_timeout(task, alias, -1);
930 /** \ingroup msg_task_usage
931 * \brief Sends a task to a mailbox with a maximum rate
933 * This is a blocking function, the execution flow will be blocked
934 * until the task is sent. The maxrate parameter allows the application
935 * to limit the bandwidth utilization of network links when sending the task.
937 * \param task the task to be sent
938 * \param alias the mailbox name to where the task is sent
939 * \param maxrate the maximum communication rate for sending this task
941 * \return Returns #MSG_OK if the task was successfully sent,
942 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
945 MSG_task_send_bounded(msg_task_t task, const char *alias, double maxrate)
947 task->simdata->rate = maxrate;
948 return MSG_task_send(task, alias);
951 /** \ingroup msg_task_usage
952 * \brief Sends a task to a mailbox with a timeout
954 * This is a blocking function, the execution flow will be blocked
955 * until the task is sent or the timeout is achieved.
957 * \param task the task to be sent
958 * \param alias the mailbox name to where the task is sent
959 * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_send)
961 * \return Returns #MSG_OK if the task was successfully sent,
962 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
965 MSG_task_send_with_timeout(msg_task_t task, const char *alias,
968 return MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_alias(alias),
972 /** \ingroup msg_task_usage
973 * \brief Sends a task to a mailbox with a timeout and with a maximum rate
975 * This is a blocking function, the execution flow will be blocked
976 * until the task is sent or the timeout is achieved.
978 * \param task the task to be sent
979 * \param alias the mailbox name to where the task is sent
980 * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_send)
981 * \param maxrate the maximum communication rate for sending this task
983 * \return Returns #MSG_OK if the task was successfully sent,
984 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
987 MSG_task_send_with_timeout_bounded(msg_task_t task, const char *alias,
988 double timeout, double maxrate)
990 task->simdata->rate = maxrate;
991 return MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_alias(alias),
995 /** \ingroup msg_task_usage
996 * \brief Check if there is a communication going on in a mailbox.
998 * \param alias the name of the mailbox to be considered
1000 * \return Returns 1 if there is a communication, 0 otherwise
1002 int MSG_task_listen(const char *alias)
1004 return !MSG_mailbox_is_empty(MSG_mailbox_get_by_alias(alias));
1007 /** \ingroup msg_task_usage
1008 * \brief Check the number of communication actions of a given host pending in a mailbox.
1010 * \param alias the name of the mailbox to be considered
1011 * \param host the host to check for communication
1013 * \return Returns the number of pending communication actions of the host in the
1014 * given mailbox, 0 if there is no pending communication actions.
1017 int MSG_task_listen_from_host(const char *alias, msg_host_t host)
1020 MSG_mailbox_get_count_host_waiting_tasks(MSG_mailbox_get_by_alias
1024 /** \ingroup msg_task_usage
1025 * \brief Look if there is a communication on a mailbox and return the
1026 * PID of the sender process.
1028 * \param alias the name of the mailbox to be considered
1030 * \return Returns the PID of sender process,
1031 * -1 if there is no communication in the mailbox.
1033 int MSG_task_listen_from(const char *alias)
1038 (task = MSG_mailbox_get_head(MSG_mailbox_get_by_alias(alias))))
1041 return MSG_process_get_PID(task->simdata->sender);
1044 /** \ingroup msg_task_usage
1045 * \brief Sets the tracing category of a task.
1047 * This function should be called after the creation of
1048 * a MSG task, to define the category of that task. The
1049 * first parameter task must contain a task that was
1050 * created with the function #MSG_task_create. The second
1051 * parameter category must contain a category that was
1052 * previously declared with the function #TRACE_category
1053 * (or with #TRACE_category_with_color).
1055 * See \ref tracing for details on how to trace
1056 * the (categorized) resource utilization.
1058 * \param task the task that is going to be categorized
1059 * \param category the name of the category to be associated to the task
1061 * \see MSG_task_get_category, TRACE_category, TRACE_category_with_color
1063 void MSG_task_set_category (msg_task_t task, const char *category)
1066 TRACE_msg_set_task_category (task, category);
1070 /** \ingroup msg_task_usage
1072 * \brief Gets the current tracing category of a task.
1074 * \param task the task to be considered
1076 * \see MSG_task_set_category
1078 * \return Returns the name of the tracing category of the given task, NULL otherwise
1080 const char *MSG_task_get_category (msg_task_t task)
1083 return task->category;
1090 * \brief Returns the value of a given AS or router property
1092 * \param asr the name of a router or AS
1093 * \param name a property name
1094 * \return value of a property (or NULL if property not set)
1096 const char *MSG_as_router_get_property_value(const char* asr, const char *name)
1098 return xbt_dict_get_or_null(MSG_as_router_get_properties(asr), name);
1102 * \brief Returns a xbt_dict_t consisting of the list of properties assigned to
1103 * a the AS or router
1105 * \param asr the name of a router or AS
1106 * \return a dict containing the properties
1108 xbt_dict_t MSG_as_router_get_properties(const char* asr)
1110 return (simcall_asr_get_properties(asr));
1114 * \brief Change the value of a given AS or router
1116 * \param asr the name of a router or AS
1117 * \param name a property name
1118 * \param value what to change the property to
1119 * \param free_ctn the freeing function to use to kill the value on need
1121 void MSG_as_router_set_property_value(const char* asr, const char *name, char *value,void_f_pvoid_t free_ctn) {
1122 xbt_dict_set(MSG_as_router_get_properties(asr), name, value,free_ctn);
1125 #ifdef MSG_USE_DEPRECATED
1126 /** \ingroup msg_deprecated_functions
1128 * \brief Return the last value returned by a MSG function (except
1129 * MSG_get_errno...).
1131 msg_error_t MSG_get_errno(void)
1133 return PROCESS_GET_ERRNO();
1136 /** \ingroup msg_deprecated_functions
1137 * \brief Put a task on a channel of an host and waits for the end of the
1140 * This function is used for describing the behavior of a process. It
1141 * takes three parameter.
1142 * \param task a #msg_task_t to send on another location. This task
1143 will not be usable anymore when the function will return. There is
1144 no automatic task duplication and you have to save your parameters
1145 before calling this function. Tasks are unique and once it has been
1146 sent to another location, you should not access it anymore. You do
1147 not need to call MSG_task_destroy() but to avoid using, as an
1148 effect of inattention, this task anymore, you definitely should
1149 renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
1150 can be transfered iff it has been correctly created with
1152 * \param dest the destination of the message
1153 * \param channel the channel on which the process should put this
1154 task. This value has to be >=0 and < than the maximal number of
1155 channels fixed with MSG_set_channel_number().
1156 * \return #MSG_HOST_FAILURE if the host on which
1157 * this function was called was shut down,
1158 * #MSG_TRANSFER_FAILURE if the transfer could not be properly done
1159 * (network failure, dest failure) or #MSG_OK if it succeeded.
1161 msg_error_t MSG_task_put(msg_task_t task, msg_host_t dest, m_channel_t channel)
1163 XBT_WARN("DEPRECATED! Now use MSG_task_send");
1164 return MSG_task_put_with_timeout(task, dest, channel, -1.0);
1167 /** \ingroup msg_deprecated_functions
1168 * \brief Does exactly the same as MSG_task_put but with a bounded transmition
1174 MSG_task_put_bounded(msg_task_t task, msg_host_t dest, m_channel_t channel,
1177 XBT_WARN("DEPRECATED! Now use MSG_task_send_bounded");
1178 task->simdata->rate = maxrate;
1179 return MSG_task_put(task, dest, channel);
1182 /** \ingroup msg_deprecated_functions
1184 * \brief Put a task on a channel of an
1185 * host (with a timeout on the waiting of the destination host) and
1186 * waits for the end of the transmission.
1188 * This function is used for describing the behavior of a process. It
1189 * takes four parameter.
1190 * \param task a #msg_task_t to send on another location. This task
1191 will not be usable anymore when the function will return. There is
1192 no automatic task duplication and you have to save your parameters
1193 before calling this function. Tasks are unique and once it has been
1194 sent to another location, you should not access it anymore. You do
1195 not need to call MSG_task_destroy() but to avoid using, as an
1196 effect of inattention, this task anymore, you definitely should
1197 renitialize it with #MSG_TASK_UNINITIALIZED. Note that this task
1198 can be transfered iff it has been correctly created with
1200 * \param dest the destination of the message
1201 * \param channel the channel on which the process should put this
1202 task. This value has to be >=0 and < than the maximal number of
1203 channels fixed with MSG_set_channel_number().
1204 * \param timeout the maximum time to wait for a task before giving
1205 up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
1206 will not be modified
1207 * \return #MSG_HOST_FAILURE if the host on which
1208 this function was called was shut down,
1209 #MSG_TRANSFER_FAILURE if the transfer could not be properly done
1210 (network failure, dest failure, timeout...) or #MSG_OK if the communication succeeded.
1213 MSG_task_put_with_timeout(msg_task_t task, msg_host_t dest,
1214 m_channel_t channel, double timeout)
1216 XBT_WARN("DEPRECATED! Now use MSG_task_send_with_timeout");
1217 xbt_assert((channel >= 0)
1218 && (channel < msg_global->max_channel), "Invalid channel %d",
1221 XBT_DEBUG("MSG_task_put_with_timout: Trying to send a task to '%s'", SIMIX_host_get_name(dest->smx_host));
1223 MSG_mailbox_put_with_timeout(MSG_mailbox_get_by_channel
1224 (dest, channel), task, timeout);
1227 /** \ingroup msg_deprecated_functions
1228 * \brief Test whether there is a pending communication on a channel, and who sent it.
1230 * It takes one parameter.
1231 * \param channel the channel on which the process should be
1232 listening. This value has to be >=0 and < than the maximal
1233 number of channels fixed with MSG_set_channel_number().
1234 * \return -1 if there is no pending communication and the PID of the process who sent it otherwise
1236 int MSG_task_probe_from(m_channel_t channel)
1238 XBT_WARN("DEPRECATED! Now use MSG_task_listen_from");
1241 xbt_assert((channel >= 0)
1242 && (channel < msg_global->max_channel), "Invalid channel %d",
1247 MSG_mailbox_get_head(MSG_mailbox_get_by_channel
1248 (MSG_host_self(), channel))))
1251 return MSG_process_get_PID(task->simdata->sender);
1254 /** \ingroup msg_deprecated_functions
1255 * \brief Test whether there is a pending communication on a channel.
1257 * It takes one parameter.
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 * \return 1 if there is a pending communication and 0 otherwise
1263 int MSG_task_Iprobe(m_channel_t channel)
1265 XBT_WARN("DEPRECATED!");
1266 xbt_assert((channel >= 0)
1267 && (channel < msg_global->max_channel), "Invalid channel %d",
1271 !MSG_mailbox_is_empty(MSG_mailbox_get_by_channel
1272 (MSG_host_self(), channel));
1275 /** \ingroup msg_deprecated_functions
1277 * \brief Return the number of tasks waiting to be received on a \a
1278 channel and sent by \a host.
1280 * It takes two parameters.
1281 * \param channel the channel on which the process should be
1282 listening. This value has to be >=0 and < than the maximal
1283 number of channels fixed with MSG_set_channel_number().
1284 * \param host the host that is to be watched.
1285 * \return the number of tasks waiting to be received on \a channel
1286 and sent by \a host.
1288 int MSG_task_probe_from_host(int channel, msg_host_t host)
1290 XBT_WARN("DEPRECATED! Now use MSG_task_listen_from_host");
1291 xbt_assert((channel >= 0)
1292 && (channel < msg_global->max_channel), "Invalid channel %d",
1296 MSG_mailbox_get_count_host_waiting_tasks(MSG_mailbox_get_by_channel
1297 (MSG_host_self(), channel),
1302 /** \ingroup msg_deprecated_functions
1303 * \brief Listen on \a channel and waits for receiving a task from \a host.
1305 * It takes three parameters.
1306 * \param task a memory location for storing a #msg_task_t. It will
1307 hold a task when this function will return. Thus \a task should not
1308 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1309 those two condition does not hold, there will be a warning message.
1310 * \param channel the channel on which the process should be
1311 listening. This value has to be >=0 and < than the maximal
1312 number of channels fixed with MSG_set_channel_number().
1313 * \param host the host that is to be watched.
1314 * \return a #msg_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1317 MSG_task_get_from_host(msg_task_t * task, m_channel_t channel, msg_host_t host)
1319 XBT_WARN("DEPRECATED! Now use MSG_task_receive_from_host");
1320 return MSG_task_get_ext(task, channel, -1, host);
1323 /** \ingroup msg_deprecated_functions
1324 * \brief Listen on a channel and wait for receiving a task.
1326 * It takes two parameters.
1327 * \param task a memory location for storing a #msg_task_t. It will
1328 hold a task when this function will return. Thus \a task should not
1329 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1330 those two condition does not hold, there will be a warning message.
1331 * \param channel the channel on which the process should be
1332 listening. This value has to be >=0 and < than the maximal
1333 number of channels fixed with MSG_set_channel_number().
1334 * \return a #msg_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1336 msg_error_t MSG_task_get(msg_task_t * task, m_channel_t channel)
1338 XBT_WARN("DEPRECATED! Now use MSG_task_receive");
1339 return MSG_task_get_with_timeout(task, channel, -1);
1342 /** \ingroup msg_deprecated_functions
1343 * \brief Listen on a channel and wait for receiving a task with a timeout.
1345 * It takes three parameters.
1346 * \param task a memory location for storing a #msg_task_t. It will
1347 hold a task when this function will return. Thus \a task should not
1348 be equal to \c NULL and \a *task should be equal to \c NULL. If one of
1349 those two condition does not hold, there will be a warning message.
1350 * \param channel the channel on which the process should be
1351 listening. This value has to be >=0 and < than the maximal
1352 number of channels fixed with MSG_set_channel_number().
1353 * \param max_duration the maximum time to wait for a task before giving
1354 up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
1355 will not be modified and will still be
1356 equal to \c NULL when returning.
1357 * \return a #msg_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
1360 MSG_task_get_with_timeout(msg_task_t * task, m_channel_t channel,
1361 double max_duration)
1363 XBT_WARN("DEPRECATED! Now use MSG_task_receive_with_timeout");
1364 return MSG_task_get_ext(task, channel, max_duration, NULL);
1368 MSG_task_get_ext(msg_task_t * task, m_channel_t channel, double timeout,
1371 XBT_WARN("DEPRECATED! Now use MSG_task_receive_ext");
1372 xbt_assert((channel >= 0)
1373 && (channel < msg_global->max_channel), "Invalid channel %d",
1377 MSG_mailbox_get_task_ext(MSG_mailbox_get_by_channel
1378 (MSG_host_self(), channel), task, host,