1 /* Copyright (c) 2004-2016. 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 "src/simix/smx_private.h" /* MSG_task_listen looks inside the rdv directly. Not clean. */
7 #include "msg_private.h"
10 #include "xbt/sysdep.h"
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_gos, msg,
13 "Logging specific to MSG (gos)");
15 /** \ingroup msg_task_usage
16 * \brief Executes a task and waits for its termination.
18 * This function is used for describing the behavior of a process. It takes only one parameter.
19 * \param task a #msg_task_t to execute on the location on which the process is running.
20 * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED or #MSG_HOST_FAILURE otherwise
22 msg_error_t MSG_task_execute(msg_task_t task)
24 /* TODO: add this to other locations */
25 msg_host_t host = MSG_process_get_host(MSG_process_self());
26 MSG_host_add_task(host, task);
28 msg_error_t ret = MSG_parallel_task_execute(task);
30 MSG_host_del_task(host, task);
35 /** \ingroup msg_task_usage
36 * \brief Executes a parallel task and waits for its termination.
38 * \param task a #msg_task_t to execute on the location on which the process is running.
40 * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
41 * or #MSG_HOST_FAILURE otherwise
43 msg_error_t MSG_parallel_task_execute(msg_task_t task)
46 simdata_task_t simdata = task->simdata;
47 simdata_process_t p_simdata = (simdata_process_t) SIMIX_process_self_get_data();
48 e_smx_state_t comp_state;
49 msg_error_t status = MSG_OK;
51 TRACE_msg_task_execute_start(task);
53 xbt_assert((!simdata->compute) && (task->simdata->isused == 0),
54 "This task is executed somewhere else. Go fix your code! %d", task->simdata->isused!=NULL);
56 XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));
58 if (simdata->flops_amount == 0 && !simdata->host_nb) {
59 TRACE_msg_task_execute_end(task);
64 if (msg_global->debug_multiple_use)
65 MSG_BT(simdata->isused, "Using Backtrace");
67 simdata->isused = (void*)1;
69 if (simdata->host_nb > 0) {
70 simdata->compute = static_cast<simgrid::simix::Exec*>(
71 simcall_execution_parallel_start(task->name, simdata->host_nb,simdata->host_list,
72 simdata->flops_parallel_amount, simdata->bytes_parallel_amount,
74 XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
76 unsigned long affinity_mask =
77 (unsigned long)(uintptr_t) xbt_dict_get_or_null_ext(simdata->affinity_mask_db, (char *) p_simdata->m_host,
79 XBT_DEBUG("execute %s@%s with affinity(0x%04lx)",
80 MSG_task_get_name(task), MSG_host_get_name(p_simdata->m_host), affinity_mask);
82 simdata->compute = static_cast<simgrid::simix::Exec*>(
83 simcall_execution_start(task->name, simdata->flops_amount, simdata->priority,
84 simdata->bound, affinity_mask));
86 simcall_set_category(simdata->compute, task->category);
87 p_simdata->waiting_action = simdata->compute;
88 comp_state = simcall_execution_wait(simdata->compute);
90 p_simdata->waiting_action = NULL;
92 if (msg_global->debug_multiple_use && simdata->isused!=0)
93 xbt_ex_free(*(xbt_ex_t*)simdata->isused);
96 XBT_DEBUG("Execution task '%s' finished in state %d", task->name, (int)comp_state);
101 status = MSG_TASK_CANCELED;
104 status = MSG_HOST_FAILURE;
111 /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
112 simdata->flops_amount = 0.0;
113 simdata->comm = NULL;
114 simdata->compute = NULL;
115 TRACE_msg_task_execute_end(task);
120 /** \ingroup msg_task_usage
121 * \brief Sleep for the specified number of seconds
123 * Makes the current process sleep until \a time seconds have elapsed.
125 * \param nb_sec a number of second
127 msg_error_t MSG_process_sleep(double nb_sec)
130 msg_error_t status = MSG_OK;
131 /*msg_process_t proc = MSG_process_self();*/
133 TRACE_msg_process_sleep_in(MSG_process_self());
136 simcall_process_sleep(nb_sec);
139 switch (e.category) {
141 XBT_DEBUG("According to the JAVA API, a sleep call should only deal with HostFailureException, WTF here ?");
142 // adsein: MSG_TASK_CANCELED is assigned when someone kills the process that made the sleep, this is not
143 // correct. For instance, when the node is turned off, the error should be MSG_HOST_FAILURE, which is by the way
144 // and according to the JAVA document, the only exception that can be triggered by MSG_Process_sleep call.
145 // To avoid possible impacts in the code, I just raised a host_failure exception for the moment in the JAVA code
146 // and did not change anythings at the C level.
147 // See comment in the jmsg_process.c file, function JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_sleep(JNIEnv *env, jclass cls, jlong jmillis, jint jnanos)
148 status = MSG_TASK_CANCELED;
156 TRACE_msg_process_sleep_out(MSG_process_self());
160 /** \ingroup msg_task_usage
161 * \brief Receives a task from a mailbox.
163 * This is a blocking function, the execution flow will be blocked until the task is received. See #MSG_task_irecv
164 * for receiving tasks asynchronously.
166 * \param task a memory location for storing a #msg_task_t.
167 * \param alias name of the mailbox to receive the task from
170 * #MSG_OK if the task was successfully received,
171 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
173 msg_error_t MSG_task_receive(msg_task_t * task, const char *alias)
175 return MSG_task_receive_with_timeout(task, alias, -1);
178 /** \ingroup msg_task_usage
179 * \brief Receives a task from a mailbox at a given rate.
181 * \param task a memory location for storing a #msg_task_t.
182 * \param alias name of the mailbox to receive the task from
183 * \param rate limit the reception to rate bandwidth
186 * #MSG_OK if the task was successfully received,
187 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
189 msg_error_t MSG_task_receive_bounded(msg_task_t * task, const char *alias, double rate)
191 return MSG_task_receive_with_timeout_bounded(task, alias, -1, rate);
194 /** \ingroup msg_task_usage
195 * \brief Receives a task from a mailbox with a given timeout.
197 * This is a blocking function with a timeout, the execution flow will be blocked until the task is received or the
198 * timeout is achieved. See #MSG_task_irecv for receiving tasks asynchronously. You can provide a -1 timeout
199 * to obtain an infinite timeout.
201 * \param task a memory location for storing a #msg_task_t.
202 * \param alias name of the mailbox to receive the task from
203 * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_receive)
206 * #MSG_OK if the task was successfully received,
207 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
209 msg_error_t MSG_task_receive_with_timeout(msg_task_t * task, const char *alias, double timeout)
211 return MSG_task_receive_ext(task, alias, timeout, NULL);
214 /** \ingroup msg_task_usage
215 * \brief Receives a task from a mailbox with a given timeout and at a given rate.
217 * \param task a memory location for storing a #msg_task_t.
218 * \param alias name of the mailbox to receive the task from
219 * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_receive)
220 * \param rate limit the reception to rate bandwidth
223 * #MSG_OK if the task was successfully received,
224 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
226 msg_error_t MSG_task_receive_with_timeout_bounded(msg_task_t * task, const char *alias, double timeout,double rate)
228 return MSG_task_receive_ext_bounded(task, alias, timeout, NULL, rate);
231 /** \ingroup msg_task_usage
232 * \brief Receives a task from a mailbox from a specific host with a given timeout.
234 * This is a blocking function with a timeout, the execution flow will be blocked until the task is received or the
235 * timeout is achieved. See #MSG_task_irecv for receiving tasks asynchronously. You can provide a -1 timeout
236 * to obtain an infinite timeout.
238 * \param task a memory location for storing a #msg_task_t.
239 * \param alias name of the mailbox to receive the task from
240 * \param timeout is the maximum wait time for completion (provide -1 for no timeout)
241 * \param host a #msg_host_t host from where the task was sent
244 * #MSG_OK if the task was successfully received,
245 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
247 msg_error_t MSG_task_receive_ext(msg_task_t * task, const char *alias, double timeout, msg_host_t host)
250 msg_error_t ret = MSG_OK;
251 XBT_DEBUG("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'", alias);
253 ret = MSG_mailbox_get_task_ext(MSG_mailbox_get_by_alias(alias), task, host, timeout);
256 switch (e.category) {
257 case cancel_error: /* may be thrown by MSG_mailbox_get_by_alias */
258 ret = MSG_HOST_FAILURE;
268 /** \ingroup msg_task_usage
269 * \brief Receives a task from a mailbox from a specific host with a given timeout and at a given rate.
271 * \param task a memory location for storing a #msg_task_t.
272 * \param alias name of the mailbox to receive the task from
273 * \param timeout is the maximum wait time for completion (provide -1 for no timeout)
274 * \param host a #msg_host_t host from where the task was sent
275 * \param rate limit the reception to rate bandwidth
278 * #MSG_OK if the task was successfully received,
279 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
281 msg_error_t MSG_task_receive_ext_bounded(msg_task_t * task, const char *alias, double timeout, msg_host_t host,
284 XBT_DEBUG("MSG_task_receive_ext: Trying to receive a message on mailbox '%s'", alias);
285 return MSG_mailbox_get_task_ext_bounded(MSG_mailbox_get_by_alias(alias), task, host, timeout, rate);
288 /* Internal function used to factorize code between MSG_task_isend_with_matching() and MSG_task_dsend(). */
289 static inline msg_comm_t MSG_task_isend_internal(msg_task_t task, const char *alias,
290 int (*match_fun)(void*,void*, smx_synchro_t),
291 void *match_data, void_f_pvoid_t cleanup, int detached)
293 simdata_task_t t_simdata = NULL;
294 msg_process_t process = MSG_process_self();
295 msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
296 int call_end = TRACE_msg_task_put_start(task);
298 /* Prepare the task to send */
299 t_simdata = task->simdata;
300 t_simdata->sender = process;
301 t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data())->m_host;
303 if (t_simdata->isused != 0) {
304 if (msg_global->debug_multiple_use){
305 XBT_ERROR("This task is already used in there:");
306 xbt_backtrace_display((xbt_ex_t*) t_simdata->isused);
307 XBT_ERROR("And you try to reuse it from here:");
308 xbt_backtrace_display_current();
310 xbt_assert(t_simdata->isused == 0,
311 "This task is still being used somewhere else. You cannot send it now. Go fix your code!"
312 "(use --cfg=msg/debug-multiple-use:on to get the backtrace of the other process)");
316 if (msg_global->debug_multiple_use)
317 MSG_BT(t_simdata->isused, "Using Backtrace");
319 t_simdata->isused = (void*)1;
320 t_simdata->comm = NULL;
321 msg_global->sent_msg++;
323 /* Send it by calling SIMIX network layer */
324 smx_synchro_t act = simcall_comm_isend(SIMIX_process_self(), mailbox, t_simdata->bytes_amount, t_simdata->rate,
325 task, sizeof(void *), match_fun, cleanup, NULL, match_data,detached);
326 t_simdata->comm = static_cast<simgrid::simix::Comm*>(act); /* FIXME: is the field t_simdata->comm still useful? */
332 comm = xbt_new0(s_msg_comm_t, 1);
333 comm->task_sent = task;
334 comm->task_received = NULL;
335 comm->status = MSG_OK;
339 if (TRACE_is_enabled())
340 simcall_set_category(act, task->category);
342 TRACE_msg_task_put_end();
347 /** \ingroup msg_task_usage
348 * \brief Sends a task on a mailbox.
350 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test() to end the communication.
352 * \param task a #msg_task_t to send on another location.
353 * \param alias name of the mailbox to sent the task to
354 * \return the msg_comm_t communication created
356 msg_comm_t MSG_task_isend(msg_task_t task, const char *alias)
358 return MSG_task_isend_internal(task, alias, NULL, NULL, NULL, 0);
361 /** \ingroup msg_task_usage
362 * \brief Sends a task on a mailbox with a maximum rate
364 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test() to end the communication. The maxrate
365 * parameter allows the application to limit the bandwidth utilization of network links when sending the task.
367 * \param task a #msg_task_t to send on another location.
368 * \param alias name of the mailbox to sent the task to
369 * \param maxrate the maximum communication rate for sending this task .
370 * \return the msg_comm_t communication created
372 msg_comm_t MSG_task_isend_bounded(msg_task_t task, const char *alias, double maxrate)
374 task->simdata->rate = maxrate;
375 return MSG_task_isend_internal(task, alias, NULL, NULL, NULL, 0);
378 /** \ingroup msg_task_usage
379 * \brief Sends a task on a mailbox, with support for matching requests
381 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test() to end the communication.
383 * \param task a #msg_task_t to send on another location.
384 * \param alias name of the mailbox to sent the task to
385 * \param match_fun boolean function which parameters are:
386 * - match_data_provided_here
387 * - match_data_provided_by_other_side_if_any
388 * - the_smx_synchro_describing_the_other_side
389 * \param match_data user provided data passed to match_fun
390 * \return the msg_comm_t communication created
392 msg_comm_t MSG_task_isend_with_matching(msg_task_t task, const char *alias,
393 int (*match_fun)(void*, void*, smx_synchro_t), void *match_data)
395 return MSG_task_isend_internal(task, alias, match_fun, match_data, NULL, 0);
398 /** \ingroup msg_task_usage
399 * \brief Sends a task on a mailbox.
401 * This is a non blocking detached send function.
402 * Think of it as a best effort send. Keep in mind that the third parameter is only called if the communication fails.
403 * If the communication does work, it is responsibility of the receiver code to free anything related to the task, as
404 * usual. More details on this can be obtained on
405 * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
406 * in the SimGrid-user mailing list archive.
408 * \param task a #msg_task_t to send on another location.
409 * \param alias name of the mailbox to sent the task to
410 * \param cleanup a function to destroy the task if the communication fails, e.g. MSG_task_destroy
411 * (if NULL, no function will be called)
413 void MSG_task_dsend(msg_task_t task, const char *alias, void_f_pvoid_t cleanup)
415 MSG_task_isend_internal(task, alias, NULL, NULL, cleanup, 1);
418 /** \ingroup msg_task_usage
419 * \brief Sends a task on a mailbox with a maximal rate.
421 * This is a non blocking detached send function.
422 * Think of it as a best effort send. Keep in mind that the third parameter is only called if the communication fails.
423 * If the communication does work, it is responsibility of the receiver code to free anything related to the task, as
424 * usual. More details on this can be obtained on
425 * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
426 * in the SimGrid-user mailing list archive.
428 * \param task a #msg_task_t to send on another location.
429 * \param alias name of the mailbox to sent the task to
430 * \param cleanup a function to destroy the task if the
431 * communication fails, e.g. MSG_task_destroy
432 * (if NULL, no function will be called)
433 * \param maxrate the maximum communication rate for sending this task
436 void MSG_task_dsend_bounded(msg_task_t task, const char *alias, void_f_pvoid_t cleanup, double maxrate)
438 task->simdata->rate = maxrate;
439 MSG_task_dsend(task, alias, cleanup);
442 /** \ingroup msg_task_usage
443 * \brief Starts listening for receiving a task from an asynchronous communication.
445 * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test() to end the communication.
447 * \param task a memory location for storing a #msg_task_t. has to be valid until the end of the communication.
448 * \param name of the mailbox to receive the task on
449 * \return the msg_comm_t communication created
451 msg_comm_t MSG_task_irecv(msg_task_t *task, const char *name)
453 return MSG_task_irecv_bounded(task, name, -1.0);
456 /** \ingroup msg_task_usage
457 * \brief Starts listening for receiving a task from an asynchronous communication at a given rate.
459 * \param task a memory location for storing a #msg_task_t. has to be valid until the end of the communication.
460 * \param name of the mailbox to receive the task on
461 * \param rate limit the bandwidth to the given rate
462 * \return the msg_comm_t communication created
464 msg_comm_t MSG_task_irecv_bounded(msg_task_t *task, const char *name, double rate)
466 smx_mailbox_t rdv = MSG_mailbox_get_by_alias(name);
468 /* FIXME: these functions are not traceable */
470 xbt_assert(task, "Null pointer for the task storage");
473 XBT_CRITICAL("MSG_task_irecv() was asked to write in a non empty task struct.");
475 /* Try to receive it by calling SIMIX network layer */
476 msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
477 comm->task_sent = NULL;
478 comm->task_received = task;
479 comm->status = MSG_OK;
480 comm->s_comm = simcall_comm_irecv(MSG_process_self(), rdv, task, NULL, NULL, NULL, NULL, rate);
485 /** \ingroup msg_task_usage
486 * \brief Checks whether a communication is done, and if yes, finalizes it.
487 * \param comm the communication to test
488 * \return TRUE if the communication is finished
489 * (but it may have failed, use MSG_comm_get_status() to know its status)
490 * or FALSE if the communication is not finished yet
491 * If the status is FALSE, don't forget to use MSG_process_sleep() after the test.
493 int MSG_comm_test(msg_comm_t comm)
499 finished = simcall_comm_test(comm->s_comm);
501 if (finished && comm->task_received != NULL) {
502 /* I am the receiver */
503 if (msg_global->debug_multiple_use && (*comm->task_received)->simdata->isused!=0)
504 xbt_ex_free(*(xbt_ex_t*)(*comm->task_received)->simdata->isused);
505 (*comm->task_received)->simdata->isused = 0;
509 switch (e.category) {
511 comm->status = MSG_TRANSFER_FAILURE;
515 comm->status = MSG_TIMEOUT;
527 /** \ingroup msg_task_usage
528 * \brief This function checks if a communication is finished.
529 * \param comms a vector of communications
530 * \return the position of the finished communication if any
531 * (but it may have failed, use MSG_comm_get_status() to know its status),
532 * or -1 if none is finished
534 int MSG_comm_testany(xbt_dynar_t comms)
537 int finished_index = -1;
539 /* create the equivalent dynar with SIMIX objects */
540 xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_synchro_t), NULL);
543 xbt_dynar_foreach(comms, cursor, comm) {
544 xbt_dynar_push(s_comms, &comm->s_comm);
547 msg_error_t status = MSG_OK;
549 finished_index = simcall_comm_testany(s_comms);
552 switch (e.category) {
554 finished_index = e.value;
555 status = MSG_TRANSFER_FAILURE;
558 finished_index = e.value;
559 status = MSG_TIMEOUT;
566 xbt_dynar_free(&s_comms);
568 if (finished_index != -1) {
569 comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
570 /* the communication is finished */
571 comm->status = status;
573 if (status == MSG_OK && comm->task_received != NULL) {
574 /* I am the receiver */
575 if (msg_global->debug_multiple_use && (*comm->task_received)->simdata->isused!=0)
576 xbt_ex_free(*(xbt_ex_t*)(*comm->task_received)->simdata->isused);
577 (*comm->task_received)->simdata->isused = 0;
581 return finished_index;
584 /** \ingroup msg_task_usage
585 * \brief Destroys a communication.
586 * \param comm the communication to destroy.
588 void MSG_comm_destroy(msg_comm_t comm)
593 /** \ingroup msg_task_usage
594 * \brief Wait for the completion of a communication.
596 * It takes two parameters.
597 * \param comm the communication to wait.
598 * \param timeout Wait until the communication terminates or the timeout occurs.
599 * You can provide a -1 timeout to obtain an infinite timeout.
600 * \return msg_error_t
602 msg_error_t MSG_comm_wait(msg_comm_t comm, double timeout)
606 simcall_comm_wait(comm->s_comm, timeout);
608 if (comm->task_received != NULL) {
609 /* I am the receiver */
610 if (msg_global->debug_multiple_use && (*comm->task_received)->simdata->isused!=0)
611 xbt_ex_free(*(xbt_ex_t*)(*comm->task_received)->simdata->isused);
612 (*comm->task_received)->simdata->isused = 0;
615 /* FIXME: these functions are not traceable */
618 switch (e.category) {
620 comm->status = MSG_TRANSFER_FAILURE;
623 comm->status = MSG_TIMEOUT;
634 /** \ingroup msg_task_usage
635 * \brief This function is called by a sender and permit to wait for each communication
637 * \param comm a vector of communication
638 * \param nb_elem is the size of the comm vector
639 * \param timeout for each call of MSG_comm_wait
641 void MSG_comm_waitall(msg_comm_t * comm, int nb_elem, double timeout)
644 for (i = 0; i < nb_elem; i++) {
645 MSG_comm_wait(comm[i], timeout);
649 /** \ingroup msg_task_usage
650 * \brief This function waits for the first communication finished in a list.
651 * \param comms a vector of communications
652 * \return the position of the first finished communication
653 * (but it may have failed, use MSG_comm_get_status() to know its status)
655 int MSG_comm_waitany(xbt_dynar_t comms)
658 int finished_index = -1;
660 /* create the equivalent dynar with SIMIX objects */
661 xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_synchro_t), NULL);
664 xbt_dynar_foreach(comms, cursor, comm) {
665 xbt_dynar_push(s_comms, &comm->s_comm);
668 msg_error_t status = MSG_OK;
670 finished_index = simcall_comm_waitany(s_comms);
673 switch (e.category) {
675 finished_index = e.value;
676 status = MSG_TRANSFER_FAILURE;
679 finished_index = e.value;
680 status = MSG_TIMEOUT;
688 xbt_assert(finished_index != -1, "WaitAny returned -1");
689 xbt_dynar_free(&s_comms);
691 comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
692 /* the communication is finished */
693 comm->status = status;
695 if (comm->task_received != NULL) {
696 /* I am the receiver */
697 if (msg_global->debug_multiple_use && (*comm->task_received)->simdata->isused!=0)
698 xbt_ex_free(*(xbt_ex_t*)(*comm->task_received)->simdata->isused);
699 (*comm->task_received)->simdata->isused = 0;
702 return finished_index;
706 * \ingroup msg_task_usage
707 * \brief Returns the error (if any) that occurred during a finished communication.
708 * \param comm a finished communication
709 * \return the status of the communication, or #MSG_OK if no error occurred
710 * during the communication
712 msg_error_t MSG_comm_get_status(msg_comm_t comm) {
717 /** \ingroup msg_task_usage
718 * \brief Get a task (#msg_task_t) from a communication
720 * \param comm the communication where to get the task
721 * \return the task from the communication
723 msg_task_t MSG_comm_get_task(msg_comm_t comm)
725 xbt_assert(comm, "Invalid parameter");
727 return comm->task_received ? *comm->task_received : comm->task_sent;
731 * \brief This function is called by SIMIX in kernel mode to copy the data of a comm.
732 * \param comm the comm
733 * \param buff the data copied
734 * \param buff_size size of the buffer
736 void MSG_comm_copy_data_from_SIMIX(smx_synchro_t synchro, void* buff, size_t buff_size)
738 simgrid::simix::Comm *comm = static_cast<simgrid::simix::Comm*>(synchro);
740 SIMIX_comm_copy_pointer_callback(comm, buff, buff_size);
742 // notify the user callback if any
743 if (msg_global->task_copy_callback) {
744 msg_task_t task = (msg_task_t) buff;
745 msg_global->task_copy_callback(task, comm->src_proc, comm->dst_proc);
749 /** \ingroup msg_task_usage
750 * \brief Sends a task to a mailbox
752 * This is a blocking function, the execution flow will be blocked until the task is sent (and received on the other
753 * side if #MSG_task_receive is used).
754 * See #MSG_task_isend for sending tasks asynchronously.
756 * \param task the task to be sent
757 * \param alias the mailbox name to where the task is sent
759 * \return Returns #MSG_OK if the task was successfully sent,
760 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
762 msg_error_t MSG_task_send(msg_task_t task, const char *alias)
764 XBT_DEBUG("MSG_task_send: Trying to send a message on mailbox '%s'", alias);
765 return MSG_task_send_with_timeout(task, alias, -1);
768 /** \ingroup msg_task_usage
769 * \brief Sends a task to a mailbox with a maximum rate
771 * This is a blocking function, the execution flow will be blocked until the task is sent. The maxrate parameter allows
772 * the application to limit the bandwidth utilization of network links when sending the task.
774 * \param task the task to be sent
775 * \param alias the mailbox name to where the task is sent
776 * \param maxrate the maximum communication rate for sending this task
778 * \return Returns #MSG_OK if the task was successfully sent,
779 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE otherwise.
781 msg_error_t MSG_task_send_bounded(msg_task_t task, const char *alias, double maxrate)
783 task->simdata->rate = maxrate;
784 return MSG_task_send(task, alias);
787 /** \ingroup msg_task_usage
788 * \brief Sends a task to a mailbox with a timeout
790 * This is a blocking function, the execution flow will be blocked until the task is sent or the timeout is achieved.
792 * \param task the task to be sent
793 * \param alias the mailbox name to where the task is sent
794 * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_send)
796 * \return Returns #MSG_OK if the task was successfully sent,
797 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
799 msg_error_t MSG_task_send_with_timeout(msg_task_t task, const char *alias, double timeout)
801 msg_error_t ret = MSG_OK;
802 simdata_task_t t_simdata = NULL;
803 msg_process_t process = MSG_process_self();
804 simdata_process_t p_simdata = (simdata_process_t) SIMIX_process_self_get_data();
805 msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
807 int call_end = TRACE_msg_task_put_start(task); //must be after CHECK_HOST()
809 /* Prepare the task to send */
810 t_simdata = task->simdata;
811 t_simdata->sender = process;
812 t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data())->m_host;
814 if (t_simdata->isused != 0) {
815 if (msg_global->debug_multiple_use){
816 XBT_ERROR("This task is already used in there:");
817 xbt_backtrace_display((xbt_ex_t*) t_simdata->isused);
818 XBT_ERROR("And you try to reuse it from here:");
819 xbt_backtrace_display_current();
821 xbt_assert(t_simdata->isused == 0,
822 "This task is still being used somewhere else. You cannot send it now. Go fix your code!"
823 " (use --cfg=msg/debug-multiple-use:on to get the backtrace of the other process)");
827 if (msg_global->debug_multiple_use)
828 MSG_BT(t_simdata->isused, "Using Backtrace");
830 t_simdata->isused = (void*)1;
831 t_simdata->comm = NULL;
832 msg_global->sent_msg++;
834 p_simdata->waiting_task = task;
837 /* Try to send it by calling SIMIX network layer */
839 smx_synchro_t comm = NULL; /* MC needs the comm to be set to NULL during the simix call */
840 comm = simcall_comm_isend(SIMIX_process_self(), mailbox,t_simdata->bytes_amount,
841 t_simdata->rate, task, sizeof(void *), NULL, NULL, NULL, task, 0);
842 if (TRACE_is_enabled())
843 simcall_set_category(comm, task->category);
844 t_simdata->comm = static_cast<simgrid::simix::Comm*>(comm);
845 simcall_comm_wait(comm, timeout);
849 switch (e.category) {
851 ret = MSG_HOST_FAILURE;
854 ret = MSG_TRANSFER_FAILURE;
864 /* If the send failed, it is not used anymore */
865 if (msg_global->debug_multiple_use && t_simdata->isused!=0)
866 xbt_ex_free(*(xbt_ex_t*)t_simdata->isused);
867 t_simdata->isused = 0;
870 p_simdata->waiting_task = NULL;
872 TRACE_msg_task_put_end();
876 /** \ingroup msg_task_usage
877 * \brief Sends a task to a mailbox with a timeout and with a maximum rate
879 * This is a blocking function, the execution flow will be blocked until the task is sent or the timeout is achieved.
881 * \param task the task to be sent
882 * \param alias the mailbox name to where the task is sent
883 * \param timeout is the maximum wait time for completion (if -1, this call is the same as #MSG_task_send)
884 * \param maxrate the maximum communication rate for sending this task
886 * \return Returns #MSG_OK if the task was successfully sent,
887 * #MSG_HOST_FAILURE, or #MSG_TRANSFER_FAILURE, or #MSG_TIMEOUT otherwise.
889 msg_error_t MSG_task_send_with_timeout_bounded(msg_task_t task, const char *alias, double timeout, double maxrate)
891 task->simdata->rate = maxrate;
892 return MSG_task_send_with_timeout(task, alias, timeout);
895 /** \ingroup msg_task_usage
896 * \brief Check if there is a communication going on in a mailbox.
898 * \param alias the name of the mailbox to be considered
900 * \return Returns 1 if there is a communication, 0 otherwise
902 int MSG_task_listen(const char *alias)
904 smx_mailbox_t mbox = MSG_mailbox_get_by_alias(alias);
905 return !MSG_mailbox_is_empty(mbox) || (mbox->permanent_receiver && !mbox->done_comm_queue->empty());
908 /** \ingroup msg_task_usage
909 * \brief Look if there is a communication on a mailbox and return the PID of the sender process.
911 * \param alias the name of the mailbox to be considered
913 * \return Returns the PID of sender process,
914 * -1 if there is no communication in the mailbox.
916 int MSG_task_listen_from(const char *alias)
920 if (NULL == (task = MSG_mailbox_front(MSG_mailbox_get_by_alias(alias))))
923 return MSG_process_get_PID(task->simdata->sender);
926 /** \ingroup msg_task_usage
927 * \brief Sets the tracing category of a task.
929 * This function should be called after the creation of a MSG task, to define the category of that task. The
930 * first parameter task must contain a task that was created with the function #MSG_task_create. The second
931 * parameter category must contain a category that was previously declared with the function #TRACE_category
932 * (or with #TRACE_category_with_color).
934 * See \ref tracing for details on how to trace the (categorized) resource utilization.
936 * \param task the task that is going to be categorized
937 * \param category the name of the category to be associated to the task
939 * \see MSG_task_get_category, TRACE_category, TRACE_category_with_color
941 void MSG_task_set_category (msg_task_t task, const char *category)
943 TRACE_msg_set_task_category (task, category);
946 /** \ingroup msg_task_usage
948 * \brief Gets the current tracing category of a task.
950 * \param task the task to be considered
952 * \see MSG_task_set_category
954 * \return Returns the name of the tracing category of the given task, NULL otherwise
956 const char *MSG_task_get_category (msg_task_t task)
958 return task->category;
962 * \brief Returns the value of a given AS or router property
964 * \param asr the name of a router or AS
965 * \param name a property name
966 * \return value of a property (or NULL if property not set)
968 const char *MSG_as_router_get_property_value(const char* asr, const char *name)
970 return (char*) xbt_dict_get_or_null(MSG_as_router_get_properties(asr), name);
974 * \brief Returns a xbt_dict_t consisting of the list of properties assigned to
977 * \param asr the name of a router or AS
978 * \return a dict containing the properties
980 xbt_dict_t MSG_as_router_get_properties(const char* asr)
982 return (simcall_asr_get_properties(asr));
986 * \brief Change the value of a given AS or router
988 * \param asr the name of a router or AS
989 * \param name a property name
990 * \param value what to change the property to
991 * \param free_ctn the freeing function to use to kill the value on need
993 void MSG_as_router_set_property_value(const char* asr, const char *name, char *value,void_f_pvoid_t free_ctn) {
994 xbt_dict_set(MSG_as_router_get_properties(asr), name, value,free_ctn);