Index: include/lldb/Utility/TaskPool.h =================================================================== --- /dev/null +++ include/lldb/Utility/TaskPool.h @@ -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 // for bind, function -#include -#include -#include // for make_shared -#include // for mutex, unique_lock, condition_variable -#include // 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 - static std::future::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 static void RunTasks(T &&... tasks); - -private: - TaskPool() = delete; - - template struct RunTaskImpl; - - static void AddTaskImpl(std::function &&task_fn); -}; - -template -std::future::type> -TaskPool::AddTask(F &&f, Args &&... args) { - auto task_sp = std::make_shared< - std::packaged_task::type()>>( - std::bind(std::forward(f), std::forward(args)...)); - - AddTaskImpl([task_sp]() { (*task_sp)(); }); - - return task_sp->get_future(); -} - -template void TaskPool::RunTasks(T &&... tasks) { - RunTaskImpl::Run(std::forward(tasks)...); -} - -template -struct TaskPool::RunTaskImpl { - static void Run(Head &&h, Tail &&... t) { - auto f = AddTask(std::forward(h)); - RunTaskImpl::Run(std::forward(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 &func); - -#endif // #ifndef utility_TaskPool_h_ Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -2664,8 +2664,8 @@ 6D99A3621BBC2F3200979793 /* ArmUnwindInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ArmUnwindInfo.cpp; path = source/Symbol/ArmUnwindInfo.cpp; sourceTree = ""; }; 6D9AB3DC1BB2B74E003F2289 /* TypeMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeMap.cpp; path = source/Symbol/TypeMap.cpp; sourceTree = ""; }; 6D9AB3DE1BB2B76B003F2289 /* TypeMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeMap.h; path = include/lldb/Symbol/TypeMap.h; sourceTree = ""; }; - 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TaskPool.cpp; path = source/Utility/TaskPool.cpp; sourceTree = ""; }; - 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaskPool.h; path = include/lldb/Utility/TaskPool.h; sourceTree = ""; }; + 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TaskPool.cpp; path = source/Host/common/TaskPool.cpp; sourceTree = ""; }; + 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaskPool.h; path = include/lldb/Host/TaskPool.h; sourceTree = ""; }; 8C26C4241C3EA4340031DF7C /* TSanRuntime.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TSanRuntime.cpp; path = TSan/TSanRuntime.cpp; sourceTree = ""; }; 8C26C4251C3EA4340031DF7C /* TSanRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TSanRuntime.h; path = TSan/TSanRuntime.h; sourceTree = ""; }; 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryHistory.cpp; path = source/Target/MemoryHistory.cpp; sourceTree = ""; }; @@ -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 */, Index: source/Host/CMakeLists.txt =================================================================== --- source/Host/CMakeLists.txt +++ source/Host/CMakeLists.txt @@ -31,6 +31,7 @@ common/SoftwareBreakpoint.cpp common/StringConvert.cpp common/Symbols.cpp + common/TaskPool.cpp common/TCPSocket.cpp common/Terminal.cpp common/ThreadLauncher.cpp Index: source/Host/common/TaskPool.cpp =================================================================== --- source/Host/common/TaskPool.cpp +++ source/Host/common/TaskPool.cpp @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Utility/TaskPool.h" +#include "lldb/Host/TaskPool.h" +#include "lldb/Host/ThreadLauncher.h" #include // for uint32_t #include // for queue @@ -23,6 +24,8 @@ private: TaskPoolImpl(); + static lldb::thread_result_t WorkerPtr(void *pool); + static void Worker(TaskPoolImpl *pool); std::queue> m_tasks; @@ -45,6 +48,7 @@ void TaskPoolImpl::AddTask(std::function &&task_fn) { static const uint32_t max_threads = std::thread::hardware_concurrency(); + const size_t min_stack_size = 8 * 1024 * 1024; std::unique_lock lock(m_tasks_mutex); m_tasks.emplace(std::move(task_fn)); @@ -54,10 +58,17 @@ // 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 lock(pool->m_tasks_mutex); Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -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" Index: source/Utility/CMakeLists.txt =================================================================== --- source/Utility/CMakeLists.txt +++ source/Utility/CMakeLists.txt @@ -29,7 +29,6 @@ StringLexer.cpp StringList.cpp StructuredData.cpp - TaskPool.cpp TildeExpressionResolver.cpp Timer.cpp UserID.cpp Index: unittests/Host/CMakeLists.txt =================================================================== --- unittests/Host/CMakeLists.txt +++ unittests/Host/CMakeLists.txt @@ -6,6 +6,7 @@ SocketAddressTest.cpp SocketTest.cpp SymbolsTest.cpp + TaskPoolTest.cpp ) if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") Index: unittests/Host/TaskPoolTest.cpp =================================================================== --- unittests/Host/TaskPoolTest.cpp +++ unittests/Host/TaskPoolTest.cpp @@ -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; }; Index: unittests/Utility/CMakeLists.txt =================================================================== --- unittests/Utility/CMakeLists.txt +++ unittests/Utility/CMakeLists.txt @@ -8,7 +8,6 @@ StatusTest.cpp StringExtractorTest.cpp StructuredDataTest.cpp - TaskPoolTest.cpp TildeExpressionResolverTest.cpp TimeoutTest.cpp TimerTest.cpp