Commit 22ede92e authored by Misha Shneerson's avatar Misha Shneerson Committed by Facebook Github Bot

store Linux thread identifier in TLS and use it

Summary:
Linux thread identifier is something that we can get with `gettid`.
http://man7.org/linux/man-pages/man2/gettid.2.html

This TID is super usefully for providing thread information while debugging on Linux (this is
the thing that `ps` command uses, or procfs), but is not really mappable from
`std::thread::id` (e.g. the thread handle we get with `pthread_self()`).

Reviewed By: yfeldblum

Differential Revision: D19134596

fbshipit-source-id: 32ad025c5e378e3c7b55da1aad8dd9f3e26d0892
parent 33d55e3c
...@@ -201,6 +201,10 @@ class SingletonThreadLocal { ...@@ -201,6 +201,10 @@ class SingletonThreadLocal {
std::thread::id getThreadId() const { std::thread::id getThreadId() const {
return this->base().getThreadId(); return this->base().getThreadId();
} }
uint64_t getOSThreadId() const {
return this->base().getOSThreadId();
}
}; };
Accessor(const Accessor&) = delete; Accessor(const Accessor&) = delete;
......
...@@ -373,6 +373,10 @@ class ThreadLocalPtr { ...@@ -373,6 +373,10 @@ class ThreadLocalPtr {
std::thread::id getThreadId() const { std::thread::id getThreadId() const {
return e_->getThreadEntry()->tid(); return e_->getThreadEntry()->tid();
} }
uint64_t getOSThreadId() const {
return e_->getThreadEntry()->tid_os;
}
}; };
~Accessor() { ~Accessor() {
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <folly/memory/Malloc.h> #include <folly/memory/Malloc.h>
#include <folly/portability/PThread.h> #include <folly/portability/PThread.h>
#include <folly/synchronization/MicroSpinLock.h> #include <folly/synchronization/MicroSpinLock.h>
#include <folly/system/ThreadId.h>
#include <folly/detail/StaticSingletonManager.h> #include <folly/detail/StaticSingletonManager.h>
...@@ -214,6 +215,7 @@ struct ThreadEntry { ...@@ -214,6 +215,7 @@ struct ThreadEntry {
ThreadEntry* listNext{nullptr}; ThreadEntry* listNext{nullptr};
StaticMetaBase* meta{nullptr}; StaticMetaBase* meta{nullptr};
bool removed_{false}; bool removed_{false};
uint64_t tid_os{};
aligned_storage_for_t<std::thread::id> tid_data{}; aligned_storage_for_t<std::thread::id> tid_data{};
size_t getElementsCapacity() const noexcept { size_t getElementsCapacity() const noexcept {
...@@ -480,6 +482,7 @@ struct StaticMeta final : StaticMetaBase { ...@@ -480,6 +482,7 @@ struct StaticMeta final : StaticMetaBase {
} }
threadEntry->tid() = std::this_thread::get_id(); threadEntry->tid() = std::this_thread::get_id();
threadEntry->tid_os = folly::getOSThreadID();
// if we're adding a thread entry // if we're adding a thread entry
// we need to increment the list count // we need to increment the list count
......
...@@ -772,12 +772,12 @@ RequestContext::StaticContext& RequestContext::getStaticContext() { ...@@ -772,12 +772,12 @@ RequestContext::StaticContext& RequestContext::getStaticContext() {
return SingletonT::get(); return SingletonT::get();
} }
/* static */ std::vector<std::pair<std::thread::id, intptr_t>> /* static */ std::vector<RequestContext::RootIdInfo>
RequestContext::getRootIdsFromAllThreads() { RequestContext::getRootIdsFromAllThreads() {
std::vector<std::pair<std::thread::id, intptr_t>> result; std::vector<RootIdInfo> result;
auto accessor = SingletonT::accessAllThreads(); auto accessor = SingletonT::accessAllThreads();
for (auto it = accessor.begin(); it != accessor.end(); ++it) { for (auto it = accessor.begin(); it != accessor.end(); ++it) {
result.push_back({it.getThreadId(), it->second}); result.push_back({it->second, it.getThreadId(), it.getOSThreadId()});
} }
return result; return result;
} }
......
...@@ -170,8 +170,12 @@ class RequestContext { ...@@ -170,8 +170,12 @@ class RequestContext {
return rootId_; return rootId_;
} }
static std::vector<std::pair<std::thread::id, intptr_t>> struct RootIdInfo {
getRootIdsFromAllThreads(); intptr_t id;
std::thread::id tid;
uint64_t tidOS;
};
static std::vector<RootIdInfo> getRootIdsFromAllThreads();
// The following APIs are used to add, remove and access RequestData instance // The following APIs are used to add, remove and access RequestData instance
// in the RequestContext instance, normally used for per-RequestContext // in the RequestContext instance, normally used for per-RequestContext
......
...@@ -77,7 +77,7 @@ class RequestContextTest : public ::testing::Test { ...@@ -77,7 +77,7 @@ class RequestContextTest : public ::testing::Test {
std::vector<intptr_t> result; std::vector<intptr_t> result;
std::transform( std::transform(
rootids.begin(), rootids.end(), std::back_inserter(result), [](auto e) { rootids.begin(), rootids.end(), std::back_inserter(result), [](auto e) {
return e.second; return e.id;
}); });
return result; return result;
} }
...@@ -373,7 +373,8 @@ TEST_F(RequestContextTest, ThreadId) { ...@@ -373,7 +373,8 @@ TEST_F(RequestContextTest, ThreadId) {
RequestContextScopeGuard g; RequestContextScopeGuard g;
auto ctxBase = std::make_shared<RequestContext>(); auto ctxBase = std::make_shared<RequestContext>();
auto rootids = RequestContext::getRootIdsFromAllThreads(); auto rootids = RequestContext::getRootIdsFromAllThreads();
EXPECT_EQ(*folly::getThreadName(rootids[0].first), "DummyThread"); EXPECT_EQ(*folly::getThreadName(rootids[0].tid), "DummyThread");
EXPECT_EQ(rootids[0].tidOS, folly::getOSThreadID());
EventBase base; EventBase base;
base.runInEventBaseThread([&]() { base.runInEventBaseThread([&]() {
...@@ -387,11 +388,11 @@ TEST_F(RequestContextTest, ThreadId) { ...@@ -387,11 +388,11 @@ TEST_F(RequestContextTest, ThreadId) {
th.join(); th.join();
std::sort(rootids.begin(), rootids.end(), [](const auto& a, const auto& b) { std::sort(rootids.begin(), rootids.end(), [](const auto& a, const auto& b) {
auto aname = folly::getThreadName(a.first); auto aname = folly::getThreadName(a.tid);
auto bname = folly::getThreadName(b.first); auto bname = folly::getThreadName(b.tid);
return (aname ? *aname : "zzz") < (bname ? *bname : "zzz"); return (aname ? *aname : "zzz") < (bname ? *bname : "zzz");
}); });
EXPECT_EQ(*folly::getThreadName(rootids[0].first), "DummyThread"); EXPECT_EQ(*folly::getThreadName(rootids[0].tid), "DummyThread");
EXPECT_FALSE(folly::getThreadName(rootids[1].first)); EXPECT_FALSE(folly::getThreadName(rootids[1].tid));
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment