Author: fjricci Date: Tue Sep 19 08:38:30 2017 New Revision: 313637 URL: http://llvm.org/viewvc/llvm-project?rev=313637&view=rev Log: Use ThreadLauncher to launch TaskPool threads
Summary: This allows for the stack size to be configured, which isn't possible with std::thread. Prevents overflowing the stack when performing complex operations in the task pool on darwin, where the default pthread stack size is only 512kb. This also moves TaskPool from Utility to Host. Reviewers: labath, tberghammer, clayborg Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D37930 Added: lldb/trunk/include/lldb/Host/TaskPool.h - copied, changed from r313540, lldb/trunk/include/lldb/Utility/TaskPool.h lldb/trunk/source/Host/common/TaskPool.cpp - copied, changed from r313540, lldb/trunk/source/Utility/TaskPool.cpp lldb/trunk/unittests/Host/TaskPoolTest.cpp - copied, changed from r313540, lldb/trunk/unittests/Utility/TaskPoolTest.cpp Removed: lldb/trunk/include/lldb/Utility/TaskPool.h lldb/trunk/source/Utility/TaskPool.cpp lldb/trunk/unittests/Utility/TaskPoolTest.cpp Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Host/CMakeLists.txt lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Utility/CMakeLists.txt lldb/trunk/unittests/Host/CMakeLists.txt lldb/trunk/unittests/Utility/CMakeLists.txt Copied: lldb/trunk/include/lldb/Host/TaskPool.h (from r313540, lldb/trunk/include/lldb/Utility/TaskPool.h) URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/TaskPool.h?p2=lldb/trunk/include/lldb/Host/TaskPool.h&p1=lldb/trunk/include/lldb/Utility/TaskPool.h&r1=313540&r2=313637&rev=313637&view=diff ============================================================================== (empty) Removed: lldb/trunk/include/lldb/Utility/TaskPool.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/TaskPool.h?rev=313636&view=auto ============================================================================== --- lldb/trunk/include/lldb/Utility/TaskPool.h (original) +++ lldb/trunk/include/lldb/Utility/TaskPool.h (removed) @@ -1,92 +0,0 @@ -//===--------------------- TaskPool.h ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef utility_TaskPool_h_ -#define utility_TaskPool_h_ - -#include "llvm/ADT/STLExtras.h" -#include <functional> // for bind, function -#include <future> -#include <list> -#include <memory> // for make_shared -#include <mutex> // for mutex, unique_lock, condition_variable -#include <type_traits> // for forward, result_of, move - -// Global TaskPool class for running tasks in parallel on a set of worker thread -// created the first -// time the task pool is used. The TaskPool provide no guarantee about the order -// the task will be run -// and about what tasks will run in parallel. None of the task added to the task -// pool should block -// on something (mutex, future, condition variable) what will be set only by the -// completion of an -// other task on the task pool as they may run on the same thread sequentally. -class TaskPool { -public: - // Add a new task to the task pool and return a std::future belonging to the - // newly created task. - // The caller of this function has to wait on the future for this task to - // complete. - template <typename F, typename... Args> - static std::future<typename std::result_of<F(Args...)>::type> - AddTask(F &&f, Args &&... args); - - // Run all of the specified tasks on the task pool and wait until all of them - // are finished - // before returning. This method is intended to be used for small number tasks - // where listing - // them as function arguments is acceptable. For running large number of tasks - // you should use - // AddTask for each task and then call wait() on each returned future. - template <typename... T> static void RunTasks(T &&... tasks); - -private: - TaskPool() = delete; - - template <typename... T> struct RunTaskImpl; - - static void AddTaskImpl(std::function<void()> &&task_fn); -}; - -template <typename F, typename... Args> -std::future<typename std::result_of<F(Args...)>::type> -TaskPool::AddTask(F &&f, Args &&... args) { - auto task_sp = std::make_shared< - std::packaged_task<typename std::result_of<F(Args...)>::type()>>( - std::bind(std::forward<F>(f), std::forward<Args>(args)...)); - - AddTaskImpl([task_sp]() { (*task_sp)(); }); - - return task_sp->get_future(); -} - -template <typename... T> void TaskPool::RunTasks(T &&... tasks) { - RunTaskImpl<T...>::Run(std::forward<T>(tasks)...); -} - -template <typename Head, typename... Tail> -struct TaskPool::RunTaskImpl<Head, Tail...> { - static void Run(Head &&h, Tail &&... t) { - auto f = AddTask(std::forward<Head>(h)); - RunTaskImpl<Tail...>::Run(std::forward<Tail>(t)...); - f.wait(); - } -}; - -template <> struct TaskPool::RunTaskImpl<> { - static void Run() {} -}; - -// Run 'func' on every value from begin .. end-1. Each worker will grab -// 'batch_size' numbers at a time to work on, so for very fast functions, batch -// should be large enough to avoid too much cache line contention. -void TaskMapOverInt(size_t begin, size_t end, - const llvm::function_ref<void(size_t)> &func); - -#endif // #ifndef utility_TaskPool_h_ Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=313637&r1=313636&r2=313637&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Sep 19 08:38:30 2017 @@ -2664,8 +2664,8 @@ 6D99A3621BBC2F3200979793 /* ArmUnwindInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ArmUnwindInfo.cpp; path = source/Symbol/ArmUnwindInfo.cpp; sourceTree = "<group>"; }; 6D9AB3DC1BB2B74E003F2289 /* TypeMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeMap.cpp; path = source/Symbol/TypeMap.cpp; sourceTree = "<group>"; }; 6D9AB3DE1BB2B76B003F2289 /* TypeMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeMap.h; path = include/lldb/Symbol/TypeMap.h; sourceTree = "<group>"; }; - 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TaskPool.cpp; path = source/Utility/TaskPool.cpp; sourceTree = "<group>"; }; - 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaskPool.h; path = include/lldb/Utility/TaskPool.h; sourceTree = "<group>"; }; + 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TaskPool.cpp; path = source/Host/common/TaskPool.cpp; sourceTree = "<group>"; }; + 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaskPool.h; path = include/lldb/Host/TaskPool.h; sourceTree = "<group>"; }; 8C26C4241C3EA4340031DF7C /* TSanRuntime.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TSanRuntime.cpp; path = TSan/TSanRuntime.cpp; sourceTree = "<group>"; }; 8C26C4251C3EA4340031DF7C /* TSanRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TSanRuntime.h; path = TSan/TSanRuntime.h; sourceTree = "<group>"; }; 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryHistory.cpp; path = source/Target/MemoryHistory.cpp; sourceTree = "<group>"; }; @@ -4413,8 +4413,6 @@ AFEC3361194A8ABA00FF05C6 /* StructuredData.cpp */, 94BA8B6E176F8CA0005A91B5 /* Range.h */, 94BA8B6C176F8C9B005A91B5 /* Range.cpp */, - 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */, - 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */, AFF8FF0B1E779D4B003830EF /* TildeExpressionResolver.cpp */, AFF8FF0D1E779D51003830EF /* TildeExpressionResolver.h */, 26BC7D7E10F1B77400F91463 /* Timer.h */, @@ -5248,6 +5246,8 @@ 267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */, 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */, 2689B0A4113EE3CD00A4AEDB /* Symbols.h */, + 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */, + 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */, 268DA871130095D000C9483A /* Terminal.h */, 3FDFED2319BA6D55009756A7 /* ThreadLauncher.h */, 267A48031B1416080021A5BC /* XML.h */, Modified: lldb/trunk/source/Host/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/CMakeLists.txt?rev=313637&r1=313636&r2=313637&view=diff ============================================================================== --- lldb/trunk/source/Host/CMakeLists.txt (original) +++ lldb/trunk/source/Host/CMakeLists.txt Tue Sep 19 08:38:30 2017 @@ -31,6 +31,7 @@ add_host_subdirectory(common common/SoftwareBreakpoint.cpp common/StringConvert.cpp common/Symbols.cpp + common/TaskPool.cpp common/TCPSocket.cpp common/Terminal.cpp common/ThreadLauncher.cpp Copied: lldb/trunk/source/Host/common/TaskPool.cpp (from r313540, lldb/trunk/source/Utility/TaskPool.cpp) URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/TaskPool.cpp?p2=lldb/trunk/source/Host/common/TaskPool.cpp&p1=lldb/trunk/source/Utility/TaskPool.cpp&r1=313540&r2=313637&rev=313637&view=diff ============================================================================== --- lldb/trunk/source/Utility/TaskPool.cpp (original) +++ lldb/trunk/source/Host/common/TaskPool.cpp Tue Sep 19 08:38:30 2017 @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Utility/TaskPool.h" +#include "lldb/Host/TaskPool.h" +#include "lldb/Host/ThreadLauncher.h" #include <cstdint> // for uint32_t #include <queue> // for queue @@ -23,6 +24,8 @@ public: private: TaskPoolImpl(); + static lldb::thread_result_t WorkerPtr(void *pool); + static void Worker(TaskPoolImpl *pool); std::queue<std::function<void()>> m_tasks; @@ -45,6 +48,7 @@ TaskPoolImpl::TaskPoolImpl() : m_thread_ void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) { static const uint32_t max_threads = std::thread::hardware_concurrency(); + const size_t min_stack_size = 8 * 1024 * 1024; std::unique_lock<std::mutex> lock(m_tasks_mutex); m_tasks.emplace(std::move(task_fn)); @@ -54,10 +58,17 @@ void TaskPoolImpl::AddTask(std::function // This prevents the thread // from exiting prematurely and triggering a linux libc bug // (https://sourceware.org/bugzilla/show_bug.cgi?id=19951). - std::thread(Worker, this).detach(); + lldb_private::ThreadLauncher::LaunchThread("task-pool.worker", WorkerPtr, + this, nullptr, min_stack_size) + .Release(); } } +lldb::thread_result_t TaskPoolImpl::WorkerPtr(void *pool) { + Worker((TaskPoolImpl *)pool); + return 0; +} + void TaskPoolImpl::Worker(TaskPoolImpl *pool) { while (true) { std::unique_lock<std::mutex> lock(pool->m_tasks_mutex); Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=313637&r1=313636&r2=313637&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Sep 19 08:38:30 2017 @@ -53,7 +53,7 @@ #include "lldb/Target/Language.h" -#include "lldb/Utility/TaskPool.h" +#include "lldb/Host/TaskPool.h" #include "DWARFASTParser.h" #include "DWARFASTParserClang.h" Modified: lldb/trunk/source/Utility/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/CMakeLists.txt?rev=313637&r1=313636&r2=313637&view=diff ============================================================================== --- lldb/trunk/source/Utility/CMakeLists.txt (original) +++ lldb/trunk/source/Utility/CMakeLists.txt Tue Sep 19 08:38:30 2017 @@ -29,7 +29,6 @@ add_lldb_library(lldbUtility StringLexer.cpp StringList.cpp StructuredData.cpp - TaskPool.cpp TildeExpressionResolver.cpp Timer.cpp UserID.cpp Removed: lldb/trunk/source/Utility/TaskPool.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/TaskPool.cpp?rev=313636&view=auto ============================================================================== --- lldb/trunk/source/Utility/TaskPool.cpp (original) +++ lldb/trunk/source/Utility/TaskPool.cpp (removed) @@ -1,98 +0,0 @@ -//===--------------------- TaskPool.cpp -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/TaskPool.h" - -#include <cstdint> // for uint32_t -#include <queue> // for queue -#include <thread> // for thread - -namespace { -class TaskPoolImpl { -public: - static TaskPoolImpl &GetInstance(); - - void AddTask(std::function<void()> &&task_fn); - -private: - TaskPoolImpl(); - - static void Worker(TaskPoolImpl *pool); - - std::queue<std::function<void()>> m_tasks; - std::mutex m_tasks_mutex; - uint32_t m_thread_count; -}; - -} // end of anonymous namespace - -TaskPoolImpl &TaskPoolImpl::GetInstance() { - static TaskPoolImpl g_task_pool_impl; - return g_task_pool_impl; -} - -void TaskPool::AddTaskImpl(std::function<void()> &&task_fn) { - TaskPoolImpl::GetInstance().AddTask(std::move(task_fn)); -} - -TaskPoolImpl::TaskPoolImpl() : m_thread_count(0) {} - -void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) { - static const uint32_t max_threads = std::thread::hardware_concurrency(); - - std::unique_lock<std::mutex> lock(m_tasks_mutex); - m_tasks.emplace(std::move(task_fn)); - if (m_thread_count < max_threads) { - m_thread_count++; - // Note that this detach call needs to happen with the m_tasks_mutex held. - // This prevents the thread - // from exiting prematurely and triggering a linux libc bug - // (https://sourceware.org/bugzilla/show_bug.cgi?id=19951). - std::thread(Worker, this).detach(); - } -} - -void TaskPoolImpl::Worker(TaskPoolImpl *pool) { - while (true) { - std::unique_lock<std::mutex> lock(pool->m_tasks_mutex); - if (pool->m_tasks.empty()) { - pool->m_thread_count--; - break; - } - - std::function<void()> f = pool->m_tasks.front(); - pool->m_tasks.pop(); - lock.unlock(); - - f(); - } -} - -void TaskMapOverInt(size_t begin, size_t end, - const llvm::function_ref<void(size_t)> &func) { - std::atomic<size_t> idx{begin}; - size_t num_workers = - std::min<size_t>(end, std::thread::hardware_concurrency()); - - auto wrapper = [&idx, end, &func]() { - while (true) { - size_t i = idx.fetch_add(1); - if (i >= end) - break; - func(i); - } - }; - - std::vector<std::future<void>> futures; - futures.reserve(num_workers); - for (size_t i = 0; i < num_workers; i++) - futures.push_back(TaskPool::AddTask(wrapper)); - for (size_t i = 0; i < num_workers; i++) - futures[i].wait(); -} Modified: lldb/trunk/unittests/Host/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Host/CMakeLists.txt?rev=313637&r1=313636&r2=313637&view=diff ============================================================================== --- lldb/trunk/unittests/Host/CMakeLists.txt (original) +++ lldb/trunk/unittests/Host/CMakeLists.txt Tue Sep 19 08:38:30 2017 @@ -6,6 +6,7 @@ set (FILES SocketAddressTest.cpp SocketTest.cpp SymbolsTest.cpp + TaskPoolTest.cpp ) if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") Copied: lldb/trunk/unittests/Host/TaskPoolTest.cpp (from r313540, lldb/trunk/unittests/Utility/TaskPoolTest.cpp) URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Host/TaskPoolTest.cpp?p2=lldb/trunk/unittests/Host/TaskPoolTest.cpp&p1=lldb/trunk/unittests/Utility/TaskPoolTest.cpp&r1=313540&r2=313637&rev=313637&view=diff ============================================================================== --- lldb/trunk/unittests/Utility/TaskPoolTest.cpp (original) +++ lldb/trunk/unittests/Host/TaskPoolTest.cpp Tue Sep 19 08:38:30 2017 @@ -1,6 +1,6 @@ #include "gtest/gtest.h" -#include "lldb/Utility/TaskPool.h" +#include "lldb/Host/TaskPool.h" TEST(TaskPoolTest, AddTask) { auto fn = [](int x) { return x * x + 1; }; Modified: lldb/trunk/unittests/Utility/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Utility/CMakeLists.txt?rev=313637&r1=313636&r2=313637&view=diff ============================================================================== --- lldb/trunk/unittests/Utility/CMakeLists.txt (original) +++ lldb/trunk/unittests/Utility/CMakeLists.txt Tue Sep 19 08:38:30 2017 @@ -8,7 +8,6 @@ add_lldb_unittest(UtilityTests StatusTest.cpp StringExtractorTest.cpp StructuredDataTest.cpp - TaskPoolTest.cpp TildeExpressionResolverTest.cpp TimeoutTest.cpp TimerTest.cpp Removed: lldb/trunk/unittests/Utility/TaskPoolTest.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Utility/TaskPoolTest.cpp?rev=313636&view=auto ============================================================================== --- lldb/trunk/unittests/Utility/TaskPoolTest.cpp (original) +++ lldb/trunk/unittests/Utility/TaskPoolTest.cpp (removed) @@ -1,43 +0,0 @@ -#include "gtest/gtest.h" - -#include "lldb/Utility/TaskPool.h" - -TEST(TaskPoolTest, AddTask) { - auto fn = [](int x) { return x * x + 1; }; - - auto f1 = TaskPool::AddTask(fn, 1); - auto f2 = TaskPool::AddTask(fn, 2); - auto f3 = TaskPool::AddTask(fn, 3); - auto f4 = TaskPool::AddTask(fn, 4); - - ASSERT_EQ(10, f3.get()); - ASSERT_EQ(2, f1.get()); - ASSERT_EQ(17, f4.get()); - ASSERT_EQ(5, f2.get()); -} - -TEST(TaskPoolTest, RunTasks) { - std::vector<int> r(4); - - auto fn = [](int x, int &y) { y = x * x + 1; }; - - TaskPool::RunTasks([fn, &r]() { fn(1, r[0]); }, [fn, &r]() { fn(2, r[1]); }, - [fn, &r]() { fn(3, r[2]); }, [fn, &r]() { fn(4, r[3]); }); - - ASSERT_EQ(2, r[0]); - ASSERT_EQ(5, r[1]); - ASSERT_EQ(10, r[2]); - ASSERT_EQ(17, r[3]); -} - -TEST(TaskPoolTest, TaskMap) { - int data[4]; - auto fn = [&data](int x) { data[x] = x * x; }; - - TaskMapOverInt(0, 4, fn); - - ASSERT_EQ(data[0], 0); - ASSERT_EQ(data[1], 1); - ASSERT_EQ(data[2], 4); - ASSERT_EQ(data[3], 9); -} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits