Commit b32c4feb authored by Peter DeLong's avatar Peter DeLong Committed by Facebook Github Bot

Add hooks to track which threads belong to which thread pools

Summary:
Keep track of which threads belong to which thread pools for use when debugging.
This will be paired with a gdb script that associates threads with their thread pools

Reviewed By: andriigrynenko

Differential Revision: D5514729

fbshipit-source-id: 57ada4dd1aaaec5d7026e4eee05b0ec4e7434c77
parent 23de25b8
main v2022.02.14.00 v2022.02.07.00 v2022.01.31.00 v2022.01.24.00 v2022.01.17.00 v2022.01.10.00 v2022.01.03.00 v2021.12.27.00 v2021.12.20.00 v2021.12.13.00 v2021.12.06.00 v2021.11.29.00 v2021.11.15.00 v2021.11.08.00 v2021.11.01.00 v2021.10.25.00 v2021.10.18.00 v2021.10.11.00 v2021.10.04.00 v2021.09.27.00 v2021.09.20.00 v2021.09.13.00 v2021.09.06.00 v2021.08.30.00 v2021.08.23.00 v2021.08.02.00 v2021.07.22.00 v2021.07.20.01 v2021.07.20.00 v2021.06.28.00 v2021.06.14.00 v2021.06.07.00 v2021.05.31.00 v2021.05.24.00 v2021.05.17.00 v2021.05.10.00 v2021.05.03.00 v2021.04.26.00 v2021.04.19.00 v2021.04.12.00 v2021.04.05.00 v2021.03.29.00 v2021.03.22.00 v2021.03.15.00 v2021.03.08.00 v2021.03.01.00 v2021.02.22.00 v2021.02.15.00 v2021.02.08.00 v2021.02.01.00 v2021.01.25.00 v2021.01.18.01 v2021.01.18.00 v2021.01.11.00 v2021.01.04.00 v2020.12.28.00 v2020.12.21.00 v2020.12.14.00 v2020.12.07.00 v2020.11.30.00 v2020.11.23.00 v2020.11.16.00 v2020.11.09.00 v2020.11.02.00 v2020.10.26.00 v2020.10.19.00 v2020.10.12.00 v2020.10.05.00 v2020.09.28.00 v2020.09.21.00 v2020.09.14.00 v2020.09.07.00 v2020.08.31.00 v2020.08.24.00 v2020.08.17.00 v2020.08.10.00 v2020.08.03.00 v2020.07.27.00 v2020.07.20.00 v2020.07.13.00 v2020.07.06.00 v2020.06.29.00 v2020.06.15.00 v2020.06.08.00 v2020.06.01.00 v2020.05.25.00 v2020.05.18.00 v2020.05.11.00 v2020.05.04.00 v2020.04.27.00 v2020.04.20.00 v2020.04.13.00 v2020.04.06.00 v2020.03.30.00 v2020.03.23.00 v2020.03.16.00 v2020.03.09.00 v2020.03.02.00 v2020.02.24.00 v2020.02.17.00 v2020.02.10.00 v2020.02.03.00 v2020.01.27.00 v2020.01.20.00 v2020.01.13.00 v2020.01.06.00 v2019.12.30.00 v2019.12.23.00 v2019.12.16.00 v2019.12.09.00 v2019.12.06.00 v2019.12.02.00 v2019.11.11.00 v2019.11.04.00 v2019.10.28.00 v2019.10.21.00 v2019.10.14.00 v2019.10.07.00 v2019.09.30.00 v2019.09.23.00 v2019.09.16.00 v2019.09.09.00 v2019.09.02.00 v2019.08.26.00 v2019.08.19.00 v2019.08.12.00 v2019.08.05.00 v2019.07.29.00 v2019.07.22.00 v2019.06.17.00 v2019.06.10.00 v2019.06.03.00 v2019.05.27.00 v2019.05.20.00 v2019.05.13.00 v2019.05.06.00 v2019.04.29.00 v2019.04.22.00 v2019.04.15.00 v2019.04.08.00 v2019.04.01.00 v2019.03.25.00 v2019.03.18.00 v2019.03.04.00 v2019.02.25.00 v2019.02.18.00 v2019.02.11.00 v2019.02.04.00 v2019.01.28.00 v2019.01.21.00 v2019.01.14.00 v2019.01.07.00 v2018.12.31.00 v2018.12.24.00 v2018.12.17.00 v2018.12.10.00 v2018.12.03.00 v2018.11.26.00 v2018.11.19.00 v2018.11.12.00 v2018.11.05.00 v2018.10.29.00 v2018.10.22.00 v2018.10.15.00 v2018.10.08.00 v2018.10.01.00 v2018.09.24.00 v2018.09.17.00 v2018.09.10.01 v2018.09.10.00 v2018.09.03.01 v2018.09.03.00 v2018.08.27.00 v2018.08.20.00 v2018.08.13.00 v2018.08.09.00 v2018.08.06.00 v2018.07.30.00 v2018.07.23.00 v2018.07.16.00 v2018.07.09.00 v2018.07.02.00 v2018.06.25.00 v2018.06.18.00 v2018.06.11.00 v2018.06.04.00 v2018.05.28.00 v2018.05.21.00 v2018.05.14.00 v2018.05.07.00 v2018.04.30.00 v2018.04.23.00 v2018.04.16.00 v2018.04.09.00 v2018.04.02.00 v2018.03.26.00 v2018.03.19.00 v2018.03.12.00 v2018.03.05.00 v2018.02.26.00 v2018.02.19.00 v2018.02.12.00 v2018.02.05.00 v2018.01.29.00 v2018.01.22.00 v2018.01.15.00 v2018.01.08.00 v2018.01.01.00 v2017.12.25.00 v2017.12.18.00 v2017.12.11.00 v2017.12.04.00 v2017.11.27.00 v2017.11.20.00 v2017.11.13.00 v2017.11.06.00 v2017.10.30.00 v2017.10.23.00 v2017.10.16.00 v2017.10.09.00 v2017.10.02.00 v2017.09.25.00 v2017.09.18.00 v2017.09.11.00 v2017.09.04.00 v2017.08.28.00 v2017.08.21.00
No related merge requests found
/*
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/GlobalThreadPoolList.h>
#include <memory>
#include <string>
#include <vector>
#include <folly/CppAttributes.h>
#include <folly/Indestructible.h>
#include <folly/Synchronized.h>
#include <folly/ThreadLocal.h>
namespace folly {
namespace {
class ThreadListHook {
public:
ThreadListHook(ThreadPoolListHook* poolId, std::thread::id threadId);
~ThreadListHook();
private:
ThreadListHook() {}
ThreadPoolListHook* poolId_;
std::thread::id threadId_;
};
class GlobalThreadPoolListImpl {
public:
GlobalThreadPoolListImpl() {}
void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name);
void unregisterThreadPool(ThreadPoolListHook* threadPoolId);
void registerThreadPoolThread(
ThreadPoolListHook* threadPoolId,
std::thread::id threadId);
void unregisterThreadPoolThread(
ThreadPoolListHook* threadPoolId,
std::thread::id threadId);
private:
struct PoolInfo {
ThreadPoolListHook* addr;
std::string name;
std::vector<std::thread::id> threads;
};
struct Pools {
// Just a vector since ease of access from gdb is the most important
// property
std::vector<PoolInfo> poolsInfo_;
std::vector<std::thread::id>* FOLLY_NULLABLE
getThreadVector(void* threadPoolId) {
for (auto& elem : vector()) {
if (elem.addr == threadPoolId) {
return &elem.threads;
}
}
return nullptr;
}
std::vector<PoolInfo>& vector() {
return poolsInfo_;
}
};
Pools pools_;
};
class GlobalThreadPoolList {
public:
GlobalThreadPoolList() {}
static GlobalThreadPoolList& instance();
void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name);
void unregisterThreadPool(ThreadPoolListHook* threadPoolId);
void registerThreadPoolThread(
ThreadPoolListHook* threadPoolId,
std::thread::id threadId);
void unregisterThreadPoolThread(
ThreadPoolListHook* threadPoolId,
std::thread::id threadId);
GlobalThreadPoolList(GlobalThreadPoolList const&) = delete;
void operator=(GlobalThreadPoolList const&) = delete;
private:
folly::Synchronized<GlobalThreadPoolListImpl> globalListImpl_;
folly::ThreadLocalPtr<ThreadListHook> threadHook_;
};
} // namespace
GlobalThreadPoolList& GlobalThreadPoolList::instance() {
static folly::Indestructible<GlobalThreadPoolList> ret;
return *ret;
}
void GlobalThreadPoolList::registerThreadPool(
ThreadPoolListHook* threadPoolId,
std::string name) {
globalListImpl_->registerThreadPool(threadPoolId, name);
}
void GlobalThreadPoolList::unregisterThreadPool(
ThreadPoolListHook* threadPoolId) {
globalListImpl_->unregisterThreadPool(threadPoolId);
}
void GlobalThreadPoolList::registerThreadPoolThread(
ThreadPoolListHook* threadPoolId,
std::thread::id threadId) {
DCHECK(!threadHook_);
threadHook_.reset(make_unique<ThreadListHook>(threadPoolId, threadId));
globalListImpl_->registerThreadPoolThread(threadPoolId, threadId);
}
void GlobalThreadPoolList::unregisterThreadPoolThread(
ThreadPoolListHook* threadPoolId,
std::thread::id threadId) {
(void)threadPoolId;
(void)threadId;
globalListImpl_->unregisterThreadPoolThread(threadPoolId, threadId);
}
void GlobalThreadPoolListImpl::registerThreadPool(
ThreadPoolListHook* threadPoolId,
std::string name) {
PoolInfo info;
info.name = name;
info.addr = threadPoolId;
pools_.vector().push_back(info);
}
void GlobalThreadPoolListImpl::unregisterThreadPool(
ThreadPoolListHook* threadPoolId) {
auto& vector = pools_.vector();
vector.erase(
std::remove_if(
vector.begin(),
vector.end(),
[=](PoolInfo& i) { return i.addr == threadPoolId; }),
vector.end());
}
void GlobalThreadPoolListImpl::registerThreadPoolThread(
ThreadPoolListHook* threadPoolId,
std::thread::id threadId) {
auto vec = pools_.getThreadVector(threadPoolId);
if (vec == nullptr) {
return;
}
vec->push_back(threadId);
}
void GlobalThreadPoolListImpl::unregisterThreadPoolThread(
ThreadPoolListHook* threadPoolId,
std::thread::id threadId) {
auto vec = pools_.getThreadVector(threadPoolId);
if (vec == nullptr) {
return;
}
vec->erase(std::remove(vec->begin(), vec->end(), threadId), vec->end());
}
ThreadListHook::ThreadListHook(
ThreadPoolListHook* poolId,
std::thread::id threadId) {
poolId_ = poolId;
threadId_ = threadId;
}
ThreadListHook::~ThreadListHook() {
GlobalThreadPoolList::instance().unregisterThreadPoolThread(
poolId_, threadId_);
}
ThreadPoolListHook::ThreadPoolListHook(std::string name) {
GlobalThreadPoolList::instance().registerThreadPool(this, name);
}
ThreadPoolListHook::~ThreadPoolListHook() {
GlobalThreadPoolList::instance().unregisterThreadPool(this);
}
void ThreadPoolListHook::registerThread() {
GlobalThreadPoolList::instance().registerThreadPoolThread(
this, std::this_thread::get_id());
}
} // folly
/*
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <folly/Indestructible.h>
#include <folly/Synchronized.h>
#include <folly/ThreadLocal.h>
namespace folly {
/**
* A hook for tracking which threads belong to which thread pools.
* This is used only by a gdb extension to aid in debugging. You won't be able
* to see any useful information from within C++ code.
*
* An instance of ThreadPoolListHook should be created in the thread pool class
* that you want to keep track of. Then, to register a thread you call
* registerThread() on your instance of ThreadPoolListHook from that thread.
*
* When a thread exits it will be removed from the list
* When the thread pool is destroyed, it will be removed from the list
*/
class ThreadPoolListHook {
public:
/**
* Name is used to identify the thread pool when listing threads.
*/
explicit ThreadPoolListHook(std::string name);
~ThreadPoolListHook();
/**
* Call this from any new thread that the thread pool creates.
*/
void registerThread();
ThreadPoolListHook(const ThreadPoolListHook& other) = delete;
ThreadPoolListHook& operator=(const ThreadPoolListHook&) = delete;
private:
ThreadPoolListHook();
};
} // folly
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