-/* Copyright (c) 2012-2022. The SimGrid Team. All rights reserved. */
+/* Copyright (c) 2012-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 "simgrid/s4u/Mutex.hpp"
#include "src/kernel/activity/ActivityImpl.hpp"
#include "src/kernel/actor/ActorImpl.hpp"
+#include "xbt/asserts.h"
#include <boost/intrusive/list.hpp>
-namespace simgrid {
-namespace kernel {
-namespace activity {
+namespace simgrid::kernel::activity {
/** Mutex Acquisition: the act / process of acquiring the mutex.
*
* of a set if some transitions may become disabled in between, while you don't have to reconsider them if you can reuse
* your previous computations).
*/
-class XBT_PUBLIC MutexAcquisitionImpl
- : public ActivityImpl_T<MutexAcquisitionImpl> { // Acquisition: n. The act or process of acquiring.
+class XBT_PUBLIC MutexAcquisitionImpl : public ActivityImpl_T<MutexAcquisitionImpl> {
actor::ActorImpl* issuer_ = nullptr;
MutexImpl* mutex_ = nullptr;
+ int recursive_depth_ = 1;
+ // TODO: use granted_ this instead of owner_ == self to test().
+ // This is mandatory to get double-lock on non-recursive locks to properly deadlock
+ bool granted_ = false;
+
+ friend MutexImpl;
public:
MutexAcquisitionImpl(actor::ActorImpl* issuer, MutexImpl* mutex) : issuer_(issuer), mutex_(mutex) {}
- MutexImplPtr get_mutex() { return mutex_; }
- actor::ActorImpl* get_issuer() { return issuer_; }
+ MutexImplPtr get_mutex() const { return mutex_; }
+ actor::ActorImpl* get_issuer() const { return issuer_; }
+ void grant() { granted_ = true; }
+ bool is_granted() const { return granted_; }
bool test(actor::ActorImpl* issuer = nullptr) override;
void wait_for(actor::ActorImpl* issuer, double timeout) override;
- void post() override
- { /*no surf action*/
- }
void finish() override;
void set_exception(actor::ActorImpl* issuer) override
{ /* nothing to do */
std::atomic_int_fast32_t refcount_{1};
s4u::Mutex piface_;
actor::ActorImpl* owner_ = nullptr;
- // List of sleeping actors:
- std::deque<MutexAcquisitionImplPtr> sleeping_;
+ std::deque<MutexAcquisitionImplPtr> ongoing_acquisitions_;
static unsigned next_id_;
- unsigned id_;
+ unsigned id_ = next_id_++;
+ bool is_recursive_ = false;
+ int recursive_depth = 0;
friend MutexAcquisitionImpl;
public:
- MutexImpl() : piface_(this), id_(next_id_++) {}
+ explicit MutexImpl(bool recursive = false) : piface_(this), is_recursive_(recursive) {}
MutexImpl(MutexImpl const&) = delete;
MutexImpl& operator=(MutexImpl const&) = delete;
void unlock(actor::ActorImpl* issuer);
unsigned get_id() const { return id_; }
- MutexImpl* ref();
- void unref();
-
actor::ActorImpl* get_owner() const { return owner_; }
// boost::intrusive_ptr<Mutex> support:
friend void intrusive_ptr_release(MutexImpl* mutex)
{
- if (mutex->refcount_.fetch_sub(1) == 1)
+ if (mutex->refcount_.fetch_sub(1) == 1) {
+ xbt_assert(mutex->ongoing_acquisitions_.empty(), "The destroyed mutex still had ongoing acquisitions");
+ xbt_assert(mutex->owner_ == nullptr, "The destroyed mutex is still owned by actor %s",
+ mutex->owner_->get_cname());
delete mutex;
+ }
}
- s4u::Mutex& mutex() { return piface_; }
+ s4u::Mutex& get_iface() { return piface_; }
};
-} // namespace activity
-} // namespace kernel
-} // namespace simgrid
+} // namespace simgrid::kernel::activity
#endif