[Lldb-commits] [lldb] r313637 - Use ThreadLauncher to launch TaskPool threads

Francis Ricci via lldb-commits lldb-commits at lists.llvm.org
Tue Sep 19 08:38:30 PDT 2017


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);
-}




More information about the lldb-commits mailing list