From 63462ee4b09a0335c96a966ff884d5fd3fd8c9aa Mon Sep 17 00:00:00 2001 From: Panferov Ivan Date: Fri, 29 Sep 2023 18:19:10 +0300 Subject: [PATCH 1/2] Integrate compiler with TaskManager Signed-off-by: Panferov Ivan --- plugins/ets/runtime_options.yaml | 2 +- runtime/compiler.cpp | 4 ++- runtime/compiler.h | 61 +++++++++++++++++++++++++------- runtime/mem/gc/gc.cpp | 2 +- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/plugins/ets/runtime_options.yaml b/plugins/ets/runtime_options.yaml index 31e907afa..5fab82891 100644 --- a/plugins/ets/runtime_options.yaml +++ b/plugins/ets/runtime_options.yaml @@ -214,5 +214,5 @@ options: lang: - ets type: uint32_t - default: 2 + default: 3 description: Number of worker threads for the taskmanager. Option is used only for --worker-type=taskmanager diff --git a/runtime/compiler.cpp b/runtime/compiler.cpp index ecc736079..122d9d230 100644 --- a/runtime/compiler.cpp +++ b/runtime/compiler.cpp @@ -773,7 +773,7 @@ bool Compiler::CompileMethod(Method *method, uintptr_t bytecode_offset, bool osr auto status = method->GetCompilationStatus(); for (; (status == Method::WAITING) || (status == Method::COMPILATION); status = method->GetCompilationStatus()) { - if (thread_pool_ == nullptr || !thread_pool_->IsActive()) { + if (jit_thread_joined_) { // JIT thread is destroyed, wait makes no sence return false; } @@ -797,6 +797,7 @@ void Compiler::CompileMethodLocked(const CompilerTask &&ctx) method->ResetHotnessCounter(); if (IsCompilationExpired(ctx)) { + ASSERT(!no_async_jit_); return; } @@ -831,6 +832,7 @@ void Compiler::JoinWorker() if (thread_pool_ != nullptr) { thread_pool_->Shutdown(true); } + jit_thread_joined_ = true; #ifdef PANDA_COMPILER_DEBUG_INFO if (!Runtime::GetOptions().IsArkAot() && compiler::OPTIONS.IsCompilerEmitDebugInfo()) { compiler::CleanJitDebugCode(); diff --git a/runtime/compiler.h b/runtime/compiler.h index 8e912d970..5f783f968 100644 --- a/runtime/compiler.h +++ b/runtime/compiler.h @@ -642,13 +642,20 @@ public: return; } - queue_ = CreateJITTaskQueue(no_async_jit_ ? "simple" : options.GetCompilerQueueType(), - options.GetCompilerQueueMaxLength(), options.GetCompilerTaskLifeSpan(), - options.GetCompilerDeathCounterValue(), options.GetCompilerEpochDuration()); - if (queue_ == nullptr) { - // Because of problems (no memory) in allocator - LOG(ERROR, COMPILER) << "Cannot create a compiler queue"; - no_async_jit_ = true; + use_task_manager_ = Runtime::GetTaskScheduler() != nullptr; + if (use_task_manager_) { + jit_task_queue_ = internal_allocator_->New( + taskmanager::TaskType::JIT, taskmanager::VMType::STATIC_VM, taskmanager::TaskQueue::DEFAULT_PRIORITY); + ASSERT(jit_task_queue_ != nullptr); + } else { + queue_ = CreateJITTaskQueue(no_async_jit_ ? "simple" : options.GetCompilerQueueType(), + options.GetCompilerQueueMaxLength(), options.GetCompilerTaskLifeSpan(), + options.GetCompilerDeathCounterValue(), options.GetCompilerEpochDuration()); + if (queue_ == nullptr) { + // Because of problems (no memory) in allocator + LOG(ERROR, COMPILER) << "Cannot create a compiler queue"; + no_async_jit_ = true; + } } CreateWorker(); if (compiler::OPTIONS.WasSetCompilerDumpJitStatsCsv()) { @@ -673,6 +680,7 @@ public: internal_allocator_->Delete(thread_pool_); thread_pool_ = nullptr; } + jit_thread_joined_ = true; } void JoinWorker() override; @@ -687,14 +695,30 @@ public: queue_->Finalize(); internal_allocator_->Delete(queue_); } + if (jit_task_queue_ != nullptr) { + internal_allocator_->Delete(jit_task_queue_); + jit_task_queue_ = nullptr; + } internal_allocator_->Delete(jit_stats_); } bool CompileMethod(Method *method, uintptr_t bytecode_offset, bool osr, TaggedValue func) override; - virtual void AddTask(CompilerTask &&task, [[maybe_unused]] TaggedValue func) - { - thread_pool_->PutTask(std::move(task)); + virtual void AddTask(CompilerTask &&ctx, [[maybe_unused]] TaggedValue func) + { + if (use_task_manager_) { + auto *ctx_ptr = internal_allocator_->New(std::move(ctx)); + auto task_runner = [this, ctx_ptr] { + if (ctx_ptr->GetMethod()->AtomicSetCompilationStatus(Method::WAITING, Method::COMPILATION)) { + CompileMethodLocked(std::move(*ctx_ptr)); + } + internal_allocator_->Delete(ctx_ptr); + }; + auto task = taskmanager::Task::Create(JIT_TASK_PROPERTIES, std::move(task_runner)); + jit_task_queue_->AddTask(std::move(task)); + } else { + thread_pool_->PutTask(std::move(ctx)); + } } /// Basic method, which starts compilation. Do not use. @@ -768,10 +792,16 @@ private: void CreateWorker() { - if (thread_pool_ == nullptr) { - thread_pool_ = internal_allocator_->New>( - internal_allocator_, queue_, this, 1, "JIT Thread"); + if (use_task_manager_) { + [[maybe_unused]] taskmanager::TaskQueueId id = Runtime::GetTaskScheduler()->RegisterQueue(jit_task_queue_); + ASSERT(!(id == taskmanager::INVALID_TASKQUEUE_ID)); + } else { + if (thread_pool_ == nullptr) { + thread_pool_ = internal_allocator_->New>( + internal_allocator_, queue_, this, 1, "JIT Thread"); + } } + jit_thread_joined_ = false; } CodeAllocator *code_allocator_; @@ -782,9 +812,14 @@ private: compiler::RuntimeInterface *runtime_iface_; // The lock is used for compiler thread synchronization os::memory::Mutex compilation_lock_; + taskmanager::TaskQueue *jit_task_queue_ {nullptr}; + static constexpr taskmanager::TaskProperties JIT_TASK_PROPERTIES { + taskmanager::TaskType::JIT, taskmanager::VMType::STATIC_VM, taskmanager::TaskExecutionMode::BACKGROUND}; // This queue is used only in ThreadPool. Do not use it from this class. CompilerQueueInterface *queue_ {nullptr}; bool no_async_jit_; + bool use_task_manager_ {false}; + std::atomic jit_thread_joined_ {true}; ThreadPool *thread_pool_; compiler::JITStats *jit_stats_ {nullptr}; NO_COPY_SEMANTIC(Compiler); diff --git a/runtime/mem/gc/gc.cpp b/runtime/mem/gc/gc.cpp index 798a890f1..a29792e4a 100644 --- a/runtime/mem/gc/gc.cpp +++ b/runtime/mem/gc/gc.cpp @@ -488,7 +488,7 @@ void GC::JoinWorker(bool continue_run_gc) // where threads observe all modifications in the same order gc_running_.store(false, std::memory_order_seq_cst); // TODO(ipetrov, #13816): remove unnecessary second check - if (!gc_settings_.RunGCInPlace() && gc_settings_.UseThreadPoolForGCWorkers()) { + if (!gc_settings_.RunGCInPlace() && gc_settings_.UseThreadPoolForGCWorkers() && continue_run_gc) { ASSERT(worker_ != nullptr); } if (worker_ != nullptr && !gc_settings_.RunGCInPlace()) { -- Gitee From a814da8f3eea37c2ffa916b23ef1eac5c1fe6732 Mon Sep 17 00:00:00 2001 From: Panferov Ivan Date: Tue, 10 Oct 2023 14:18:31 +0300 Subject: [PATCH 2/2] Fix compiler finalization with taskmanager Signed-off-by: Panferov Ivan --- runtime/compiler.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- runtime/compiler.h | 22 +++++----------------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/runtime/compiler.cpp b/runtime/compiler.cpp index 122d9d230..d937e7f7b 100644 --- a/runtime/compiler.cpp +++ b/runtime/compiler.cpp @@ -827,12 +827,52 @@ void Compiler::CompileMethodLocked(const CompilerTask &&ctx) method->AtomicSetCompilationStatus(Method::COMPILATION, Method::COMPILED); } +void Compiler::AddTask(CompilerTask &&ctx, [[maybe_unused]] TaggedValue func) +{ + if (use_task_manager_) { + auto *ctx_ptr = internal_allocator_->New(std::move(ctx)); + auto task_runner = [this, ctx_ptr] { + if (ctx_ptr->GetMethod()->AtomicSetCompilationStatus(Method::WAITING, Method::COMPILATION)) { + CompileMethodLocked(std::move(*ctx_ptr)); + } + internal_allocator_->Delete(ctx_ptr); + { + os::memory::LockHolder lock(jit_worker_finalization_lock_); + --unprocessed_tasks_; + if (jit_thread_joined_ && (unprocessed_tasks_ == 0)) { + jit_tasks_processed_.Signal(); + } + } + }; + auto task = taskmanager::Task::Create(JIT_TASK_PROPERTIES, std::move(task_runner)); + { + os::memory::LockHolder lock(jit_worker_finalization_lock_); + if (!jit_thread_joined_) { + ++unprocessed_tasks_; + jit_task_queue_->AddTask(std::move(task)); + } + } + } else { + thread_pool_->PutTask(std::move(ctx)); + } +} + void Compiler::JoinWorker() { if (thread_pool_ != nullptr) { thread_pool_->Shutdown(true); } - jit_thread_joined_ = true; + + { + os::memory::LockHolder lock(jit_worker_finalization_lock_); + jit_thread_joined_ = true; + if (use_task_manager_) { + while (unprocessed_tasks_ != 0) { + jit_tasks_processed_.Wait(&jit_worker_finalization_lock_); + } + } + } + #ifdef PANDA_COMPILER_DEBUG_INFO if (!Runtime::GetOptions().IsArkAot() && compiler::OPTIONS.IsCompilerEmitDebugInfo()) { compiler::CleanJitDebugCode(); diff --git a/runtime/compiler.h b/runtime/compiler.h index 5f783f968..001f9d238 100644 --- a/runtime/compiler.h +++ b/runtime/compiler.h @@ -704,22 +704,7 @@ public: bool CompileMethod(Method *method, uintptr_t bytecode_offset, bool osr, TaggedValue func) override; - virtual void AddTask(CompilerTask &&ctx, [[maybe_unused]] TaggedValue func) - { - if (use_task_manager_) { - auto *ctx_ptr = internal_allocator_->New(std::move(ctx)); - auto task_runner = [this, ctx_ptr] { - if (ctx_ptr->GetMethod()->AtomicSetCompilationStatus(Method::WAITING, Method::COMPILATION)) { - CompileMethodLocked(std::move(*ctx_ptr)); - } - internal_allocator_->Delete(ctx_ptr); - }; - auto task = taskmanager::Task::Create(JIT_TASK_PROPERTIES, std::move(task_runner)); - jit_task_queue_->AddTask(std::move(task)); - } else { - thread_pool_->PutTask(std::move(ctx)); - } - } + virtual void AddTask(CompilerTask &&ctx, [[maybe_unused]] TaggedValue func); /// Basic method, which starts compilation. Do not use. void CompileMethodLocked(const CompilerTask &&ctx); @@ -815,11 +800,14 @@ private: taskmanager::TaskQueue *jit_task_queue_ {nullptr}; static constexpr taskmanager::TaskProperties JIT_TASK_PROPERTIES { taskmanager::TaskType::JIT, taskmanager::VMType::STATIC_VM, taskmanager::TaskExecutionMode::BACKGROUND}; + os::memory::Mutex jit_worker_finalization_lock_; + size_t unprocessed_tasks_ {0}; + os::memory::ConditionVariable jit_tasks_processed_; // This queue is used only in ThreadPool. Do not use it from this class. CompilerQueueInterface *queue_ {nullptr}; bool no_async_jit_; bool use_task_manager_ {false}; - std::atomic jit_thread_joined_ {true}; + bool jit_thread_joined_ {true}; ThreadPool *thread_pool_; compiler::JITStats *jit_stats_ {nullptr}; NO_COPY_SEMANTIC(Compiler); -- Gitee