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 {
std::thread::id getThreadId() const {
return this->base().getThreadId();
}
uint64_t getOSThreadId() const {
return this->base().getOSThreadId();
}
};
Accessor(const Accessor&) = delete;
......
......@@ -373,6 +373,10 @@ class ThreadLocalPtr {
std::thread::id getThreadId() const {
return e_->getThreadEntry()->tid();
}
uint64_t getOSThreadId() const {
return e_->getThreadEntry()->tid_os;
}
};
~Accessor() {
......
......@@ -37,6 +37,7 @@
#include <folly/memory/Malloc.h>
#include <folly/portability/PThread.h>
#include <folly/synchronization/MicroSpinLock.h>
#include <folly/system/ThreadId.h>
#include <folly/detail/StaticSingletonManager.h>
......@@ -214,6 +215,7 @@ struct ThreadEntry {
ThreadEntry* listNext{nullptr};
StaticMetaBase* meta{nullptr};
bool removed_{false};
uint64_t tid_os{};
aligned_storage_for_t<std::thread::id> tid_data{};
size_t getElementsCapacity() const noexcept {
......@@ -480,6 +482,7 @@ struct StaticMeta final : StaticMetaBase {
}
threadEntry->tid() = std::this_thread::get_id();
threadEntry->tid_os = folly::getOSThreadID();
// if we're adding a thread entry
// we need to increment the list count
......
......@@ -772,12 +772,12 @@ RequestContext::StaticContext& RequestContext::getStaticContext() {
return SingletonT::get();
}
/* static */ std::vector<std::pair<std::thread::id, intptr_t>>
/* static */ std::vector<RequestContext::RootIdInfo>
RequestContext::getRootIdsFromAllThreads() {
std::vector<std::pair<std::thread::id, intptr_t>> result;
std::vector<RootIdInfo> result;
auto accessor = SingletonT::accessAllThreads();
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;
}
......
......@@ -170,8 +170,12 @@ class RequestContext {
return rootId_;
}
static std::vector<std::pair<std::thread::id, intptr_t>>
getRootIdsFromAllThreads();
struct RootIdInfo {
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
// in the RequestContext instance, normally used for per-RequestContext
......
......@@ -77,7 +77,7 @@ class RequestContextTest : public ::testing::Test {
std::vector<intptr_t> result;
std::transform(
rootids.begin(), rootids.end(), std::back_inserter(result), [](auto e) {
return e.second;
return e.id;
});
return result;
}
......@@ -373,7 +373,8 @@ TEST_F(RequestContextTest, ThreadId) {
RequestContextScopeGuard g;
auto ctxBase = std::make_shared<RequestContext>();
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;
base.runInEventBaseThread([&]() {
......@@ -387,11 +388,11 @@ TEST_F(RequestContextTest, ThreadId) {
th.join();
std::sort(rootids.begin(), rootids.end(), [](const auto& a, const auto& b) {
auto aname = folly::getThreadName(a.first);
auto bname = folly::getThreadName(b.first);
auto aname = folly::getThreadName(a.tid);
auto bname = folly::getThreadName(b.tid);
return (aname ? *aname : "zzz") < (bname ? *bname : "zzz");
});
EXPECT_EQ(*folly::getThreadName(rootids[0].first), "DummyThread");
EXPECT_FALSE(folly::getThreadName(rootids[1].first));
EXPECT_EQ(*folly::getThreadName(rootids[0].tid), "DummyThread");
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