summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2016-12-08 15:15:01 -0500
committerMark Benvenuto <mark.benvenuto@mongodb.com>2016-12-08 15:15:01 -0500
commite713fab06dba2dd34b66ecdcf891a04377b74f1f (patch)
tree2360c44b8693bd9f83d1f3195c82f50fade7a59e /src
parentaad88dd01b39f1c689280289e8fe00f87dcb1db3 (diff)
downloadmongo-e713fab06dba2dd34b66ecdcf891a04377b74f1f.tar.gz
SERVER-27191 hang analyzer should dump lock manager state
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/concurrency/lock_manager.cpp8
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp8
-rw-r--r--src/mongo/db/concurrency/lock_state.h5
-rw-r--r--src/mongo/db/concurrency/locker.h7
-rw-r--r--src/mongo/db/concurrency/locker_noop.h4
5 files changed, 31 insertions, 1 deletions
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);
}