X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/95da4b54779cd1eae048f8d1207e45231e5599da..610e12fc03b4aa83d87e3e52dd8fe5f1cf58b667:/src/mc/api.cpp diff --git a/src/mc/api.cpp b/src/mc/api.cpp index 1b133f7630..c62d73c8df 100644 --- a/src/mc/api.cpp +++ b/src/mc/api.cpp @@ -44,7 +44,7 @@ static std::string buff_size_to_string(size_t buff_size) } static void simcall_translate(smx_simcall_t req, - simgrid::mc::Remote& internal_comm); + simgrid::mc::Remote& buffered_comm); /* Search an enabled transition for the given process. * @@ -142,6 +142,7 @@ static inline smx_simcall_t MC_state_choose_request_for_process(simgrid::mc::Sta state->transition_.pid_ = actor->get_pid(); state->executed_req_ = *req; + // Fetch the data of the request and translate it: state->internal_req_ = *req; state->internal_req_.mc_value_ = state->transition_.times_considered_; @@ -151,7 +152,7 @@ static inline smx_simcall_t MC_state_choose_request_for_process(simgrid::mc::Sta } static void simcall_translate(smx_simcall_t req, - simgrid::mc::Remote& internal_comm) + simgrid::mc::Remote& buffered_comm) { simgrid::kernel::activity::CommImpl* chosen_comm; @@ -163,8 +164,8 @@ static void simcall_translate(smx_simcall_t req, chosen_comm = mc_model_checker->get_remote_simulation().read( remote(simcall_comm_waitany__get__comms(req) + req->mc_value_)); - mc_model_checker->get_remote_simulation().read(internal_comm, remote(chosen_comm)); - simcall_comm_wait__set__comm(req, internal_comm.get_buffer()); + mc_model_checker->get_remote_simulation().read(buffered_comm, remote(chosen_comm)); + simcall_comm_wait__set__comm(req, buffered_comm.get_buffer()); simcall_comm_wait__set__timeout(req, 0); break; @@ -173,21 +174,21 @@ static void simcall_translate(smx_simcall_t req, chosen_comm = mc_model_checker->get_remote_simulation().read( remote(simcall_comm_testany__get__comms(req) + req->mc_value_)); - mc_model_checker->get_remote_simulation().read(internal_comm, remote(chosen_comm)); - simcall_comm_test__set__comm(req, internal_comm.get_buffer()); + mc_model_checker->get_remote_simulation().read(buffered_comm, remote(chosen_comm)); + simcall_comm_test__set__comm(req, buffered_comm.get_buffer()); simcall_comm_test__set__result(req, req->mc_value_); break; case Simcall::COMM_WAIT: chosen_comm = simcall_comm_wait__getraw__comm(req); - mc_model_checker->get_remote_simulation().read(internal_comm, remote(chosen_comm)); - simcall_comm_wait__set__comm(req, internal_comm.get_buffer()); + mc_model_checker->get_remote_simulation().read(buffered_comm, remote(chosen_comm)); + simcall_comm_wait__set__comm(req, buffered_comm.get_buffer()); break; case Simcall::COMM_TEST: chosen_comm = simcall_comm_test__getraw__comm(req); - mc_model_checker->get_remote_simulation().read(internal_comm, remote(chosen_comm)); - simcall_comm_test__set__comm(req, internal_comm.get_buffer()); + mc_model_checker->get_remote_simulation().read(buffered_comm, remote(chosen_comm)); + simcall_comm_test__set__comm(req, buffered_comm.get_buffer()); break; default: @@ -196,16 +197,13 @@ static void simcall_translate(smx_simcall_t req, } } -simgrid::kernel::activity::CommImpl* Api::get_comm(smx_simcall_t const r) const +simgrid::kernel::activity::CommImpl* Api::get_comm_or_nullptr(smx_simcall_t const r) const { - switch (r->call_) { - case Simcall::COMM_WAIT: - return simcall_comm_wait__getraw__comm(r); - case Simcall::COMM_TEST: - return simcall_comm_test__getraw__comm(r); - default: - return nullptr; - } + if (r->call_ == Simcall::COMM_WAIT) + return simcall_comm_wait__getraw__comm(r); + if (r->call_ == Simcall::COMM_TEST) + return simcall_comm_test__getraw__comm(r); + return nullptr; } /** Statically "upcast" a s_smx_actor_t into an ActorInformation @@ -223,36 +221,33 @@ simgrid::mc::ActorInformation* Api::actor_info_cast(smx_actor_t actor) const return process_info; } -// Does half the job +// Does half the job. precondition: r1->call_ < r2->call_ bool Api::request_depend_asymmetric(smx_simcall_t r1, smx_simcall_t r2) const { - if (r1->call_ == Simcall::COMM_ISEND && r2->call_ == Simcall::COMM_IRECV) - return false; - if (r1->call_ == Simcall::COMM_IRECV && r2->call_ == Simcall::COMM_ISEND) return false; // Those are internal requests, we do not need indirection because those objects are copies: - const kernel::activity::CommImpl* acti1 = get_comm(r1); - const kernel::activity::CommImpl* acti2 = get_comm(r2); + auto comm1 = get_comm_or_nullptr(r1); + auto comm2 = get_comm_or_nullptr(r2); - if ((r1->call_ == Simcall::COMM_ISEND || r1->call_ == Simcall::COMM_IRECV) && r2->call_ == Simcall::COMM_WAIT) { + if ((r1->call_ == Simcall::COMM_IRECV || r1->call_ == Simcall::COMM_ISEND) && r2->call_ == Simcall::COMM_WAIT) { auto mbox1 = get_mbox_remote_addr(r1); - auto mbox2 = remote(acti2->mbox_cpy); + auto mbox2 = remote(comm2->mbox_cpy); if (mbox1 != mbox2 && simcall_comm_wait__get__timeout(r2) <= 0) return false; - if ((r1->issuer_ != acti2->src_actor_.get()) && (r1->issuer_ != acti2->dst_actor_.get()) && + if ((r1->issuer_ != comm2->src_actor_.get()) && (r1->issuer_ != comm2->dst_actor_.get()) && simcall_comm_wait__get__timeout(r2) <= 0) return false; - if ((r1->call_ == Simcall::COMM_ISEND) && (acti2->type_ == kernel::activity::CommImpl::Type::SEND) && - (acti2->src_buff_ != simcall_comm_isend__get__src_buff(r1)) && simcall_comm_wait__get__timeout(r2) <= 0) + if ((r1->call_ == Simcall::COMM_ISEND) && (comm2->type_ == kernel::activity::CommImpl::Type::SEND) && + (comm2->src_buff_ != simcall_comm_isend__get__src_buff(r1)) && simcall_comm_wait__get__timeout(r2) <= 0) return false; - if ((r1->call_ == Simcall::COMM_IRECV) && (acti2->type_ == kernel::activity::CommImpl::Type::RECEIVE) && - (acti2->dst_buff_ != simcall_comm_irecv__get__dst_buff(r1)) && simcall_comm_wait__get__timeout(r2) <= 0) + if ((r1->call_ == Simcall::COMM_IRECV) && (comm2->type_ == kernel::activity::CommImpl::Type::RECEIVE) && + (comm2->dst_buff_ != simcall_comm_irecv__get__dst_buff(r1)) && simcall_comm_wait__get__timeout(r2) <= 0) return false; } @@ -264,27 +259,82 @@ bool Api::request_depend_asymmetric(smx_simcall_t r1, smx_simcall_t r2) const return false; #endif - if (r1->call_ == Simcall::COMM_WAIT && (r2->call_ == Simcall::COMM_WAIT || r2->call_ == Simcall::COMM_TEST) && - (acti1->src_actor_.get() == nullptr || acti1->dst_actor_.get() == nullptr)) + if (r1->call_ == Simcall::COMM_TEST && r2->call_ == Simcall::COMM_WAIT && + (comm1->src_actor_.get() == nullptr || comm1->dst_actor_.get() == nullptr)) return false; if (r1->call_ == Simcall::COMM_TEST && - (simcall_comm_test__get__comm(r1) == nullptr || acti1->src_buff_ == nullptr || acti1->dst_buff_ == nullptr)) + (simcall_comm_test__get__comm(r1) == nullptr || comm1->src_buff_ == nullptr || comm1->dst_buff_ == nullptr)) + return false; + if (r2->call_ == Simcall::COMM_TEST && + (simcall_comm_test__get__comm(r2) == nullptr || comm2->src_buff_ == nullptr || comm2->dst_buff_ == nullptr)) return false; - if (r1->call_ == Simcall::COMM_TEST && r2->call_ == Simcall::COMM_WAIT && acti1->src_buff_ == acti2->src_buff_ && - acti1->dst_buff_ == acti2->dst_buff_) + if (r1->call_ == Simcall::COMM_TEST && r2->call_ == Simcall::COMM_WAIT && comm1->src_buff_ == comm2->src_buff_ && + comm1->dst_buff_ == comm2->dst_buff_) return false; - if (r1->call_ == Simcall::COMM_WAIT && r2->call_ == Simcall::COMM_TEST && acti1->src_buff_ != nullptr && - acti1->dst_buff_ != nullptr && acti2->src_buff_ != nullptr && acti2->dst_buff_ != nullptr && - acti1->dst_buff_ != acti2->src_buff_ && acti1->dst_buff_ != acti2->dst_buff_ && - acti2->dst_buff_ != acti1->src_buff_) + if (r1->call_ == Simcall::COMM_TEST && r2->call_ == Simcall::COMM_WAIT && comm1->src_buff_ != nullptr && + comm1->dst_buff_ != nullptr && comm2->src_buff_ != nullptr && comm2->dst_buff_ != nullptr && + comm1->dst_buff_ != comm2->src_buff_ && comm1->dst_buff_ != comm2->dst_buff_ && + comm2->dst_buff_ != comm1->src_buff_) return false; return true; } +bool Api::simcall_check_dependency(smx_simcall_t req1, smx_simcall_t req2) const +{ + const auto IRECV = Simcall::COMM_IRECV; + const auto ISEND = Simcall::COMM_ISEND; + const auto TEST = Simcall::COMM_TEST; + const auto WAIT = Simcall::COMM_WAIT; + + if (req1->issuer_ == req2->issuer_) + return false; + + /* The independence theorem only consider 4 simcalls. All others are dependent with anything. */ + if (req1->call_ != ISEND && req1->call_ != IRECV && req1->call_ != TEST && req1->call_ != WAIT) + return true; + if (req2->call_ != ISEND && req2->call_ != IRECV && req2->call_ != TEST && req2->call_ != WAIT) + return true; + + /* Timeouts in wait transitions are not considered by the independence theorem, thus assumed dependent */ + if ((req1->call_ == WAIT && simcall_comm_wait__get__timeout(req1) > 0) || + (req2->call_ == WAIT && simcall_comm_wait__get__timeout(req2) > 0)) + return true; + + /* Make sure that req1 and req2 are in alphabetic order */ + if (req1->call_ > req2->call_) { + auto temp = req1; + req1 = req2; + req2 = temp; + } + if (req1->call_ != req2->call_) + return request_depend_asymmetric(req1, req2); + + // Those are internal requests, we do not need indirection because those objects are copies: + const auto comm1 = get_comm_or_nullptr(req1); + const auto comm2 = get_comm_or_nullptr(req2); + + switch (req1->call_) { + case Simcall::COMM_ISEND: + return simcall_comm_isend__get__mbox(req1) == simcall_comm_isend__get__mbox(req2); + case Simcall::COMM_IRECV: + return simcall_comm_irecv__get__mbox(req1) == simcall_comm_irecv__get__mbox(req2); + case Simcall::COMM_WAIT: + if (comm1->src_buff_ == comm2->src_buff_ && comm1->dst_buff_ == comm2->dst_buff_) + return false; + if (comm1->src_buff_ != nullptr && comm1->dst_buff_ != nullptr && comm2->src_buff_ != nullptr && + comm2->dst_buff_ != nullptr && comm1->dst_buff_ != comm2->src_buff_ && comm1->dst_buff_ != comm2->dst_buff_ && + comm2->dst_buff_ != comm1->src_buff_) + return false; + return true; + default: + return true; + } +} + xbt::string const& Api::get_actor_host_name(smx_actor_t actor) const { if (mc_model_checker == nullptr) @@ -309,10 +359,10 @@ std::string Api::get_actor_name(smx_actor_t actor) const if (mc_model_checker == nullptr) return actor->get_cname(); - const simgrid::mc::RemoteSimulation* process = &mc_model_checker->get_remote_simulation(); - simgrid::mc::ActorInformation* info = actor_info_cast(actor); if (info->name.empty()) { + const simgrid::mc::RemoteSimulation* process = &mc_model_checker->get_remote_simulation(); + simgrid::xbt::string_data string_data = simgrid::xbt::string::to_string_data(actor->name_); info->name = process->read_string(remote(string_data.data), string_data.len); } @@ -387,11 +437,6 @@ RemotePtr Api::get_comm_isend_raw_addr(smx_simcall_t return remote(static_cast(simcall_comm_isend__getraw__result(request))); } -RemotePtr Api::get_comm_wait_raw_addr(smx_simcall_t request) const -{ - return remote(simcall_comm_wait__getraw__comm(request)); -} - RemotePtr Api::get_comm_waitany_raw_addr(smx_simcall_t request, int value) const { auto addr = simcall_comm_waitany__getraw__comms(request) + value; @@ -652,42 +697,6 @@ std::list Api::get_enabled_transitions(simgrid::mc::State* return tr_list; } -bool Api::simcall_check_dependency(smx_simcall_t const req1, smx_simcall_t const req2) const -{ - if (req1->issuer_ == req2->issuer_) - return false; - - /* Wait with timeout transitions are not considered by the independence theorem, thus we consider them as dependent - * with all other transitions */ - if ((req1->call_ == Simcall::COMM_WAIT && simcall_comm_wait__get__timeout(req1) > 0) || - (req2->call_ == Simcall::COMM_WAIT && simcall_comm_wait__get__timeout(req2) > 0)) - return true; - - if (req1->call_ != req2->call_) - return request_depend_asymmetric(req1, req2) && request_depend_asymmetric(req2, req1); - - // Those are internal requests, we do not need indirection because those objects are copies: - const kernel::activity::CommImpl* activity1 = get_comm(req1); - const kernel::activity::CommImpl* activity2 = get_comm(req2); - - switch (req1->call_) { - case Simcall::COMM_ISEND: - return simcall_comm_isend__get__mbox(req1) == simcall_comm_isend__get__mbox(req2); - case Simcall::COMM_IRECV: - return simcall_comm_irecv__get__mbox(req1) == simcall_comm_irecv__get__mbox(req2); - case Simcall::COMM_WAIT: - if (activity1->src_buff_ == activity2->src_buff_ && activity1->dst_buff_ == activity2->dst_buff_) - return false; - if (activity1->src_buff_ != nullptr && activity1->dst_buff_ != nullptr && activity2->src_buff_ != nullptr && - activity2->dst_buff_ != nullptr && activity1->dst_buff_ != activity2->src_buff_ && - activity1->dst_buff_ != activity2->dst_buff_ && activity2->dst_buff_ != activity1->src_buff_) - return false; - return true; - default: - return true; - } -} - std::string Api::request_to_string(smx_simcall_t req, int value) const { xbt_assert(mc_model_checker != nullptr, "Must be called from MCer");