diff options
-rwxr-xr-x | buildscripts/hang_analyzer.py | 1 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_manager.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state.h | 5 | ||||
-rw-r--r-- | src/mongo/db/concurrency/locker.h | 7 | ||||
-rw-r--r-- | src/mongo/db/concurrency/locker_noop.h | 4 |
6 files changed, 32 insertions, 1 deletions
diff --git a/buildscripts/hang_analyzer.py b/buildscripts/hang_analyzer.py index 3ea07eeded4..fa45e259e59 100755 --- a/buildscripts/hang_analyzer.py +++ b/buildscripts/hang_analyzer.py @@ -299,6 +299,7 @@ class GDBDumper(object): "source " + printers_script, "thread apply all bt", "gcore dump_" + process_name + "." + str(pid) + "." + self.get_dump_ext() if take_dump else "", + "mongodb-analyze", "set confirm off", "quit", ] diff --git a/src/mongo/db/concurrency/lock_manager.cpp b/src/mongo/db/concurrency/lock_manager.cpp index 815a235d623..8496e81fc6c 100644 --- a/src/mongo/db/concurrency/lock_manager.cpp +++ b/src/mongo/db/concurrency/lock_manager.cpp @@ -32,6 +32,8 @@ #include "mongo/db/concurrency/lock_manager.h" +#include <sstream> + #include "mongo/base/simple_string_data_comparator.h" #include "mongo/base/static_assert.h" #include "mongo/bson/bsonobjbuilder.h" @@ -896,8 +898,11 @@ void LockManager::_dumpBucket(const LockBucket* bucket) const { sb << "GRANTED:\n"; for (const LockRequest* iter = lock->grantedList._front; iter != nullptr; iter = iter->next) { + std::stringstream threadId; + threadId << iter->locker->getThreadId(); sb << '\t' << "LockRequest " << iter->locker->getId() << " @ " << iter->locker << ": " << "Mode = " << modeName(iter->mode) << "; " + << "Thread = " << threadId.str() << "; " << "ConvertMode = " << modeName(iter->convertMode) << "; " << "EnqueueAtFront = " << iter->enqueueAtFront << "; " << "CompatibleFirst = " << iter->compatibleFirst << "; " << '\n'; @@ -906,8 +911,11 @@ void LockManager::_dumpBucket(const LockBucket* bucket) const { sb << "PENDING:\n"; for (const LockRequest* iter = lock->conflictList._front; iter != nullptr; iter = iter->next) { + std::stringstream threadId; + threadId << iter->locker->getThreadId(); sb << '\t' << "LockRequest " << iter->locker->getId() << " @ " << iter->locker << ": " << "Mode = " << modeName(iter->mode) << "; " + << "Thread = " << threadId.str() << "; " << "ConvertMode = " << modeName(iter->convertMode) << "; " << "EnqueueAtFront = " << iter->enqueueAtFront << "; " << "CompatibleFirst = " << iter->compatibleFirst << "; " << '\n'; diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp index a119c8b9ae0..898f9cd462e 100644 --- a/src/mongo/db/concurrency/lock_state.cpp +++ b/src/mongo/db/concurrency/lock_state.cpp @@ -270,7 +270,13 @@ void Locker::setGlobalThrottling(class TicketHolder* reading, class TicketHolder } template <bool IsForMMAPV1> -LockerImpl<IsForMMAPV1>::LockerImpl() : _id(idCounter.addAndFetch(1)), _wuowNestingLevel(0) {} +LockerImpl<IsForMMAPV1>::LockerImpl() + : _id(idCounter.addAndFetch(1)), _wuowNestingLevel(0), _threadId(stdx::this_thread::get_id()) {} + +template <bool IsForMMAPV1> +stdx::thread::id LockerImpl<IsForMMAPV1>::getThreadId() const { + return _threadId; +} template <bool IsForMMAPV1> LockerImpl<IsForMMAPV1>::~LockerImpl() { diff --git a/src/mongo/db/concurrency/lock_state.h b/src/mongo/db/concurrency/lock_state.h index 9c0ebd837ca..79f348d4ac6 100644 --- a/src/mongo/db/concurrency/lock_state.h +++ b/src/mongo/db/concurrency/lock_state.h @@ -99,6 +99,8 @@ public: return _id; } + stdx::thread::id getThreadId() const override; + virtual LockResult lockGlobal(LockMode mode, unsigned timeoutMs = UINT_MAX); virtual LockResult lockGlobalBegin(LockMode mode); virtual LockResult lockGlobalComplete(unsigned timeoutMs); @@ -223,6 +225,9 @@ private: // Indicates whether the client is active reader/writer or is queued. AtomicWord<ClientState> _clientState{kInactive}; + // Track the thread who owns the lock for debugging purposes + stdx::thread::id _threadId; + ////////////////////////////////////////////////////////////////////////////////////////// // // Methods merged from LockState, which should eventually be removed or changed to methods diff --git a/src/mongo/db/concurrency/locker.h b/src/mongo/db/concurrency/locker.h index ca8501393dd..e00882a498d 100644 --- a/src/mongo/db/concurrency/locker.h +++ b/src/mongo/db/concurrency/locker.h @@ -33,6 +33,7 @@ #include "mongo/db/concurrency/lock_manager.h" #include "mongo/db/concurrency/lock_stats.h" +#include "mongo/stdx/thread.h" namespace mongo { @@ -83,6 +84,12 @@ public: virtual LockerId getId() const = 0; /** + * Get a platform-specific thread identifier of the thread which owns the this locker for + * tracing purposes. + */ + virtual stdx::thread::id getThreadId() const = 0; + + /** * This should be the first method invoked for a particular Locker object. It acquires the * Global lock in the specified mode and effectively indicates the mode of the operation. * This is what the lock modes on the global lock mean: diff --git a/src/mongo/db/concurrency/locker_noop.h b/src/mongo/db/concurrency/locker_noop.h index 04786f4a13e..24450ceeecc 100644 --- a/src/mongo/db/concurrency/locker_noop.h +++ b/src/mongo/db/concurrency/locker_noop.h @@ -53,6 +53,10 @@ public: invariant(false); } + stdx::thread::id getThreadId() const override { + invariant(false); + } + virtual LockResult lockGlobal(LockMode mode, unsigned timeoutMs) { invariant(false); } |