diff options
author | Mathieu Chartier <mathieuc@google.com> | 2013-11-13 14:33:28 -0800 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2013-11-13 14:48:41 -0800 |
commit | bcd5e9daecad39f0dab3246808b4835caec29ea6 (patch) | |
tree | 1221f94faef80c649e7236f0e7c3045383720abb | |
parent | dfcca560e7b92e055a02adb39fdfb11798144cdd (diff) | |
download | art-bcd5e9daecad39f0dab3246808b4835caec29ea6.zip art-bcd5e9daecad39f0dab3246808b4835caec29ea6.tar.gz art-bcd5e9daecad39f0dab3246808b4835caec29ea6.tar.bz2 |
Manually manage thread pool stacks.
We now allocate the thread pool worker stack using a MemMap. This
enables us to name the maps so that we get more descriptive output
for debugging leaks.
Appears to fix the mips build 5/5 successful clean-oat and builds.
This is probably since glibc caches up to 40 MB of thread stacks
before releasing them.
Change-Id: I1df2de50cb95838aa0d272a09807021404ba410c
-rw-r--r-- | compiler/driver/compiler_driver.cc | 4 | ||||
-rw-r--r-- | runtime/barrier_test.cc | 4 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 2 | ||||
-rw-r--r-- | runtime/thread_pool.cc | 20 | ||||
-rw-r--r-- | runtime/thread_pool.h | 11 | ||||
-rw-r--r-- | runtime/thread_pool_test.cc | 6 |
6 files changed, 27 insertions, 20 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 4af492b..d74383e 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -505,7 +505,7 @@ void CompilerDriver::CompileAll(jobject class_loader, const std::vector<const DexFile*>& dex_files, base::TimingLogger& timings) { DCHECK(!Runtime::Current()->IsStarted()); - UniquePtr<ThreadPool> thread_pool(new ThreadPool(thread_count_ - 1)); + UniquePtr<ThreadPool> thread_pool(new ThreadPool("Compiler driver thread pool", thread_count_ - 1)); PreCompile(class_loader, dex_files, *thread_pool.get(), timings); Compile(class_loader, dex_files, *thread_pool.get(), timings); if (dump_stats_) { @@ -568,7 +568,7 @@ void CompilerDriver::CompileOne(const mirror::ArtMethod* method, base::TimingLog std::vector<const DexFile*> dex_files; dex_files.push_back(dex_file); - UniquePtr<ThreadPool> thread_pool(new ThreadPool(0U)); + UniquePtr<ThreadPool> thread_pool(new ThreadPool("Compiler driver thread pool", 0U)); PreCompile(jclass_loader, dex_files, *thread_pool.get(), timings); uint32_t method_idx = method->GetDexMethodIndex(); diff --git a/runtime/barrier_test.cc b/runtime/barrier_test.cc index 298ae56..91fc143 100644 --- a/runtime/barrier_test.cc +++ b/runtime/barrier_test.cc @@ -66,7 +66,7 @@ int32_t BarrierTest::num_threads = 4; // Check that barrier wait and barrier increment work. TEST_F(BarrierTest, CheckWait) { Thread* self = Thread::Current(); - ThreadPool thread_pool(num_threads); + ThreadPool thread_pool("Barrier test thread pool", num_threads); Barrier barrier(0); AtomicInteger count1(0); AtomicInteger count2(0); @@ -121,7 +121,7 @@ class CheckPassTask : public Task { // Check that barrier pass through works. TEST_F(BarrierTest, CheckPass) { Thread* self = Thread::Current(); - ThreadPool thread_pool(num_threads); + ThreadPool thread_pool("Barrier test thread pool", num_threads); Barrier barrier(0); AtomicInteger count(0); const int32_t num_tasks = num_threads * 4; diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 69ca620..70df3d3 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -309,7 +309,7 @@ void Heap::DecrementDisableGC(Thread* self) { void Heap::CreateThreadPool() { const size_t num_threads = std::max(parallel_gc_threads_, conc_gc_threads_); if (num_threads != 0) { - thread_pool_.reset(new ThreadPool(num_threads)); + thread_pool_.reset(new ThreadPool("Heap thread pool", num_threads)); } } diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc index bb6c475..aca0561 100644 --- a/runtime/thread_pool.cc +++ b/runtime/thread_pool.cc @@ -28,12 +28,15 @@ static constexpr bool kMeasureWaitTime = false; ThreadPoolWorker::ThreadPoolWorker(ThreadPool* thread_pool, const std::string& name, size_t stack_size) : thread_pool_(thread_pool), - name_(name), - stack_size_(stack_size) { + name_(name) { + std::string error_msg; + stack_.reset(MemMap::MapAnonymous(name.c_str(), nullptr, stack_size, PROT_READ | PROT_WRITE, + &error_msg)); + CHECK(stack_.get() != nullptr) << error_msg; const char* reason = "new thread pool worker thread"; pthread_attr_t attr; CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason); - CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), reason); + CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack_->Begin(), stack_->Size()), reason); CHECK_PTHREAD_CALL(pthread_create, (&pthread_, &attr, &Callback, this), reason); CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason); } @@ -71,8 +74,9 @@ void ThreadPool::AddTask(Thread* self, Task* task) { } } -ThreadPool::ThreadPool(size_t num_threads) - : task_queue_lock_("task queue lock"), +ThreadPool::ThreadPool(const char* name, size_t num_threads) + : name_(name), + task_queue_lock_("task queue lock"), task_queue_condition_("task queue condition", task_queue_lock_), completion_condition_("task completion condition", task_queue_lock_), started_(false), @@ -85,7 +89,7 @@ ThreadPool::ThreadPool(size_t num_threads) max_active_workers_(num_threads) { Thread* self = Thread::Current(); while (GetThreadCount() < num_threads) { - const std::string name = StringPrintf("Thread pool worker %zu", GetThreadCount()); + const std::string name = StringPrintf("%s worker thread %zu", name_.c_str(), GetThreadCount()); threads_.push_back(new ThreadPoolWorker(this, name, ThreadPoolWorker::kDefaultStackSize)); } // Wait for all of the threads to attach. @@ -270,8 +274,8 @@ void WorkStealingWorker::Run() { WorkStealingWorker::~WorkStealingWorker() {} -WorkStealingThreadPool::WorkStealingThreadPool(size_t num_threads) - : ThreadPool(0), +WorkStealingThreadPool::WorkStealingThreadPool(const char* name, size_t num_threads) + : ThreadPool(name, 0), work_steal_lock_("work stealing lock"), steal_index_(0) { while (GetThreadCount() < num_threads) { diff --git a/runtime/thread_pool.h b/runtime/thread_pool.h index b9a97a1..e8f9afe 100644 --- a/runtime/thread_pool.h +++ b/runtime/thread_pool.h @@ -24,6 +24,7 @@ #include "base/mutex.h" #include "closure.h" #include "locks.h" +#include "mem_map.h" namespace art { @@ -40,7 +41,8 @@ class ThreadPoolWorker { static const size_t kDefaultStackSize = 1 * MB; size_t GetStackSize() const { - return stack_size_; + DCHECK(stack_.get() != nullptr); + return stack_->Size(); } virtual ~ThreadPoolWorker(); @@ -52,7 +54,7 @@ class ThreadPoolWorker { ThreadPool* const thread_pool_; const std::string name_; - const size_t stack_size_; + UniquePtr<MemMap> stack_; pthread_t pthread_; private: @@ -77,7 +79,7 @@ class ThreadPool { // after running it, it is the caller's responsibility. void AddTask(Thread* self, Task* task); - explicit ThreadPool(size_t num_threads); + explicit ThreadPool(const char* name, size_t num_threads); virtual ~ThreadPool(); // Wait for all tasks currently on queue to get completed. @@ -107,6 +109,7 @@ class ThreadPool { return shutting_down_; } + const std::string name_; Mutex task_queue_lock_; ConditionVariable task_queue_condition_ GUARDED_BY(task_queue_lock_); ConditionVariable completion_condition_ GUARDED_BY(task_queue_lock_); @@ -167,7 +170,7 @@ class WorkStealingWorker : public ThreadPoolWorker { class WorkStealingThreadPool : public ThreadPool { public: - explicit WorkStealingThreadPool(size_t num_threads); + explicit WorkStealingThreadPool(const char* name, size_t num_threads); virtual ~WorkStealingThreadPool(); private: diff --git a/runtime/thread_pool_test.cc b/runtime/thread_pool_test.cc index 9b789d2..1b22361 100644 --- a/runtime/thread_pool_test.cc +++ b/runtime/thread_pool_test.cc @@ -59,7 +59,7 @@ int32_t ThreadPoolTest::num_threads = 4; // Check that the thread pool actually runs tasks that you assign it. TEST_F(ThreadPoolTest, CheckRun) { Thread* self = Thread::Current(); - ThreadPool thread_pool(num_threads); + ThreadPool thread_pool("Thread pool test thread pool", num_threads); AtomicInteger count(0); static const int32_t num_tasks = num_threads * 4; for (int32_t i = 0; i < num_tasks; ++i) { @@ -74,7 +74,7 @@ TEST_F(ThreadPoolTest, CheckRun) { TEST_F(ThreadPoolTest, StopStart) { Thread* self = Thread::Current(); - ThreadPool thread_pool(num_threads); + ThreadPool thread_pool("Thread pool test thread pool", num_threads); AtomicInteger count(0); static const int32_t num_tasks = num_threads * 4; for (int32_t i = 0; i < num_tasks; ++i) { @@ -129,7 +129,7 @@ class TreeTask : public Task { // Test that adding new tasks from within a task works. TEST_F(ThreadPoolTest, RecursiveTest) { Thread* self = Thread::Current(); - ThreadPool thread_pool(num_threads); + ThreadPool thread_pool("Thread pool test thread pool", num_threads); AtomicInteger count(0); static const int depth = 8; thread_pool.AddTask(self, new TreeTask(&thread_pool, &count, depth)); |