[K/N] Extract ThreadRegistry::waitAllThreads

This commit is contained in:
Alexander Shabalin
2023-07-19 10:20:41 +02:00
committed by Space Team
parent 9baac3685d
commit a69cd5e333
4 changed files with 21 additions and 60 deletions
@@ -44,15 +44,11 @@ void waitForThreadsToReachCheckpoint() {
mm::SafePointActivator safePointActivator;
// Disable new threads coming and going.
auto threads = mm::ThreadRegistry::Instance().LockForIter();
// And wait for all threads to either have passed safepoint or to be in the native state.
// Wait for all threads to either have passed safepoint or to be in the native state.
// Either of these mean that none of them are inside a weak reference accessing code.
while (!std::all_of(threads.begin(), threads.end(), [](mm::ThreadData& thread) noexcept {
mm::ThreadRegistry::Instance().waitAllThreads([](mm::ThreadData& thread) noexcept {
return thread.gc().impl().gc().barriers().visitedCheckpoint() || thread.suspensionData().suspendedOrNative();
})) {
std::this_thread::yield();
}
});
}
} // namespace
@@ -162,7 +162,6 @@ void gc::ConcurrentMarkAndSweep::PerformFullGC(int64_t epoch) noexcept {
RuntimeAssert(didSuspend, "Only GC thread can request suspension");
gcHandle.suspensionRequested();
RuntimeAssert(!kotlin::mm::IsCurrentThreadRegistered(), "GC must run on unregistered thread");
WaitForThreadsReadyToMark();
gcHandle.threadsAreSuspended();
@@ -236,41 +235,16 @@ void gc::ConcurrentMarkAndSweep::PerformFullGC(int64_t epoch) noexcept {
finalizerProcessor_.ScheduleTasks(std::move(finalizerQueue), epoch);
}
namespace {
bool isSuspendedOrNative(kotlin::mm::ThreadData& thread) noexcept {
auto& suspensionData = thread.suspensionData();
return suspensionData.suspended() || suspensionData.state() == kotlin::ThreadState::kNative;
}
template <typename F>
bool allThreads(F predicate) noexcept {
auto& threadRegistry = kotlin::mm::ThreadRegistry::Instance();
auto* currentThread = (threadRegistry.IsCurrentThreadRegistered()) ? threadRegistry.CurrentThreadData() : nullptr;
kotlin::mm::ThreadRegistry::Iterable threads = kotlin::mm::ThreadRegistry::Instance().LockForIter();
for (auto& thread : threads) {
// Handle if suspension was initiated by the mutator thread.
if (&thread == currentThread) continue;
if (!predicate(thread)) {
return false;
}
}
return true;
}
void yield() noexcept {
std::this_thread::yield();
}
} // namespace
void gc::ConcurrentMarkAndSweep::SetMarkingRequested(uint64_t epoch) noexcept {
markingRequested = markingBehavior_ == MarkingBehavior::kMarkOwnStack;
markingEpoch = epoch;
}
void gc::ConcurrentMarkAndSweep::WaitForThreadsReadyToMark() noexcept {
while(!allThreads([](kotlin::mm::ThreadData& thread) { return isSuspendedOrNative(thread) || thread.gc().impl().gc().marking_.load(); })) {
yield();
}
RuntimeAssert(!kotlin::mm::IsCurrentThreadRegistered(), "GC must run on unregistered thread");
mm::ThreadRegistry::Instance().waitAllThreads([](mm::ThreadData& thread) noexcept {
return thread.suspensionData().suspendedOrNative() || thread.gc().impl().gc().marking_.load();
});
}
void gc::ConcurrentMarkAndSweep::CollectRootSetAndStartMarking(GCHandle gcHandle) noexcept {
@@ -50,6 +50,15 @@ public:
static void ClearCurrentThreadData() { currentThreadDataNode_ = nullptr; }
template <typename F>
void waitAllThreads(F&& f) noexcept {
// Disable new threads coming and going.
auto iter = LockForIter();
while (!std::all_of(iter.begin(), iter.end(), std::forward<F>(f))) {
std::this_thread::yield();
}
}
private:
friend class GlobalData;
@@ -19,26 +19,6 @@ using namespace kotlin;
namespace {
template<typename F>
bool allThreads(F predicate) noexcept {
auto& threadRegistry = kotlin::mm::ThreadRegistry::Instance();
auto* currentThread = (threadRegistry.IsCurrentThreadRegistered()) ? threadRegistry.CurrentThreadData() : nullptr;
kotlin::mm::ThreadRegistry::Iterable threads = kotlin::mm::ThreadRegistry::Instance().LockForIter();
for (auto& thread : threads) {
// Handle if suspension was initiated by the mutator thread.
if (&thread == currentThread)
continue;
if (!predicate(thread)) {
return false;
}
}
return true;
}
void yield() noexcept {
std::this_thread::yield();
}
[[clang::no_destroy]] thread_local std::optional<mm::SafePointActivator> gSafePointActivator = std::nullopt;
[[clang::no_destroy]] std::mutex gSuspensionMutex;
[[clang::no_destroy]] std::condition_variable gSuspensionCondVar;
@@ -89,10 +69,12 @@ bool kotlin::mm::RequestThreadsSuspension() noexcept {
}
void kotlin::mm::WaitForThreadsSuspension() noexcept {
auto& threadRegistry = kotlin::mm::ThreadRegistry::Instance();
auto* currentThread = (threadRegistry.IsCurrentThreadRegistered()) ? threadRegistry.CurrentThreadData() : nullptr;
// Spin waiting for threads to suspend. Ignore Native threads.
while (!allThreads([](mm::ThreadData& thread) { return thread.suspensionData().suspendedOrNative(); })) {
yield();
}
threadRegistry.waitAllThreads([currentThread](mm::ThreadData& thread) noexcept {
return &thread == currentThread || thread.suspensionData().suspendedOrNative();
});
}
void kotlin::mm::ResumeThreads() noexcept {