-/* 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. */
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ker_mutex, ker_synchro, "Mutex kernel-space implementation");
-namespace simgrid {
-namespace kernel {
-namespace activity {
+namespace simgrid::kernel::activity {
/* -------- Acquisition -------- */
// Already in the queue
}
}
+
void MutexAcquisitionImpl::finish()
{
xbt_assert(simcalls_.size() == 1, "Unexpected number of simcalls waiting: %zu", simcalls_.size());
MutexAcquisitionImplPtr MutexImpl::lock_async(actor::ActorImpl* issuer)
{
- auto res = MutexAcquisitionImplPtr(new kernel::activity::MutexAcquisitionImpl(issuer, this), true);
-
- if (owner_ != nullptr) {
- /* Somebody is using the mutex; register the acquisition */
+ /* 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);
- } else {
+ 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;
+ recursive_depth = 1;
+ res->grant();
+ } else { // Somebody is using the mutex; register the acquisition
+ ongoing_acquisitions_.push_back(res);
}
return res;
}
*/
bool MutexImpl::try_lock(actor::ActorImpl* issuer)
{
- XBT_IN("(%p, %p)", this, issuer);
- if (owner_ != nullptr) {
- XBT_OUT();
- return false;
+ if (owner_ == issuer && is_recursive_) {
+ recursive_depth++;
+ return true;
}
+ if (owner_ != nullptr)
+ return false;
- owner_ = issuer;
- XBT_OUT();
+ owner_ = issuer;
return true;
}
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 ongoing_acquisitions_.empty()) {
/* Give the ownership to the first waiting actor */
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
XBT_OUT();
}
-} // namespace activity
-} // namespace kernel
-} // namespace simgrid
+} // namespace simgrid::kernel::activity