X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/e4339afd9b4ae5f3558a0348f24b0022db3501d5..97e476dc536bfd9fada85509d1c1f93714d46a10:/src/s4u/s4u_Barrier.cpp diff --git a/src/s4u/s4u_Barrier.cpp b/src/s4u/s4u_Barrier.cpp index 1bb6e23225..80ce0e29b2 100644 --- a/src/s4u/s4u_Barrier.cpp +++ b/src/s4u/s4u_Barrier.cpp @@ -4,8 +4,12 @@ * under the terms of the license (GNU LGPL) which comes with this package. */ #include +#include #include -#include + +#include "src/kernel/activity/BarrierImpl.hpp" +#include "src/kernel/actor/SynchroObserver.hpp" +#include "src/mc/mc_replay.hpp" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(s4u_barrier, s4u, "S4U barrier"); @@ -18,45 +22,45 @@ namespace s4u { */ BarrierPtr Barrier::create(unsigned int expected_actors) { - return BarrierPtr(new Barrier(expected_actors)); + auto* res = new kernel::activity::BarrierImpl(expected_actors); + return BarrierPtr(&res->piface_); } /** @brief Block the current actor until all expected actors reach the barrier. * * This method is meant to be somewhat consistent with the pthread_barrier_wait function. * - * @return 0 for all actors but one: exactly one actor will get SG_BARRIER_SERIAL_THREAD as a return value. + * @return false for all actors but one: exactly one actor will get true as a return value. */ int Barrier::wait() { - mutex_->lock(); - arrived_actors_++; - XBT_DEBUG("waiting %p %u/%u", this, arrived_actors_, expected_actors_); - if (arrived_actors_ == expected_actors_) { - cond_->notify_all(); - arrived_actors_ = 0; - mutex_->unlock(); - return SG_BARRIER_SERIAL_THREAD; - } + kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self(); - cond_->wait(mutex_); - mutex_->unlock(); - return 0; + if (MC_is_active() || MC_record_replay_is_active()) { // Split in 2 simcalls for transition persistency + kernel::actor::BarrierObserver lock_observer{issuer, mc::Transition::Type::BARRIER_LOCK, pimpl_}; + auto acquisition = + kernel::actor::simcall_answered([issuer, this] { return pimpl_->acquire_async(issuer); }, &lock_observer); + + kernel::actor::BarrierObserver wait_observer{issuer, mc::Transition::Type::BARRIER_WAIT, acquisition.get()}; + return kernel::actor::simcall_blocking([issuer, acquisition] { return acquisition->wait_for(issuer, -1); }, + &wait_observer); + + } else { // Do it in one simcall only + kernel::activity::BarrierAcquisitionImpl* acqui = nullptr; // unused here, but must be typed to pick the right ctor + kernel::actor::BarrierObserver observer{issuer, mc::Transition::Type::BARRIER_WAIT, acqui}; + return kernel::actor::simcall_blocking([issuer, this] { pimpl_->acquire_async(issuer)->wait_for(issuer, -1); }, + &observer); + } } void intrusive_ptr_add_ref(Barrier* barrier) { - xbt_assert(barrier); - barrier->refcount_.fetch_add(1, std::memory_order_relaxed); + intrusive_ptr_add_ref(barrier->pimpl_); } void intrusive_ptr_release(Barrier* barrier) { - xbt_assert(barrier); - if (barrier->refcount_.fetch_sub(1, std::memory_order_release) == 1) { - std::atomic_thread_fence(std::memory_order_acquire); - delete barrier; - } + intrusive_ptr_release(barrier->pimpl_); } } // namespace s4u } // namespace simgrid @@ -65,17 +69,23 @@ void intrusive_ptr_release(Barrier* barrier) sg_bar_t sg_barrier_init(unsigned int count) { - return new simgrid::s4u::Barrier(count); + simgrid::s4u::BarrierPtr bar = simgrid::s4u::Barrier::create(count); + intrusive_ptr_add_ref(bar.get()); + return bar.get(); } /** @brief Initializes a barrier, with count elements */ -void sg_barrier_destroy(const_sg_bar_t bar) +void sg_barrier_destroy(sg_bar_t bar) { - delete bar; + intrusive_ptr_release(bar); } -/** @brief Performs a barrier already initialized */ +/** @brief Performs a barrier already initialized. + * + * @return 0 for all actors but one: exactly one actor will get SG_BARRIER_SERIAL_THREAD as a return value. */ int sg_barrier_wait(sg_bar_t bar) { - return bar->wait(); + if (bar->wait()) + return SG_BARRIER_SERIAL_THREAD; + return 0; }