Qutex: currOwner should use registered sh_ptr to Lockvoker

This ensures that the Lockvoker object we access from currOwner
remains valid past the lifetime of the Lockvoker object that
gets copied and invoked by boost::asio
This commit is contained in:
2025-09-29 14:37:16 -04:00
parent 462247d743
commit 2a60fdd9df
7 changed files with 22 additions and 16 deletions
+1 -1
View File
@@ -68,7 +68,7 @@ public:
// Implement the virtual method from AsynchronousContinuationChainLink
virtual std::shared_ptr<AsynchronousContinuationChainLink>
getCallersContinuation() override
getCallersContinuationShPtr() override
{ return originalCallback.callerContinuation; }
public:
+1 -1
View File
@@ -20,7 +20,7 @@ public:
virtual ~AsynchronousContinuationChainLink() = default;
virtual std::shared_ptr<AsynchronousContinuationChainLink>
getCallersContinuation() = 0;
getCallersContinuationShPtr() = 0;
};
} // namespace smo
+1 -1
View File
@@ -37,7 +37,7 @@ public:
* @param qutex The Qutex to get the iterator for
* @return Iterator pointing to this lockvoker in the Qutex's queue
*/
virtual List::iterator getLockvokerIteratorForQutex(Qutex& qutex) = 0;
virtual List::iterator getLockvokerIteratorForQutex(Qutex& qutex) const = 0;
/**
* @brief Awaken this lockvoker by posting it to its io_service
+3 -2
View File
@@ -90,13 +90,14 @@ public:
void release();
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
LockerAndInvokerBase* getCurrOwner() const { return currOwner; }
std::shared_ptr<LockerAndInvokerBase> getCurrOwner() const
{ return currOwner; }
#endif
public:
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
std::string name;
LockerAndInvokerBase* currOwner;
std::shared_ptr<LockerAndInvokerBase> currOwner;
#endif
SpinLock lock;
LockerAndInvokerBase::List queue;
+1 -1
View File
@@ -154,7 +154,7 @@ public:
* @return Iterator pointing to this lockvoker in the Qutex's queue
*/
LockerAndInvokerBase::List::iterator
getLockvokerIteratorForQutex(Qutex& qutex) override
getLockvokerIteratorForQutex(Qutex& qutex) const override
{
return serializedContinuation.requiredLocks.getLockUsageDesc(
qutex).second;
+7 -3
View File
@@ -44,7 +44,9 @@ bool Qutex::tryAcquire(
{
isOwned = true;
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
currOwner = const_cast<LockerAndInvokerBase*>(&tryingLockvoker);
// Use the stored iterator from the LockSet
auto it = tryingLockvoker.getLockvokerIteratorForQutex(*this);
currOwner = *it;
#endif
lock.release();
return true;
@@ -59,7 +61,7 @@ bool Qutex::tryAcquire(
{
isOwned = true;
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
currOwner = const_cast<LockerAndInvokerBase*>(&tryingLockvoker);
currOwner = queue.front();
#endif
ret = true;
}
@@ -96,7 +98,9 @@ bool Qutex::tryAcquire(
// Not found in rear portion - must be in top X%, so succeed
isOwned = true;
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
currOwner = const_cast<LockerAndInvokerBase*>(&tryingLockvoker);
// Use the stored iterator from the LockSet
auto it = tryingLockvoker.getLockvokerIteratorForQutex(*this);
currOwner = *it;
#endif
lock.release();
return true;
@@ -27,9 +27,9 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
* lockvoker.
*/
for (std::shared_ptr<AsynchronousContinuationChainLink> currContin =
this->serializedContinuation.getCallersContinuation();
this->serializedContinuation.getCallersContinuationShPtr();
currContin != nullptr;
currContin = currContin->getCallersContinuation())
currContin = currContin->getCallersContinuationShPtr())
{
auto serializedCont = std::dynamic_pointer_cast<
SerializedAsynchronousContinuation<OriginalCbFnT>>(currContin);
@@ -94,13 +94,14 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
* Hence, we have a gridlock.
*/
LockerAndInvokerBase* foreignOwnerPtr = firstFailedQutex.getCurrOwner();
std::shared_ptr<LockerAndInvokerBase> foreignOwnerShPtr =
firstFailedQutex.getCurrOwner();
// If no current owner, can't be a gridlock
if (foreignOwnerPtr == nullptr)
if (foreignOwnerShPtr == nullptr)
{ return false; }
// Use reference for the rest of the function for safety.
LockerAndInvokerBase& foreignOwner = *foreignOwnerPtr;
LockerAndInvokerBase &foreignOwner = *foreignOwnerShPtr;
/* For each lock in the foreign owner's LockSet, check if we hold it
* in any of our previous continuations (excluding our most immediate one)
@@ -128,9 +129,9 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
* should eventually be able to acquire that lock.
*/
for (std::shared_ptr<AsynchronousContinuationChainLink> currContin =
this->serializedContinuation.getCallersContinuation();
this->serializedContinuation.getCallersContinuationShPtr();
currContin != nullptr;
currContin = currContin->getCallersContinuation())
currContin = currContin->getCallersContinuationShPtr())
{
auto serializedCont = std::dynamic_pointer_cast<
SerializedAsynchronousContinuation<OriginalCbFnT>>(currContin);