Commit 21f9cf7d authored by Amlan Nayak's avatar Amlan Nayak Committed by Facebook GitHub Bot

Record OS thread IDs for threads used in CPUThreadPoolExecutor

Summary:
In order to collect backtraces of all threads consuming from the executor's
queue(s), we need to record their actual thread IDs. We can keep track of the IDs
in a list owned by the executor. Each thread in the pool will add its own
thread ID to the tracking list by calling `folly::getOSThreadID()` and is also
responsible for removing it from the list as it exits.

Reviewed By: yfeldblum, mshneer

Differential Revision: D30103988

fbshipit-source-id: c59a1c31811684974fdb238433bd4796d0bbf2c8
parent 7f69cb31
...@@ -272,6 +272,10 @@ void CPUThreadPoolExecutor::threadRun(ThreadPtr thread) { ...@@ -272,6 +272,10 @@ void CPUThreadPoolExecutor::threadRun(ThreadPtr thread) {
} }
thread->startupBaton.post(); thread->startupBaton.post();
osThreadIds_.wlock()->insert(folly::getOSThreadID());
// On thread exit, we should remove the thread ID from the tracking list.
auto threadIDsGuard = folly::makeGuard(
[this]() { osThreadIds_.wlock()->erase(folly::getOSThreadID()); });
while (true) { while (true) {
auto task = taskQueue_->try_take_for(threadTimeout_); auto task = taskQueue_->try_take_for(threadTimeout_);
......
...@@ -289,6 +289,7 @@ class ThreadPoolExecutor : public DefaultKeepAliveExecutor { ...@@ -289,6 +289,7 @@ class ThreadPoolExecutor : public DefaultKeepAliveExecutor {
std::string namePrefix_; std::string namePrefix_;
const bool isWaitForAll_; // whether to wait till event base loop exits const bool isWaitForAll_; // whether to wait till event base loop exits
folly::Synchronized<std::unordered_set<pid_t>> osThreadIds_;
ThreadList threadList_; ThreadList threadList_;
SharedMutex threadListLock_; SharedMutex threadListLock_;
StoppedThreadQueue stoppedThreads_; StoppedThreadQueue stoppedThreads_;
......
...@@ -924,6 +924,29 @@ TEST(ThreadPoolExecutorTest, AddPerf) { ...@@ -924,6 +924,29 @@ TEST(ThreadPoolExecutorTest, AddPerf) {
e.stop(); e.stop();
} }
class OSThreadIDTestExecutor : public CPUThreadPoolExecutor {
public:
explicit OSThreadIDTestExecutor(size_t n) : CPUThreadPoolExecutor(n) {}
const std::unordered_set<pid_t>& getThreadIds() const {
return *osThreadIds_.rlock();
}
};
TEST(ThreadPoolExecutorTest, OSThreadIDsCollectionTest) {
OSThreadIDTestExecutor e(1);
const auto& idsList = e.getThreadIds();
std::atomic<uint64_t> flag{0};
Baton<> b;
e.add([&]() {
flag.exchange(getOSThreadID());
b.post();
});
b.wait();
EXPECT_EQ(idsList.count(flag.load()), 1);
e.join();
EXPECT_EQ(idsList.size(), 0);
}
template <typename TPE> template <typename TPE>
static void WeakRefTest() { static void WeakRefTest() {
// test that adding a .then() after we have // test that adding a .then() after we have
......
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