X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/ea74f5d95928a521a588737e81f1de94eef25d19..63d238ad4d74226fae3321cb5c128f03160dacb2:/src/kernel/activity/MutexImpl.cpp diff --git a/src/kernel/activity/MutexImpl.cpp b/src/kernel/activity/MutexImpl.cpp index 660d77cfe4..cac3e9524d 100644 --- a/src/kernel/activity/MutexImpl.cpp +++ b/src/kernel/activity/MutexImpl.cpp @@ -1,46 +1,89 @@ -/* Copyright (c) 2007-2022. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2007-2023. The SimGrid Team. All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ #include "src/kernel/activity/MutexImpl.hpp" -#include "src/kernel/activity/SynchroRaw.hpp" - -#if SIMGRID_HAVE_MC -#include "simgrid/modelchecker.h" -#include "src/mc/mc_safety.hpp" -#define MC_CHECK_NO_DPOR() \ - xbt_assert(not MC_is_active() || mc::reduction_mode != mc::ReductionMode::dpor, \ - "Mutex is currently not supported with DPOR, use --cfg=model-check/reduction:none") -#else -#define MC_CHECK_NO_DPOR() (void)0 -#endif +#include "src/kernel/activity/Synchro.hpp" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ker_mutex, ker_synchro, "Mutex kernel-space implementation"); -namespace simgrid { -namespace kernel { -namespace activity { +namespace simgrid::kernel::activity { -void MutexImpl::lock(actor::ActorImpl* issuer) +/* -------- Acquisition -------- */ + +bool MutexAcquisitionImpl::test(actor::ActorImpl*) +{ + return mutex_->owner_ == issuer_; +} +void MutexAcquisitionImpl::wait_for(actor::ActorImpl* issuer, double timeout) { - XBT_IN("(%p; %p)", this, issuer); - MC_CHECK_NO_DPOR(); - - if (locked_) { - /* FIXME: check if the host is active ? */ - /* Somebody using the mutex, use a synchronization to get host failures */ - RawImplPtr synchro(new RawImpl([this, issuer]() { this->remove_sleeping_actor(*issuer); })); - (*synchro).set_host(issuer->get_host()).start(); - synchro->register_simcall(&issuer->simcall_); - sleeping_.push_back(*issuer); + xbt_assert(mutex_->owner_ != nullptr); // it was locked either by someone else or by me during the lock_async + xbt_assert(issuer == issuer_, "Cannot wait on acquisitions created by another actor (id %ld)", issuer_->get_pid()); + xbt_assert(timeout < 0, "Timeouts on mutex acquisitions are not implemented yet."); + + this->register_simcall(&issuer_->simcall_); // Block on that acquisition + + if (mutex_->get_owner() == issuer_) { // I'm the owner + finish(); } else { - /* mutex free */ - locked_ = true; + // Already in the queue + } +} + +void MutexAcquisitionImpl::finish() +{ + xbt_assert(simcalls_.size() == 1, "Unexpected number of simcalls waiting: %zu", simcalls_.size()); + actor::Simcall* simcall = simcalls_.front(); + simcalls_.pop_front(); + + simcall->issuer_->waiting_synchro_ = nullptr; + simcall->issuer_->simcall_answer(); +} + +/* -------- Mutex -------- */ + +unsigned MutexImpl::next_id_ = 0; + +MutexAcquisitionImplPtr MutexImpl::lock_async(actor::ActorImpl* issuer) +{ + /* If the mutex is recursive */ + if (is_recursive_) { + if (owner_ == issuer) { + recursive_depth++; + auto res = MutexAcquisitionImplPtr(new kernel::activity::MutexAcquisitionImpl(issuer, this), true); + res->grant(); + return res; + } else if (owner_ == nullptr) { // Free + owner_ = issuer; + recursive_depth = 1; + auto res = MutexAcquisitionImplPtr(new kernel::activity::MutexAcquisitionImpl(issuer, this), true); + res->grant(); + return res; + } + + for (auto acq : ongoing_acquisitions_) + if (acq->get_issuer() == issuer) { + acq->recursive_depth_++; + return acq; + } + + // Not yet in the ongoing acquisition list. Get in there + auto res = MutexAcquisitionImplPtr(new kernel::activity::MutexAcquisitionImpl(issuer, this), true); + ongoing_acquisitions_.push_back(res); + return res; + } + + // Non-recursive mutex + auto res = MutexAcquisitionImplPtr(new kernel::activity::MutexAcquisitionImpl(issuer, this), true); + if (owner_ == nullptr) { // Lock is free, take it owner_ = issuer; - issuer->simcall_answer(); + recursive_depth = 1; + res->grant(); + } else { // Somebody is using the mutex; register the acquisition + ongoing_acquisitions_.push_back(res); } - XBT_OUT(); + return res; } /** Tries to lock the mutex for a actor @@ -50,16 +93,14 @@ void MutexImpl::lock(actor::ActorImpl* issuer) */ bool MutexImpl::try_lock(actor::ActorImpl* issuer) { - XBT_IN("(%p, %p)", this, issuer); - MC_CHECK_NO_DPOR(); - if (locked_) { - XBT_OUT(); - return false; + if (owner_ == issuer && is_recursive_) { + recursive_depth++; + return true; } + if (owner_ != nullptr) + return false; - locked_ = true; - owner_ = issuer; - XBT_OUT(); + owner_ = issuer; return true; } @@ -72,36 +113,32 @@ bool MutexImpl::try_lock(actor::ActorImpl* issuer) void MutexImpl::unlock(actor::ActorImpl* issuer) { XBT_IN("(%p, %p)", this, issuer); - xbt_assert(locked_, "Cannot release that mutex: it was not locked."); - xbt_assert(issuer == owner_, "Cannot release that mutex: it was locked by %s (pid:%ld), not by you.", - owner_->get_cname(), owner_->get_pid()); + xbt_assert(issuer == owner_, "Cannot release that mutex: you're not the owner. %s is (pid:%ld).", + owner_ != nullptr ? owner_->get_cname() : "(nobody)", owner_ != nullptr ? owner_->get_pid() : -1); + + if (is_recursive_) { + recursive_depth--; + if (recursive_depth > 0) // Still owning the lock + return; + } - if (not sleeping_.empty()) { + if (not ongoing_acquisitions_.empty()) { /* Give the ownership to the first waiting actor */ - owner_ = &sleeping_.front(); - sleeping_.pop_front(); - owner_->waiting_synchro_ = nullptr; - owner_->simcall_answer(); + auto acq = ongoing_acquisitions_.front(); + ongoing_acquisitions_.pop_front(); + + owner_ = acq->get_issuer(); + acq->grant(); + recursive_depth = acq->recursive_depth_; + if (acq == owner_->waiting_synchro_) + acq->finish(); + // else, the issuer is not blocked on this acquisition so no need to release it + } else { /* nobody to wake up */ - locked_ = false; owner_ = nullptr; } XBT_OUT(); } -/** Increase the refcount for this mutex */ -MutexImpl* MutexImpl::ref() -{ - intrusive_ptr_add_ref(this); - return this; -} - -/** Decrease the refcount for this mutex */ -void MutexImpl::unref() -{ - intrusive_ptr_release(this); -} -} // namespace activity -} // namespace kernel -} // namespace simgrid +} // namespace simgrid::kernel::activity