/** * \ingroup simix_comm_management */ void simcall_comm_send(smx_process_t sender, smx_mailbox_t mbox, double task_size, double rate, void *src_buff, size_t src_buff_size, int (*match_fun)(void *, void *, smx_synchro_t), void (*copy_data_fun)(smx_synchro_t, void*, size_t), void *data, double timeout) { /* checking for infinite values */ xbt_assert(std::isfinite(task_size), "task_size is not finite!"); xbt_assert(std::isfinite(rate), "rate is not finite!"); xbt_assert(std::isfinite(timeout), "timeout is not finite!"); xbt_assert(mbox, "No rendez-vous point defined for send"); if (MC_is_active() || MC_record_replay_is_active()) { /* the model-checker wants two separate simcalls */ smx_synchro_t comm = NULL; /* MC needs the comm to be set to NULL during the simcall */ comm = simcall_comm_isend(sender, mbox, task_size, rate, src_buff, src_buff_size, match_fun, NULL, copy_data_fun, data, 0); simcall_comm_wait(comm, timeout); comm = NULL; } else { simcall_BODY_comm_send(sender, mbox, task_size, rate, src_buff, src_buff_size, match_fun, copy_data_fun, data, timeout); } }
/* Internal function used to factorize code between * MSG_task_isend_with_matching() and MSG_task_dsend(). */ static XBT_INLINE msg_comm_t MSG_task_isend_internal(msg_task_t task, const char *alias, int (*match_fun)(void*,void*, smx_synchro_t), void *match_data, void_f_pvoid_t cleanup, int detached) { simdata_task_t t_simdata = NULL; msg_process_t process = MSG_process_self(); msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias); int call_end = TRACE_msg_task_put_start(task); /* Prepare the task to send */ t_simdata = task->simdata; t_simdata->sender = process; t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host; if (t_simdata->isused != 0) { if (msg_global->debug_multiple_use){ XBT_ERROR("This task is already used in there:"); xbt_backtrace_display(t_simdata->isused); XBT_ERROR("And you try to reuse it from here:"); xbt_backtrace_display_current(); } else { xbt_assert(t_simdata->isused == 0, "This task is still being used somewhere else. You cannot send it now. Go fix your code! (use --cfg=msg/debug_multiple_use:on to get the backtrace of the other process)"); } } if (msg_global->debug_multiple_use) MSG_BT(t_simdata->isused, "Using Backtrace"); else t_simdata->isused = (void*)1; t_simdata->comm = NULL; msg_global->sent_msg++; /* Send it by calling SIMIX network layer */ smx_synchro_t act = simcall_comm_isend(SIMIX_process_self(), mailbox, t_simdata->bytes_amount, t_simdata->rate, task, sizeof(void *), match_fun, cleanup, NULL, match_data,detached); t_simdata->comm = act; /* FIXME: is the field t_simdata->comm still useful? */ msg_comm_t comm; if (detached) { comm = NULL; } else { comm = xbt_new0(s_msg_comm_t, 1); comm->task_sent = task; comm->task_received = NULL; comm->status = MSG_OK; comm->s_comm = act; } if (TRACE_is_enabled()) simcall_set_category(act, task->category); if (call_end) TRACE_msg_task_put_end(); return comm; }
/** \ingroup msg_task_usage * \brief Sends a task on a mailbox, with support for matching requests * * This is a non blocking function: use MSG_comm_wait() or MSG_comm_test() * to end the communication. * * \param task a #msg_task_t to send on another location. * \param alias name of the mailbox to sent the task to * \param match_fun boolean function which parameters are: * - match_data_provided_here * - match_data_provided_by_other_side_if_any * - the_smx_action_describing_the_other_side * \param match_data user provided data passed to match_fun * \return the msg_comm_t communication created */ XBT_INLINE msg_comm_t MSG_task_isend_with_matching(msg_task_t task, const char *alias, int (*match_fun)(void*,void*, smx_action_t), void *match_data) { simdata_task_t t_simdata = NULL; msg_process_t process = MSG_process_self(); msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias); #ifdef HAVE_TRACING int call_end = TRACE_msg_task_put_start(task); #endif /* Prepare the task to send */ t_simdata = task->simdata; t_simdata->sender = process; t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host; xbt_assert(t_simdata->isused == 0, "This task is still being used somewhere else. You cannot send it now. Go fix your code!"); t_simdata->isused = 1; t_simdata->comm = NULL; msg_global->sent_msg++; /* Send it by calling SIMIX network layer */ msg_comm_t comm = xbt_new0(s_msg_comm_t, 1); comm->task_sent = task; comm->task_received = NULL; comm->status = MSG_OK; comm->s_comm = simcall_comm_isend(mailbox, t_simdata->message_size, t_simdata->rate, task, sizeof(void *), match_fun, NULL, match_data, 0); t_simdata->comm = comm->s_comm; /* FIXME: is the field t_simdata->comm still useful? */ #ifdef HAVE_TRACING if (TRACE_is_enabled()) { simcall_set_category(comm->s_comm, task->category); } #endif #ifdef HAVE_TRACING if (call_end) TRACE_msg_task_put_end(); #endif return comm; }
/* Internal function used to factorize code between MSG_task_isend_with_matching() and MSG_task_dsend(). */ static inline msg_comm_t MSG_task_isend_internal(msg_task_t task, const char *alias, int (*match_fun)(void*,void*, smx_synchro_t), void *match_data, void_f_pvoid_t cleanup, int detached) { simdata_task_t t_simdata = nullptr; msg_process_t process = MSG_process_self(); msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias); int call_end = TRACE_msg_task_put_start(task); /* Prepare the task to send */ t_simdata = task->simdata; t_simdata->sender = process; t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data())->m_host; t_simdata->setUsed(); t_simdata->comm = nullptr; msg_global->sent_msg++; /* Send it by calling SIMIX network layer */ smx_synchro_t act = simcall_comm_isend(SIMIX_process_self(), mailbox, t_simdata->bytes_amount, t_simdata->rate, task, sizeof(void *), match_fun, cleanup, nullptr, match_data,detached); t_simdata->comm = static_cast<simgrid::simix::Comm*>(act); /* FIXME: is the field t_simdata->comm still useful? */ msg_comm_t comm; if (detached) { comm = nullptr; } else { comm = xbt_new0(s_msg_comm_t, 1); comm->task_sent = task; comm->task_received = nullptr; comm->status = MSG_OK; comm->s_comm = act; } if (TRACE_is_enabled()) simcall_set_category(act, task->category); if (call_end) TRACE_msg_task_put_end(); return comm; }
/** \ingroup msg_task_usage * \brief Sends a task on a mailbox with a maximal rate. * * This is a non blocking detached send function. * Think of it as a best effort send. Keep in mind that the third parameter * is only called if the communication fails. If the communication does work, * it is responsibility of the receiver code to free anything related to * the task, as usual. More details on this can be obtained on * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a> * in the SimGrid-user mailing list archive. * * \param task a #msg_task_t to send on another location. * \param alias name of the mailbox to sent the task to * \param cleanup a function to destroy the task if the * communication fails, e.g. MSG_task_destroy * (if NULL, no function will be called) * \param maxrate the maximum communication rate for sending this task * */ void MSG_task_dsend_bounded(msg_task_t task, const char *alias, void_f_pvoid_t cleanup, double maxrate) { task->simdata->rate = maxrate; simdata_task_t t_simdata = NULL; msg_process_t process = MSG_process_self(); msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias); /* Prepare the task to send */ t_simdata = task->simdata; t_simdata->sender = process; t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host; xbt_assert(t_simdata->isused == 0, "This task is still being used somewhere else. You cannot send it now. Go fix your code!"); t_simdata->isused = 1; t_simdata->comm = NULL; msg_global->sent_msg++; #ifdef HAVE_TRACING int call_end = TRACE_msg_task_put_start(task); #endif /* Send it by calling SIMIX network layer */ smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size, t_simdata->rate, task, sizeof(void *), NULL, cleanup, NULL, 1); t_simdata->comm = comm; #ifdef HAVE_TRACING if (TRACE_is_enabled()) { simcall_set_category(comm, task->category); } #endif #ifdef HAVE_TRACING if (call_end) TRACE_msg_task_put_end(); #endif }
/** * \ingroup simix_comm_management */ void simcall_comm_send(smx_rdv_t rdv, double task_size, double rate, void *src_buff, size_t src_buff_size, int (*match_fun)(void *, void *, smx_action_t), void *data, double timeout) { /* checking for infinite values */ xbt_assert(isfinite(task_size), "task_size is not finite!"); xbt_assert(isfinite(rate), "rate is not finite!"); xbt_assert(isfinite(timeout), "timeout is not finite!"); xbt_assert(rdv, "No rendez-vous point defined for send"); if (MC_is_active()) { /* the model-checker wants two separate simcalls */ smx_action_t comm = simcall_comm_isend(rdv, task_size, rate, src_buff, src_buff_size, match_fun, NULL, data, 0); simcall_comm_wait(comm, timeout); } else { simcall_BODY_comm_send(rdv, task_size, rate, src_buff, src_buff_size, match_fun, data, timeout); } }
msg_error_t MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task, double timeout) { xbt_ex_t e; msg_error_t ret = MSG_OK; simdata_task_t t_simdata = NULL; msg_process_t process = MSG_process_self(); simdata_process_t p_simdata = SIMIX_process_self_get_data(process); #ifdef HAVE_TRACING int call_end = TRACE_msg_task_put_start(task); //must be after CHECK_HOST() #endif /* Prepare the task to send */ t_simdata = task->simdata; t_simdata->sender = process; t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host; xbt_assert(t_simdata->isused == 0, "This task is still being used somewhere else. You cannot send it now. Go fix your code!"); t_simdata->isused=1; t_simdata->comm = NULL; msg_global->sent_msg++; p_simdata->waiting_task = task; /* Try to send it by calling SIMIX network layer */ TRY { smx_action_t comm = simcall_comm_isend(mailbox, t_simdata->message_size, t_simdata->rate, task, sizeof(void *), NULL, NULL, task, 0); #ifdef HAVE_TRACING if (TRACE_is_enabled()) { simcall_set_category(comm, task->category); } #endif t_simdata->comm = comm; simcall_comm_wait(comm, timeout); } CATCH(e) { switch (e.category) { case network_error: ret = MSG_TRANSFER_FAILURE; break; case timeout_error: ret = MSG_TIMEOUT; break; default: RETHROW; } xbt_ex_free(e); /* If the send failed, it is not used anymore */ t_simdata->isused = 0; } p_simdata->waiting_task = NULL; #ifdef HAVE_TRACING if (call_end) TRACE_msg_task_put_end(); #endif MSG_RETURN(ret); }
msg_error_t MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task, double timeout) { msg_error_t ret = MSG_OK; simdata_task_t t_simdata = NULL; msg_process_t process = MSG_process_self(); simdata_process_t p_simdata = SIMIX_process_self_get_data(process); int call_end = TRACE_msg_task_put_start(task); //must be after CHECK_HOST() /* Prepare the task to send */ t_simdata = task->simdata; t_simdata->sender = process; t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host; if (t_simdata->isused != 0) { if (msg_global->debug_multiple_use){ XBT_ERROR("This task is already used in there:"); xbt_backtrace_display(t_simdata->isused); XBT_ERROR("And you try to reuse it from here:"); xbt_backtrace_display_current(); } else { xbt_assert(t_simdata->isused == 0, "This task is still being used somewhere else. You cannot send it now. Go fix your code! (use --cfg=msg/debug_multiple_use:on to get the backtrace of the other process)"); } } if (msg_global->debug_multiple_use) MSG_BT(t_simdata->isused, "Using Backtrace"); else t_simdata->isused = (void*)1; t_simdata->comm = NULL; msg_global->sent_msg++; p_simdata->waiting_task = task; xbt_ex_t e; /* Try to send it by calling SIMIX network layer */ TRY { smx_synchro_t comm = NULL; /* MC needs the comm to be set to NULL during the simix call */ comm = simcall_comm_isend(SIMIX_process_self(), mailbox,t_simdata->bytes_amount, t_simdata->rate, task, sizeof(void *), NULL, NULL, NULL, task, 0); if (TRACE_is_enabled()) simcall_set_category(comm, task->category); t_simdata->comm = comm; simcall_comm_wait(comm, timeout); } CATCH(e) { switch (e.category) { case cancel_error: ret = MSG_HOST_FAILURE; break; case network_error: ret = MSG_TRANSFER_FAILURE; break; case timeout_error: ret = MSG_TIMEOUT; break; default: RETHROW; } xbt_ex_free(e); /* If the send failed, it is not used anymore */ if (msg_global->debug_multiple_use && t_simdata->isused!=0) xbt_ex_free(*(xbt_ex_t*)t_simdata->isused); t_simdata->isused = 0; } p_simdata->waiting_task = NULL; if (call_end) TRACE_msg_task_put_end(); MSG_RETURN(ret); }