summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@mongodb.com>2020-10-05 13:11:19 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-10-08 08:45:03 +0000
commitca0150eaf6cad95debae550c28fd50bb016db396 (patch)
treebc37490d499c2ada761a9ac2485ce8027fec5d10 /src/mongo/db/concurrency
parent1f11a9c73e11ebb6a89b1600a0a03741111c48bc (diff)
downloadmongo-ca0150eaf6cad95debae550c28fd50bb016db396.tar.gz
SERVER-50678 Implement lock-free version of AutoGetCollection
Diffstat (limited to 'src/mongo/db/concurrency')
-rw-r--r--src/mongo/db/concurrency/d_concurrency.cpp32
-rw-r--r--src/mongo/db/concurrency/d_concurrency.h12
2 files changed, 33 insertions, 11 deletions
diff --git a/src/mongo/db/concurrency/d_concurrency.cpp b/src/mongo/db/concurrency/d_concurrency.cpp
index a48d176689e..ea4738e55aa 100644
--- a/src/mongo/db/concurrency/d_concurrency.cpp
+++ b/src/mongo/db/concurrency/d_concurrency.cpp
@@ -139,11 +139,13 @@ bool Lock::ResourceMutex::isAtLeastReadLocked(Locker* locker) {
Lock::GlobalLock::GlobalLock(OperationContext* opCtx,
LockMode lockMode,
Date_t deadline,
- InterruptBehavior behavior)
+ InterruptBehavior behavior,
+ bool skipRSTLLock)
: _opCtx(opCtx),
_result(LOCK_INVALID),
_pbwm(opCtx->lockState(), resourceIdParallelBatchWriterMode),
_interruptBehavior(behavior),
+ _skipRSTLLock(skipRSTLLock),
_isOutermostLock(!opCtx->lockState()->isLocked()) {
_opCtx->lockState()->getFlowControlTicket(_opCtx, lockMode);
@@ -157,17 +159,14 @@ Lock::GlobalLock::GlobalLock(OperationContext* opCtx,
}
});
- _opCtx->lockState()->lock(
- _opCtx, resourceIdReplicationStateTransitionLock, MODE_IX, deadline);
-
- auto unlockRSTL = makeGuard(
- [this] { _opCtx->lockState()->unlock(resourceIdReplicationStateTransitionLock); });
-
_result = LOCK_INVALID;
- _opCtx->lockState()->lockGlobal(_opCtx, lockMode, deadline);
+ if (skipRSTLLock) {
+ _takeGlobalLockOnly(lockMode, deadline);
+ } else {
+ _takeGlobalAndRSTLLocks(lockMode, deadline);
+ }
_result = LOCK_OK;
- unlockRSTL.dismiss();
unlockPBWM.dismiss();
} catch (const ExceptionForCat<ErrorCategory::Interruption>&) {
// The kLeaveUnlocked behavior suppresses this exception.
@@ -178,11 +177,26 @@ Lock::GlobalLock::GlobalLock(OperationContext* opCtx,
_opCtx->lockState()->setGlobalLockTakenInMode(acquiredLockMode);
}
+void Lock::GlobalLock::_takeGlobalLockOnly(LockMode lockMode, Date_t deadline) {
+ _opCtx->lockState()->lockGlobal(_opCtx, lockMode, deadline);
+}
+
+void Lock::GlobalLock::_takeGlobalAndRSTLLocks(LockMode lockMode, Date_t deadline) {
+ _opCtx->lockState()->lock(_opCtx, resourceIdReplicationStateTransitionLock, MODE_IX, deadline);
+ auto unlockRSTL = makeGuard(
+ [this] { _opCtx->lockState()->unlock(resourceIdReplicationStateTransitionLock); });
+
+ _opCtx->lockState()->lockGlobal(_opCtx, lockMode, deadline);
+
+ unlockRSTL.dismiss();
+}
+
Lock::GlobalLock::GlobalLock(GlobalLock&& otherLock)
: _opCtx(otherLock._opCtx),
_result(otherLock._result),
_pbwm(std::move(otherLock._pbwm)),
_interruptBehavior(otherLock._interruptBehavior),
+ _skipRSTLLock(otherLock._skipRSTLLock),
_isOutermostLock(otherLock._isOutermostLock) {
// Mark as moved so the destructor doesn't invalidate the newly-constructed lock.
otherLock._result = LOCK_INVALID;
diff --git a/src/mongo/db/concurrency/d_concurrency.h b/src/mongo/db/concurrency/d_concurrency.h
index 187cb3d5a41..4ae7af8cdb9 100644
--- a/src/mongo/db/concurrency/d_concurrency.h
+++ b/src/mongo/db/concurrency/d_concurrency.h
@@ -221,7 +221,8 @@ public:
GlobalLock(OperationContext* opCtx,
LockMode lockMode,
Date_t deadline,
- InterruptBehavior behavior);
+ InterruptBehavior behavior,
+ bool skipRSTLLock = false);
GlobalLock(GlobalLock&&);
@@ -239,7 +240,7 @@ public:
}
_unlock();
}
- if (lockResult == LOCK_OK || lockResult == LOCK_WAITING) {
+ if (!_skipRSTLLock && (lockResult == LOCK_OK || lockResult == LOCK_WAITING)) {
_opCtx->lockState()->unlock(resourceIdReplicationStateTransitionLock);
}
}
@@ -249,12 +250,19 @@ public:
}
private:
+ /**
+ * Constructor helper functions, to handle skipping or taking the RSTL lock.
+ */
+ void _takeGlobalLockOnly(LockMode lockMode, Date_t deadline);
+ void _takeGlobalAndRSTLLocks(LockMode lockMode, Date_t deadline);
+
void _unlock();
OperationContext* const _opCtx;
LockResult _result;
ResourceLock _pbwm;
InterruptBehavior _interruptBehavior;
+ bool _skipRSTLLock;
const bool _isOutermostLock;
};