summaryrefslogtreecommitdiff
path: root/src/mongo/db/operation_context.cpp
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2019-01-23 13:18:49 -0500
committerJason Carey <jcarey@argv.me>2019-02-05 22:41:49 -0500
commita23cdb1bd0f8fbe9cd79db08a24b8a89dc54ff81 (patch)
tree1adc2fdb36e6c8babaab134d53f84de3020c2404 /src/mongo/db/operation_context.cpp
parent5fd66f15797c45c9bab7b59f9e55e0a2f7ad5cd0 (diff)
downloadmongo-a23cdb1bd0f8fbe9cd79db08a24b8a89dc54ff81.tar.gz
SERVER-39146 Refactor Baton
Refactor the baton into regular and networking batons while also cleaning up the basic baton implementation.
Diffstat (limited to 'src/mongo/db/operation_context.cpp')
-rw-r--r--src/mongo/db/operation_context.cpp20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/mongo/db/operation_context.cpp b/src/mongo/db/operation_context.cpp
index 11ca8b8f641..319b803288c 100644
--- a/src/mongo/db/operation_context.cpp
+++ b/src/mongo/db/operation_context.cpp
@@ -77,6 +77,8 @@ MONGO_FAIL_POINT_DEFINE(maxTimeNeverTimeOut);
// inclusive.
MONGO_FAIL_POINT_DEFINE(checkForInterruptFail);
+const auto kNoWaiterThread = stdx::thread::id();
+
} // namespace
OperationContext::OperationContext(Client* client, unsigned int opId)
@@ -261,6 +263,7 @@ StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAsser
stdx::lock_guard<Client> clientLock(*getClient());
invariant(!_waitMutex);
invariant(!_waitCV);
+ invariant(_waitThread == kNoWaiterThread);
invariant(0 == _numKillers);
// This interrupt check must be done while holding the client lock, so as not to race with a
@@ -271,6 +274,7 @@ StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAsser
}
_waitMutex = m.mutex();
_waitCV = &cv;
+ _waitThread = stdx::this_thread::get_id();
}
// If the maxTimeNeverTimeOut failpoint is set, behave as though the operation's deadline does
@@ -302,6 +306,7 @@ StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAsser
if (0 == _numKillers) {
_waitMutex = nullptr;
_waitCV = nullptr;
+ _waitThread = kNoWaiterThread;
return true;
}
return false;
@@ -328,7 +333,20 @@ StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAsser
void OperationContext::markKilled(ErrorCodes::Error killCode) {
invariant(killCode != ErrorCodes::OK);
stdx::unique_lock<stdx::mutex> lkWaitMutex;
- if (_waitMutex) {
+
+ // If we have a _waitMutex, it means this opCtx is currently blocked in
+ // waitForConditionOrInterrupt.
+ //
+ // From there, we also know which thread is actually doing that waiting (it's recorded in
+ // _waitThread). If that thread isn't our thread, it's necessary to do the regular numKillers
+ // song and dance mentioned in waitForConditionOrInterrupt.
+ //
+ // If it is our thread, we know that we're currently inside that call to
+ // waitForConditionOrInterrupt and are being invoked by a callback run from Baton->run. And
+ // that means we don't need to deal with the waitMutex and waitCV (because we're running
+ // callbacks, which means run is returning, which means we'll be checking _killCode in the near
+ // future).
+ if (_waitMutex && stdx::this_thread::get_id() != _waitThread) {
invariant(++_numKillers > 0);
getClient()->unlock();
ON_BLOCK_EXIT([this] {