/** \ingroup msg_mailbox_management * \brief Set the mailbox to receive in asynchronous mode * * All messages sent to this mailbox will be transferred to * the receiver without waiting for the receive call. * The receive call will still be necessary to use the received data. * If there is a need to receive some messages asynchronously, and some not, * two different mailboxes should be used. * * \param alias The name of the mailbox */ void MSG_mailbox_set_async(const char *alias){ msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias); simcall_rdv_set_receiver(mailbox, SIMIX_process_self()); XBT_VERB("%s mailbox set to receive eagerly for process %p\n",alias, SIMIX_process_self()); }
CommPtr Mailbox::put_init() { CommPtr res = CommPtr(new s4u::Comm()); res->sender_ = SIMIX_process_self(); res->mailbox_ = this; return res; }
Host *Host::current(){ smx_process_t smx_proc = SIMIX_process_self(); if (smx_proc == NULL) xbt_die("Cannot call Host::current() from the maestro context"); return Host::byName(SIMIX_host_get_name(SIMIX_process_get_host(smx_proc))); }
/** * \brief Cleans the MSG data of a process. * \param smx_proc a SIMIX process */ void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc) { simdata_process_t msg_proc; // get the MSG process from the SIMIX process if (smx_proc == SIMIX_process_self()) { /* avoid a SIMIX request if this function is called by the process itself */ msg_proc = SIMIX_process_self_get_data(smx_proc); SIMIX_process_self_set_data(smx_proc, NULL); } else { msg_proc = simcall_process_get_data(smx_proc); simcall_process_set_data(smx_proc, NULL); } #ifdef HAVE_TRACING TRACE_msg_process_end(smx_proc); #endif // free the data if a function was provided if (msg_proc->data && msg_global->process_data_cleanup) { msg_global->process_data_cleanup(msg_proc->data); } // remove the process from its virtual machine if (msg_proc->vm) { int pos = xbt_dynar_search(msg_proc->vm->processes,&smx_proc); xbt_dynar_remove_at(msg_proc->vm->processes,pos, NULL); } // free the MSG process xbt_free(msg_proc); }
static void smx_ctx_cojava_suspend(smx_context_t context) { smx_context_t previous_context = context; unsigned long int i = cojava_process_index++; jobject next_coroutine; if (i < xbt_dynar_length(cojava_processes)) { smx_context_t next_context = SIMIX_process_get_context(xbt_dynar_get_as( cojava_processes,i, smx_process_t)); my_current_context = next_context; XBT_DEBUG("Switching to %p",my_current_context); smx_ctx_cojava_t java_context = (smx_ctx_cojava_t)(next_context); if (!java_context->jprocess) { java_context->super.code(java_context->super.argc, java_context->super.argv); smx_ctx_cojava_create_coroutine(java_context); } else if (!java_context->bound) { java_context->bound = 1; smx_process_t process = SIMIX_process_self(); (*global_env)->SetLongField(global_env, java_context->jprocess, jprocess_field_Process_bind, (intptr_t)process); } next_coroutine = java_context->jcoroutine; } else { //Give maestro the control back. next_coroutine = cojava_maestro_coroutine; my_current_context = maestro_context; } (*global_env)->CallStaticVoidMethod(global_env, coclass, coroutine_yieldTo, next_coroutine); my_current_context = previous_context; }
/** * \brief Cleans the MSG data of a process. * \param smx_proc a SIMIX process */ void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc) { simdata_process_t msg_proc; // get the MSG process from the SIMIX process if (smx_proc == SIMIX_process_self()) { /* avoid a SIMIX request if this function is called by the process itself */ msg_proc = SIMIX_process_self_get_data(smx_proc); SIMIX_process_self_set_data(smx_proc, NULL); } else { msg_proc = simcall_process_get_data(smx_proc); simcall_process_set_data(smx_proc, NULL); } TRACE_msg_process_end(smx_proc); // free the data if a function was provided if (msg_proc && msg_proc->data && msg_global->process_data_cleanup) { msg_global->process_data_cleanup(msg_proc->data); } // free the MSG process xbt_free(msg_proc); SIMIX_process_cleanup(smx_proc); }
/* 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; }
const char *TRACE_internal_smpi_get_category (void) { if (!TRACE_smpi_is_enabled()) return NULL; char processid[INSTR_DEFAULT_STR_SIZE]; snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self()); return xbt_dict_get_or_null (process_category, processid); }
/** * \ingroup simix_process_management * \brief Return the name of an agent. * * This functions checks whether \a process is a valid pointer or not and return its name. * \param process SIMIX process * \return The process name */ const char* simcall_process_get_name(smx_process_t process) { if (process == SIMIX_process_self()) { /* avoid a simcall if this function is called by the process itself */ return process->name; } return simcall_BODY_process_get_name(process); }
/** * \ingroup simix_process_management * \brief Return the user data of a #smx_process_t. * \param process a SIMIX process * \return the user data of this process */ void* simcall_process_get_data(smx_process_t process) { if (process == SIMIX_process_self()) { /* avoid a simcall if this function is called by the process itself */ return SIMIX_process_get_data(process); } return simcall_BODY_process_get_data(process); }
void smpi_process_init(int *argc, char ***argv) { int index=-1; smpi_process_data_t data; smx_process_t proc; if (argc && argv) { proc = SIMIX_process_self(); //FIXME: dirty cleanup method to avoid using msg cleanup functions on these processes when using MSG+SMPI SIMIX_process_set_cleanup_function(proc, MSG_process_cleanup_from_SIMIX); char* instance_id = (*argv)[1]; int rank = xbt_str_parse_int((*argv)[2], "Invalid rank: %s"); index = smpi_process_index_of_smx_process(proc); if(!index_to_process_data){ index_to_process_data=(int*)xbt_malloc(SIMIX_process_count()*sizeof(int)); } if(smpi_privatize_global_variables){ /* Now using segment index of the process */ index = proc->segment_index; /* Done at the process's creation */ SMPI_switch_data_segment(index); } MPI_Comm* temp_comm_world; xbt_bar_t temp_bar; smpi_deployment_register_process(instance_id, rank, index, &temp_comm_world, &temp_bar); data = smpi_process_remote_data(index); data->comm_world = temp_comm_world; if(temp_bar != NULL) data->finalization_barrier = temp_bar; data->index = index; data->instance_id = instance_id; data->replaying = 0; //xbt_free(simcall_process_get_data(proc)); simdata_process_t simdata = static_cast<simdata_process_t>(simcall_process_get_data(proc)); simdata->data = data; if (*argc > 3) { free((*argv)[1]); memmove(&(*argv)[0], &(*argv)[2], sizeof(char *) * (*argc - 2)); (*argv)[(*argc) - 1] = NULL; (*argv)[(*argc) - 2] = NULL; } (*argc)-=2; data->argc = argc; data->argv = argv; // set the process attached to the mailbox simcall_mbox_set_receiver(data->mailbox_small, proc); XBT_DEBUG("<%d> New process in the game: %p", index, proc); } xbt_assert(smpi_process_data(), "smpi_process_data() returned NULL. You probably gave a NULL parameter to MPI_Init. Although it's required by " "MPI-2, this is currently not supported by SMPI."); }
/** * \ingroup simix_process_management * \brief Set the user data of a #smx_process_t. * * This functions sets the user data associated to \a process. * \param process SIMIX process * \param data User data */ void simcall_process_set_data(smx_process_t process, void *data) { if (process == SIMIX_process_self()) { /* avoid a simcall if this function is called by the process itself */ SIMIX_process_self_set_data(process, data); } else { simcall_BODY_process_set_data(process, data); } }
/** \ingroup m_process_management * \brief Return the location on which a process is running. * \param process a process (NULL means the current one) * \return the msg_host_t corresponding to the location on which \a * process is running. */ msg_host_t MSG_process_get_host(msg_process_t process) { simdata_process_t simdata; if (process == NULL) { simdata = SIMIX_process_self_get_data(SIMIX_process_self()); } else { simdata = simcall_process_get_data(process); } return simdata->m_host; }
inline static R simcall(e_smx_simcall_t call, T const&... t) { smx_actor_t self = SIMIX_process_self(); simgrid::simix::marshal(&self->simcall, call, t...); if (self != simix_global->maestro_process) { XBT_DEBUG("Yield process '%s' on simcall %s (%d)", self->name.c_str(), SIMIX_simcall_name(self->simcall.call), (int)self->simcall.call); SIMIX_process_yield(self); } else { SIMIX_simcall_handle(&self->simcall, 0); } return simgrid::simix::unmarshal<R>(self->simcall.result); }
/** Run the Java org.simgrid.msg.Process */ void java_main_jprocess(jobject jprocess) { JNIEnv *env = get_current_thread_env(); simgrid::java::JavaContext* context = (simgrid::java::JavaContext*) SIMIX_context_self(); context->jprocess = jprocess; smx_process_t process = SIMIX_process_self(); jprocess_bind(context->jprocess, process, env); // Adrien, ugly path, just to bypass creation of context at low levels (i.e such as for the VM migration for instance) if (context->jprocess == nullptr) return; else run_jprocess(env, context->jprocess); }
void TRACE_internal_smpi_set_category (const char *category) { if (!TRACE_smpi_is_enabled()) return; //declare category TRACE_category (category); char processid[INSTR_DEFAULT_STR_SIZE]; snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self()); if (xbt_dict_get_or_null (process_category, processid)) xbt_dict_remove (process_category, processid); if (category != NULL) xbt_dict_set (process_category, processid, xbt_strdup(category), NULL); }
/** * \brief Return the name of an agent. * * This functions checks whether \a process is a valid pointer or not and return its name. * \param process SIMIX process * \return The process name */ const char* SIMIX_req_process_get_name(smx_process_t process) { if (process == SIMIX_process_self()) { /* avoid a request if this function is called by the process itself */ return process->name; } smx_req_t req = SIMIX_req_mine(); req->call = REQ_PROCESS_GET_NAME; req->process_get_name.process = process; SIMIX_request_push(); return req->process_get_name.result; }
/** * \brief Return the user data of a #smx_process_t. * * This functions checks whether \a process is a valid pointer or not and return the user data associated to \a process if it is possible. * \param process SIMIX process * \return A void pointer to the user data */ void* SIMIX_req_process_get_data(smx_process_t process) { if (process == SIMIX_process_self()) { /* avoid a request if this function is called by the process itself */ return SIMIX_process_self_get_data(); } smx_req_t req = SIMIX_req_mine(); req->call = REQ_PROCESS_GET_DATA; req->process_get_data.process = process; SIMIX_request_push(); return req->process_get_data.result; }
/** * \brief Set the user data of a #m_process_t. * * This functions checks whether \a process is a valid pointer or not and set the user data associated to \a process if it is possible. * \param process SIMIX process * \param data User data */ void SIMIX_req_process_set_data(smx_process_t process, void *data) { if (process == SIMIX_process_self()) { /* avoid a request if this function is called by the process itself */ SIMIX_process_self_set_data(data); } else { smx_req_t req = SIMIX_req_mine(); req->call = REQ_PROCESS_SET_DATA; req->process_set_data.process = process; req->process_set_data.data = data; SIMIX_request_push(); } }
static void smx_ctx_cojava_resume(smx_context_t new_context) { my_current_context = new_context; smx_ctx_cojava_t java_context = (smx_ctx_cojava_t)(new_context); if (!java_context->jprocess) { java_context->super.code(java_context->super.argc, java_context->super.argv); smx_ctx_cojava_create_coroutine(java_context); java_context->bound = 1; } else if (!java_context->bound) { java_context->bound = 1; smx_process_t process = SIMIX_process_self(); (*global_env)->SetLongField(global_env, java_context->jprocess, jprocess_field_Process_bind, (intptr_t)process); } (*global_env)->CallStaticVoidMethod(global_env, coclass, coroutine_yieldTo, java_context->jcoroutine); }
/******************************** Process ************************************/ void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc) { simdata_process_t msg_proc; if (smx_proc == SIMIX_process_self()) { /* avoid a SIMIX request if this function is called by the process itself */ msg_proc = SIMIX_process_self_get_data(); } else { msg_proc = SIMIX_req_process_get_data(smx_proc); } #ifdef HAVE_TRACING TRACE_msg_process_end(smx_proc); #endif xbt_free(msg_proc); }
/** \ingroup m_process_management * \brief Creates and runs a new #m_process_t. * A constructor for #m_process_t taking four arguments and returning the * corresponding object. The structure (and the corresponding thread) is * created, and put in the list of ready process. * \param name a name for the object. It is for user-level information and can be NULL. * \param code is a function describing the behavior of the agent. It should then only use functions described in \ref m_process_management (to create a new #m_process_t for example), in \ref m_host_management (only the read-only functions i.e. whose name contains the word get), in \ref m_task_management (to create or destroy some #m_task_t for example) and in \ref msg_gos_functions (to handle file transfers and task processing). * \param data a pointer to any data one may want to attach to the new object. It is for user-level information and can be NULL. It can be retrieved with the function \ref MSG_process_get_data. * \param host the location where the new agent is executed. * \param argc first argument passed to \a code * \param argv second argument passed to \a code * \param properties list a properties defined for this process * \see m_process_t * \return The new corresponding object. */ m_process_t MSG_process_create_with_environment(const char *name, xbt_main_func_t code, void *data, m_host_t host, int argc, char **argv, xbt_dict_t properties) { xbt_assert(code != NULL && host != NULL, "Invalid parameters"); simdata_process_t simdata = xbt_new0(s_simdata_process_t, 1); m_process_t process; /* Simulator data for MSG */ simdata->PID = msg_global->PID++; simdata->waiting_action = NULL; simdata->waiting_task = NULL; simdata->m_host = host; simdata->argc = argc; simdata->argv = argv; simdata->data = data; simdata->last_errno = MSG_OK; if (SIMIX_process_self()) { simdata->PPID = MSG_process_get_PID(MSG_process_self()); } else { simdata->PPID = -1; } /* Let's create the process: SIMIX may decide to start it right now, * even before returning the flow control to us */ SIMIX_req_process_create(&process, name, code, simdata, host->name, argc, argv, properties); #ifdef HAVE_TRACING TRACE_msg_process_create(process); #endif if (!process) { /* Undo everything we have just changed */ msg_global->PID--; xbt_free(simdata); return NULL; } return process; }
xbt_thread_t xbt_thread_create(const char *name, void_f_pvoid_t code, void *param, int joinable) { xbt_thread_t res = xbt_new0(s_xbt_thread_t, 1); res->name = xbt_strdup(name); res->userparam = param; res->code = code; res->father_data = SIMIX_process_self_get_data(SIMIX_process_self()); /* char*name = bprintf("%s#%p",SIMIX_process_self_get_name(), param); */ simcall_process_create(&res->s_process, name, xbt_thread_create_wrapper, res, SIMIX_host_self_get_name(), -1.0, 0, NULL, /*props */ NULL,0); res->joinable = joinable; res->done = 0; res->cond = xbt_cond_init(); res->mutex = xbt_mutex_init(); // free(name); return res; }
static int xbt_thread_create_wrapper(int argc, char *argv[]) { smx_process_t self = SIMIX_process_self(); xbt_thread_t t = (xbt_thread_t) SIMIX_process_self_get_data(self); simcall_process_set_data(self, t->father_data); t->code(t->userparam); if (t->joinable) { t->done = 1; xbt_mutex_acquire(t->mutex); xbt_cond_broadcast(t->cond); xbt_mutex_release(t->mutex); } else { xbt_mutex_destroy(t->mutex); xbt_cond_destroy(t->cond); free(t->name); free(t); } return 0; }
/* 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; }
void SIMIX_request_push() { xbt_swag_t req_table; smx_process_t issuer = SIMIX_process_self(); if (issuer != simix_global->maestro_process){ issuer->request.issuer = issuer; req_table = SIMIX_request_get_reqlist(SIMIX_context_get_thread_id()); xbt_swag_insert_at_tail(&issuer->request, req_table); XBT_DEBUG("Pushed request %s (%d) of %s", SIMIX_request_name(issuer->request.call), issuer->request.call, issuer->name); XBT_DEBUG("Yield process '%s' on request of type %s (%d)", issuer->name, SIMIX_request_name(issuer->request.call), issuer->request.call); SIMIX_process_yield(); } else { SIMIX_request_pre(&issuer->request, 0); } }
/** * \brief Cleans the MSG data of a process. * \param smx_proc a SIMIX process */ void MSG_process_cleanup_from_SIMIX(smx_actor_t smx_proc) { simdata_process_t msg_proc; // get the MSG process from the SIMIX process if (smx_proc == SIMIX_process_self()) { /* avoid a SIMIX request if this function is called by the process itself */ msg_proc = (simdata_process_t) SIMIX_process_self_get_data(); SIMIX_process_self_set_data(nullptr); } else { msg_proc = (simdata_process_t) simcall_process_get_data(smx_proc); simcall_process_set_data(smx_proc, nullptr); } TRACE_msg_process_destroy(smx_proc->name.c_str(), smx_proc->pid); // free the data if a function was provided if (msg_proc && msg_proc->data && msg_global->process_data_cleanup) { msg_global->process_data_cleanup(msg_proc->data); } // free the MSG process xbt_free(msg_proc); SIMIX_process_cleanup(smx_proc); }
void xbt_thread_yield(void) { SIMIX_process_yield(SIMIX_process_self()); }
xbt_thread_t xbt_thread_self(void) { return SIMIX_process_self_get_data(SIMIX_process_self()); }
void xbt_thread_exit() { simcall_process_kill(SIMIX_process_self()); }