[K/N] Do not hold GC locks when finalizer thread is starting

Merge-request: KT-MR-9799
Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
Alexander Shabalin
2023-04-26 08:29:07 +00:00
committed by Space Team
parent c52ad22795
commit f058ee21b0
2 changed files with 11 additions and 5 deletions
@@ -972,7 +972,7 @@ task worker9_experimentalMM(type: KonanLocalTest) {
task worker10(type: KonanLocalTest) { task worker10(type: KonanLocalTest) {
enabled = (project.testTarget != 'wasm32') && // Workers need pthreads. enabled = (project.testTarget != 'wasm32') && // Workers need pthreads.
!isNoopGC && !isAggressiveGC !isNoopGC
useGoldenData = true useGoldenData = true
source = "runtime/workers/worker10.kt" source = "runtime/workers/worker10.kt"
} }
@@ -6,6 +6,7 @@
#include "ConcurrentMarkAndSweep.hpp" #include "ConcurrentMarkAndSweep.hpp"
#include <cinttypes> #include <cinttypes>
#include <optional>
#include "CompilerConstants.hpp" #include "CompilerConstants.hpp"
#include "GlobalData.hpp" #include "GlobalData.hpp"
@@ -194,13 +195,15 @@ bool gc::ConcurrentMarkAndSweep::PerformFullGC(int64_t epoch) noexcept {
#ifndef CUSTOM_ALLOCATOR #ifndef CUSTOM_ALLOCATOR
// Taking the locks before the pause is completed. So that any destroying thread // Taking the locks before the pause is completed. So that any destroying thread
// would not publish into the global state at an unexpected time. // would not publish into the global state at an unexpected time.
auto extraObjectFactoryIterable = mm::GlobalData::Instance().extraObjectDataFactory().LockForIter(); std::optional extraObjectFactoryIterable = mm::GlobalData::Instance().extraObjectDataFactory().LockForIter();
auto objectFactoryIterable = objectFactory_.LockForIter(); std::optional objectFactoryIterable = objectFactory_.LockForIter();
mm::ResumeThreads(); mm::ResumeThreads();
gcHandle.threadsAreResumed(); gcHandle.threadsAreResumed();
gc::SweepExtraObjects<SweepTraits>(gcHandle, extraObjectFactoryIterable); gc::SweepExtraObjects<SweepTraits>(gcHandle, *extraObjectFactoryIterable);
auto finalizerQueue = gc::Sweep<SweepTraits>(gcHandle, objectFactoryIterable); extraObjectFactoryIterable = std::nullopt;
auto finalizerQueue = gc::Sweep<SweepTraits>(gcHandle, *objectFactoryIterable);
objectFactoryIterable = std::nullopt;
kotlin::compactObjectPoolInMainThread(); kotlin::compactObjectPoolInMainThread();
#else #else
auto finalizerQueue = heap_.SweepExtraObjects(gcHandle); auto finalizerQueue = heap_.SweepExtraObjects(gcHandle);
@@ -212,6 +215,9 @@ bool gc::ConcurrentMarkAndSweep::PerformFullGC(int64_t epoch) noexcept {
state_.finish(epoch); state_.finish(epoch);
gcHandle.finalizersScheduled(finalizerQueue.size()); gcHandle.finalizersScheduled(finalizerQueue.size());
gcHandle.finished(); gcHandle.finished();
// This may start a new thread. On some pthreads implementations, this may block waiting for concurrent thread
// destructors running. So, it must ensured that no locks are held by this point.
// TODO: Consider having an always on sleeping finalizer thread.
finalizerProcessor_->ScheduleTasks(std::move(finalizerQueue), epoch); finalizerProcessor_->ScheduleTasks(std::move(finalizerQueue), epoch);
return true; return true;
} }