void smpi_global_init(void) { int i; MPI_Group group; char name[MAILBOX_NAME_MAXLEN]; int smpirun=0; if (!MC_is_active()) { global_timer = xbt_os_timer_new(); xbt_os_walltimer_start(global_timer); } if (process_count == 0){ process_count = SIMIX_process_count(); smpirun=1; } smpi_universe_size = process_count; process_data = xbt_new0(smpi_process_data_t, process_count); for (i = 0; i < process_count; i++) { process_data[i] = xbt_new(s_smpi_process_data_t, 1); //process_data[i]->index = i; process_data[i]->argc = NULL; process_data[i]->argv = NULL; process_data[i]->mailbox = simcall_rdv_create(get_mailbox_name(name, i)); process_data[i]->mailbox_small = simcall_rdv_create(get_mailbox_name_small(name, i)); process_data[i]->mailboxes_mutex = xbt_mutex_init(); process_data[i]->timer = xbt_os_timer_new(); if (MC_is_active()) MC_ignore_heap(process_data[i]->timer, xbt_os_timer_size()); process_data[i]->comm_self = MPI_COMM_NULL; process_data[i]->comm_intra = MPI_COMM_NULL; process_data[i]->comm_world = NULL; process_data[i]->state = SMPI_UNINITIALIZED; process_data[i]->sampling = 0; process_data[i]->finalization_barrier = NULL; } //if the process was launched through smpirun script //we generate a global mpi_comm_world //if not, we let MPI_COMM_NULL, and the comm world //will be private to each mpi instance if(smpirun){ group = smpi_group_new(process_count); MPI_COMM_WORLD = smpi_comm_new(group, NULL); MPI_Attr_put(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, (void *)(MPI_Aint)process_count); xbt_bar_t bar=xbt_barrier_init(process_count); for (i = 0; i < process_count; i++) { smpi_group_set_mapping(group, i, i); process_data[i]->finalization_barrier = bar; } } }
void simcall_HANDLER_comm_testany( smx_simcall_t simcall, simgrid::kernel::activity::ActivityImpl* comms[], size_t count) { // The default result is -1 -- this means, "nothing is ready". // It can be changed below, but only if something matches. simcall_comm_testany__set__result(simcall, -1); if (MC_is_active() || MC_record_replay_is_active()){ int idx = SIMCALL_GET_MC_VALUE(simcall); if(idx == -1){ SIMIX_simcall_answer(simcall); }else{ simgrid::kernel::activity::ActivityImpl* synchro = comms[idx]; simcall_comm_testany__set__result(simcall, idx); synchro->simcalls.push_back(simcall); synchro->state = SIMIX_DONE; SIMIX_comm_finish(synchro); } return; } for (std::size_t i = 0; i != count; ++i) { simgrid::kernel::activity::ActivityImpl* synchro = comms[i]; if (synchro->state != SIMIX_WAITING && synchro->state != SIMIX_RUNNING) { simcall_comm_testany__set__result(simcall, i); synchro->simcalls.push_back(simcall); SIMIX_comm_finish(synchro); return; } } SIMIX_simcall_answer(simcall); }
void MC_automaton_new_propositional_symbol_pointer(const char *name, int* value) { xbt_assert(mc_model_checker == nullptr); if (!MC_is_active()) return; simgrid::mc::Client::get()->declareSymbol(name, value); }
void MC_assert(int prop) { if (MC_is_active() && !prop) { MC_client_send_simple_message(MC_MESSAGE_ASSERTION_FAILED); MC_client_handle_messages(); } }
/** @brief Register a stack in the model checker * * The stacks are allocated in the heap. The MC handle them especially * when we analyse/compare the content of the heap so it must be told where * they are with this function. * * @param stack * @param process Process owning the stack * @param context * @param size Size of the stack */ void MC_register_stack_area(void *stack, smx_process_t process, ucontext_t* context, size_t size) { xbt_assert(mc_model_checker == nullptr); if (!MC_is_active()) return; simgrid::mc::Client::get()->declareStack(stack, size, process, context); }
/* * Instrumentation functions to trace MSG processes (msg_process_t) */ void TRACE_msg_process_change_host(msg_process_t process, msg_host_t old_host, msg_host_t new_host) { if (TRACE_msg_process_is_enabled()){ static long long int counter = 0; if(MC_is_active()) MC_ignore_data_bss(&counter, sizeof(counter)); char key[INSTR_DEFAULT_STR_SIZE]; snprintf (key, INSTR_DEFAULT_STR_SIZE, "%lld", counter++); int len = INSTR_DEFAULT_STR_SIZE; char str[INSTR_DEFAULT_STR_SIZE]; //start link container_t msg = PJ_container_get (instr_process_id(process, str, len)); type_t type = PJ_type_get ("MSG_PROCESS_LINK", PJ_type_get_root()); new_pajeStartLink (MSG_get_clock(), PJ_container_get_root(), type, msg, "M", key); //destroy existing container of this process TRACE_msg_process_destroy (MSG_process_get_name (process), MSG_process_get_PID (process), old_host); //create new container on the new_host location TRACE_msg_process_create (MSG_process_get_name (process), MSG_process_get_PID (process), new_host); //end link msg = PJ_container_get(instr_process_id(process, str, len)); type = PJ_type_get ("MSG_PROCESS_LINK", PJ_type_get_root()); new_pajeEndLink (MSG_get_clock(), PJ_container_get_root(), type, msg, "M", key); } }
void MC_ignore_heap(void *address, size_t size) { xbt_assert(mc_model_checker == nullptr); if (!MC_is_active()) return; simgrid::mc::Client::get()->ignoreHeap(address, size); }
/** * \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); } }
/** used by the module to know if it's time to activate the mallocators yet */ static XBT_INLINE int xbt_mallocator_is_active(void) { #if MALLOCATOR_COMPILED_IN return initialization_done && !MC_is_active(); #else return 0; #endif }
static smx_context_t smx_ctx_sysv_create_context_sized(size_t size, xbt_main_func_t code, int argc, char **argv, void_pfn_smxprocess_t cleanup_func, void *data) { int ctx_addr[CTX_ADDR_LEN]; smx_ctx_sysv_t context = (smx_ctx_sysv_t) smx_ctx_base_factory_create_context_sized(size, code, argc, argv, cleanup_func, data); /* if the user provided a function for the process then use it, otherwise it is the context for maestro */ if (code) { getcontext(&(context->uc)); context->uc.uc_link = NULL; context->uc.uc_stack.ss_sp = pth_skaddr_makecontext(context->stack, smx_context_stack_size); context->uc.uc_stack.ss_size = pth_sksize_makecontext(context->stack, smx_context_stack_size); #ifdef HAVE_VALGRIND_VALGRIND_H context->valgrind_stack_id = VALGRIND_STACK_REGISTER(context->uc.uc_stack.ss_sp, ((char *) context->uc.uc_stack.ss_sp) + context->uc.uc_stack.ss_size); #endif /* HAVE_VALGRIND_VALGRIND_H */ memcpy(ctx_addr, &context, sizeof(smx_ctx_sysv_t)); switch (CTX_ADDR_LEN) { case 1: makecontext(&context->uc, (void (*)())smx_ctx_sysv_wrapper, 1, ctx_addr[0]); break; case 2: makecontext(&context->uc, (void (*)())smx_ctx_sysv_wrapper, 2, ctx_addr[0], ctx_addr[1]); break; default: xbt_die("Ucontexts are not supported on this arch yet (addr len = %zu/%zu = %zu)", sizeof(smx_ctx_sysv_t), sizeof(int), CTX_ADDR_LEN); } } else { if(data != NULL && sysv_maestro_context == NULL) sysv_maestro_context = context; } if(MC_is_active() && code) MC_new_stack_area(context, ((smx_process_t)((smx_context_t)context)->data)->name, &(context->uc), size); return (smx_context_t) context; }
ExecImpl& ExecImpl::set_timeout(double timeout) { if (timeout > 0 && not MC_is_active() && not MC_record_replay_is_active()) { timeout_detector_ = hosts_.front()->pimpl_cpu->sleep(timeout); timeout_detector_->set_activity(this); } return *this; }
void ContextFactory::declare_context(void* context, std::size_t size) { #if HAVE_MC /* Store the address of the stack in heap to compare it apart of heap comparison */ if(MC_is_active()) MC_ignore_heap(context, size); #endif }
void Context::declare_context(std::size_t size) { #if SIMGRID_HAVE_MC /* Store the address of the stack in heap to compare it apart of heap comparison */ if(MC_is_active()) MC_ignore_heap(this, size); #endif }
void MC_automaton_new_propositional_symbol(const char *id, int(*fct)(void)) { xbt_assert(mc_model_checker == nullptr); if (!MC_is_active()) return; xbt_die("Support for client-side function proposition is not implemented: " "use MC_automaton_new_propositional_symbol_pointer instead."); }
void MC_cut(void) { xbt_assert(mc_model_checker == nullptr); if (!MC_is_active()) return; // FIXME, We want to do this in the model-checker: xbt_die("MC_cut() not implemented"); }
void MC_ignore_global_variable(const char *name) { xbt_assert(mc_model_checker == nullptr); if (!MC_is_active()) return; // TODO, send a message to the model_checker xbt_die("Unimplemented"); }
static smx_context_t smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char **argv, void_pfn_smxprocess_t cleanup_func, smx_process_t process) { int ctx_addr[CTX_ADDR_LEN]; smx_ctx_sysv_t context = (smx_ctx_sysv_t) smx_ctx_base_factory_create_context_sized( sizeof(s_smx_ctx_sysv_t), code, argc, argv, cleanup_func, process); /* if the user provided a function for the process then use it, otherwise it is the context for maestro */ if (code) { context->stack = SIMIX_context_stack_new(); getcontext(&(context->uc)); context->uc.uc_link = NULL; context->uc.uc_stack.ss_sp = pth_skaddr_makecontext(context->stack, smx_context_usable_stack_size); context->uc.uc_stack.ss_size = pth_sksize_makecontext(context->stack, smx_context_usable_stack_size); memcpy(ctx_addr, &context, sizeof(smx_ctx_sysv_t)); switch (CTX_ADDR_LEN) { case 1: makecontext(&context->uc, (void (*)())smx_ctx_sysv_wrapper, 1, ctx_addr[0]); break; case 2: makecontext(&context->uc, (void (*)())smx_ctx_sysv_wrapper, 2, ctx_addr[0], ctx_addr[1]); break; default: xbt_die("Ucontexts are not supported on this arch yet (addr len = %zu/%zu = %zu)", sizeof(smx_ctx_sysv_t), sizeof(int), CTX_ADDR_LEN); } } else { if (process != NULL && sysv_maestro_context == NULL) sysv_maestro_context = context; } #ifdef HAVE_MC if (MC_is_active() && code) { MC_register_stack_area(context->stack, ((smx_context_t)context)->process, &(context->uc), smx_context_usable_stack_size); } #endif return (smx_context_t) context; }
/** @brief Prepares the current process for termination. */ void smpi_process_finalize(void) { // This leads to an explosion of the search graph which cannot be reduced: if(MC_is_active() || MC_record_replay_is_active()) return; int index = smpi_process_index(); // wait for all pending asynchronous comms to finish xbt_barrier_wait(process_data[index_to_process_data[index]]->finalization_barrier); }
/* MSG_task_create related function*/ void TRACE_msg_task_create(msg_task_t task) { static long long counter = 0; task->counter = counter++; task->category = NULL; if(MC_is_active()) MC_ignore_heap(&(task->counter), sizeof(task->counter)); XBT_DEBUG("CREATE %p, %lld", task, task->counter); }
void Engine::run() { /* Clean IO before the run */ fflush(stdout); fflush(stderr); if (MC_is_active()) { MC_run(); } else { SIMIX_run(); } }
void simgrid::kernel::activity::CommImpl::cancel() { /* if the synchro is a waiting state means that it is still in a mbox */ /* so remove from it and delete it */ if (state_ == SIMIX_WAITING) { mbox->remove(this); state_ = SIMIX_CANCELED; } else if (not MC_is_active() /* when running the MC there are no surf actions */ && not MC_record_replay_is_active() && (state_ == SIMIX_READY || state_ == SIMIX_RUNNING)) { surfAction_->cancel(); } }
/** \ingroup msg_simulation * \brief Launch the MSG simulation */ msg_error_t MSG_main(void) { /* Clean IO before the run */ fflush(stdout); fflush(stderr); if (MC_is_active()) { MC_do_the_modelcheck_for_real(); } else { SIMIX_run(); } return MSG_OK; }
/** \ingroup msg_simulation * \brief Launch the MSG simulation */ msg_error_t MSG_main() { /* Clean IO before the run */ fflush(stdout); fflush(stderr); if (MC_is_active()) { MC_run(); } else { SIMIX_run(); } return MSG_OK; }
/** An (fake) application with a bug occuring for some random values */ static int app(int argc, char *argv[]) { int x = MC_random(0, 5); int y = MC_random(0, 5); if (MC_is_active()) { MC_assert(x !=3 || y !=4); } if (x ==3 && y ==4) { fprintf(stderr, "Error reached\n"); } return 0; }
/** * \ingroup simix_comm_management */ void simcall_comm_recv_bounded(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size, int (*match_fun)(void *, void *, smx_action_t), void *data, double timeout, double rate) { xbt_assert(isfinite(timeout), "timeout is not finite!"); xbt_assert(rdv, "No rendez-vous point defined for recv"); if (MC_is_active()) { /* the model-checker wants two separate simcalls */ smx_action_t comm = simcall_comm_irecv_bounded(rdv, dst_buff, dst_buff_size, match_fun, data, rate); simcall_comm_wait(comm, timeout); } else { simcall_BODY_comm_recv_bounded(rdv, dst_buff, dst_buff_size, match_fun, data, timeout, rate); } }
void smpi_global_destroy(void) { int count = smpi_process_count(); int i; smpi_bench_destroy(); if (MPI_COMM_WORLD != MPI_COMM_UNINITIALIZED){ while (smpi_group_unuse(smpi_comm_group(MPI_COMM_WORLD)) > 0); xbt_barrier_destroy(process_data[0]->finalization_barrier); }else{ smpi_deployment_cleanup_instances(); } for (i = 0; i < count; i++) { if(process_data[i]->comm_self!=MPI_COMM_NULL){ smpi_comm_destroy(process_data[i]->comm_self); } if(process_data[i]->comm_intra!=MPI_COMM_NULL){ smpi_comm_destroy(process_data[i]->comm_intra); } xbt_os_timer_free(process_data[i]->timer); xbt_mutex_destroy(process_data[i]->mailboxes_mutex); xbt_free(process_data[i]); } xbt_free(process_data); process_data = NULL; if (MPI_COMM_WORLD != MPI_COMM_UNINITIALIZED){ smpi_comm_cleanup_smp(MPI_COMM_WORLD); smpi_comm_cleanup_attributes(MPI_COMM_WORLD); if(smpi_coll_cleanup_callback!=NULL) smpi_coll_cleanup_callback(); xbt_free(MPI_COMM_WORLD); } MPI_COMM_WORLD = MPI_COMM_NULL; if (!MC_is_active()) { xbt_os_timer_free(global_timer); } xbt_free(index_to_process_data); if(smpi_privatize_global_variables) smpi_destroy_global_memory_segments(); smpi_free_static(); }
void simcall_HANDLER_execution_wait(smx_simcall_t simcall, simgrid::kernel::activity::ExecImpl* synchro) { XBT_DEBUG("Wait for execution of synchro %p, state %d", synchro, (int)synchro->state_); /* Associate this simcall to the synchro */ synchro->register_simcall(simcall); /* set surf's synchro */ if (MC_is_active() || MC_record_replay_is_active()) { synchro->state_ = SIMIX_DONE; synchro->finish(); return; } /* If the synchro is already finished then perform the error handling */ if (synchro->state_ != SIMIX_RUNNING) synchro->finish(); }
void simcall_HANDLER_comm_wait(smx_simcall_t simcall, smx_activity_t synchro, double timeout) { /* Associate this simcall to the wait synchro */ XBT_DEBUG("simcall_HANDLER_comm_wait, %p", synchro); synchro->simcalls.push_back(simcall); simcall->issuer->waiting_synchro = synchro; if (MC_is_active() || MC_record_replay_is_active()) { int idx = SIMCALL_GET_MC_VALUE(simcall); if (idx == 0) { synchro->state = SIMIX_DONE; } else { /* If we reached this point, the wait simcall must have a timeout */ /* Otherwise it shouldn't be enabled and executed by the MC */ if (timeout < 0.0) THROW_IMPOSSIBLE; simgrid::kernel::activity::Comm *comm = static_cast<simgrid::kernel::activity::Comm*>(synchro); if (comm->src_proc == simcall->issuer) comm->state = SIMIX_SRC_TIMEOUT; else comm->state = SIMIX_DST_TIMEOUT; } SIMIX_comm_finish(synchro); return; } /* If the synchro has already finish perform the error handling, */ /* otherwise set up a waiting timeout on the right side */ if (synchro->state != SIMIX_WAITING && synchro->state != SIMIX_RUNNING) { SIMIX_comm_finish(synchro); } else { /* if (timeout >= 0) { we need a surf sleep action even when there is no timeout, otherwise surf won't tell us when the host fails */ surf_action_t sleep = simcall->issuer->host->pimpl_cpu->sleep(timeout); sleep->setData(synchro); simgrid::kernel::activity::Comm *comm = static_cast<simgrid::kernel::activity::Comm*>(synchro); if (simcall->issuer == comm->src_proc) comm->src_timeout = sleep; else comm->dst_timeout = sleep; } }
/** * \ingroup msg_simulation * \brief Initialize MSG with less verifications * You should use the MSG_init() function instead. Failing to do so may turn into PEBKAC some day. You've been warned. */ void MSG_init_nocheck(int *argc, char **argv) { #ifdef HAVE_TRACING TRACE_global_init(argc, argv); #endif xbt_getpid = MSG_process_self_PID; if (!msg_global) { msg_global = xbt_new0(s_MSG_Global_t, 1); xbt_cfg_register(&_sg_cfg_set, "msg/debug_multiple_use", "Print backtraces of both processes when there is a conflict of multiple use of a task", xbt_cfgelm_boolean, 1, 1, _sg_cfg_cb_msg_debug_multiple_use, NULL); xbt_cfg_setdefault_boolean(_sg_cfg_set, "msg/debug_multiple_use", "no"); SIMIX_global_init(argc, argv); #ifdef MSG_USE_DEPRECATED msg_global->max_channel = 0; #endif msg_global->sent_msg = 0; msg_global->task_copy_callback = NULL; msg_global->process_data_cleanup = NULL; SIMIX_function_register_process_create(MSG_process_create_from_SIMIX); SIMIX_function_register_process_cleanup(MSG_process_cleanup_from_SIMIX); sg_platf_postparse_add_cb(MSG_post_create_environment); } if(MC_is_active()){ /* Ignore total amount of messages sent during the simulation for heap comparison */ MC_ignore_heap(&(msg_global->sent_msg), sizeof(msg_global->sent_msg)); } XBT_DEBUG("ADD MSG LEVELS"); MSG_HOST_LEVEL = xbt_lib_add_level(host_lib, (void_f_pvoid_t) __MSG_host_priv_free); MSG_STORAGE_LEVEL = xbt_lib_add_level(storage_lib, (void_f_pvoid_t) __MSG_storage_destroy); MSG_FILE_LEVEL = xbt_lib_add_level(file_lib, (void_f_pvoid_t) __MSG_file_destroy); if(sg_cfg_get_boolean("clean_atexit")) atexit(MSG_exit); }
/** * \ingroup msg_simulation * \brief Initialize MSG with less verifications * You should use the MSG_init() function instead. Failing to do so may turn into PEBKAC some day. You've been warned. */ void MSG_init_nocheck(int *argc, char **argv) { TRACE_global_init(argc, argv); xbt_getpid = MSG_process_self_PID; if (!msg_global) { msg_global = xbt_new0(s_MSG_Global_t, 1); xbt_cfg_register_boolean("msg/debug-multiple-use", "no", _sg_cfg_cb_msg_debug_multiple_use, "Print backtraces of both processes when there is a conflict of multiple use of a task"); SIMIX_global_init(argc, argv); msg_global->sent_msg = 0; msg_global->task_copy_callback = nullptr; msg_global->process_data_cleanup = nullptr; SIMIX_function_register_process_create(MSG_process_create_from_SIMIX); SIMIX_function_register_process_cleanup(MSG_process_cleanup_from_SIMIX); simgrid::surf::on_postparse.connect(MSG_post_create_environment); simgrid::s4u::Host::onCreation.connect([](simgrid::s4u::Host& host) { MSG_host_create_(&host); }); MSG_HOST_LEVEL = simgrid::s4u::Host::extension_create([](void *p) { __MSG_host_priv_free((msg_host_priv_t) p); }); } if(MC_is_active()){ /* Ignore total amount of messages sent during the simulation for heap comparison */ MC_ignore_heap(&(msg_global->sent_msg), sizeof(msg_global->sent_msg)); } XBT_DEBUG("ADD MSG LEVELS"); MSG_STORAGE_LEVEL = xbt_lib_add_level(storage_lib, (void_f_pvoid_t) __MSG_storage_destroy); MSG_FILE_LEVEL = xbt_lib_add_level(file_lib, (void_f_pvoid_t) __MSG_file_destroy); if(xbt_cfg_get_boolean("clean-atexit")) atexit(MSG_exit); }