8374686: ZGC: Convert zMarkTerminate to use Atomic<T>

Reviewed-by: stefank, kbarrett
This commit is contained in:
Axel Boldt-Christmas 2026-01-27 08:26:00 +00:00
parent cba7d88ca4
commit 5c05d6f230
2 changed files with 26 additions and 28 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
#define SHARE_GC_Z_ZMARKTERMINATE_HPP #define SHARE_GC_Z_ZMARKTERMINATE_HPP
#include "gc/z/zLock.hpp" #include "gc/z/zLock.hpp"
#include "runtime/atomic.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
class ZMarkStripeSet; class ZMarkStripeSet;
@ -32,9 +33,9 @@ class ZMarkStripeSet;
class ZMarkTerminate { class ZMarkTerminate {
private: private:
uint _nworkers; uint _nworkers;
volatile uint _nworking; Atomic<uint> _nworking;
volatile uint _nawakening; Atomic<uint> _nawakening;
volatile bool _resurrected; Atomic<bool> _resurrected;
ZConditionLock _lock; ZConditionLock _lock;
void maybe_reduce_stripes(ZMarkStripeSet* stripes, size_t used_nstripes); void maybe_reduce_stripes(ZMarkStripeSet* stripes, size_t used_nstripes);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,7 +30,6 @@
#include "gc/z/zLock.inline.hpp" #include "gc/z/zLock.inline.hpp"
#include "gc/z/zMarkStack.hpp" #include "gc/z/zMarkStack.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/osThread.hpp" #include "runtime/osThread.hpp"
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
@ -42,24 +41,23 @@ inline ZMarkTerminate::ZMarkTerminate()
_lock() {} _lock() {}
inline void ZMarkTerminate::reset(uint nworkers) { inline void ZMarkTerminate::reset(uint nworkers) {
AtomicAccess::store(&_nworkers, nworkers); _nworkers = nworkers;
AtomicAccess::store(&_nworking, nworkers); _nworking.store_relaxed(nworkers);
_nawakening = 0; _nawakening.store_relaxed(0u);
} }
inline void ZMarkTerminate::leave() { inline void ZMarkTerminate::leave() {
SuspendibleThreadSetLeaver sts_leaver; SuspendibleThreadSetLeaver sts_leaver;
ZLocker<ZConditionLock> locker(&_lock); ZLocker<ZConditionLock> locker(&_lock);
AtomicAccess::store(&_nworking, _nworking - 1); if (_nworking.sub_then_fetch(1u, memory_order_relaxed) == 0) {
if (_nworking == 0) {
// Last thread leaving; notify waiters // Last thread leaving; notify waiters
_lock.notify_all(); _lock.notify_all();
} }
} }
inline void ZMarkTerminate::maybe_reduce_stripes(ZMarkStripeSet* stripes, size_t used_nstripes) { inline void ZMarkTerminate::maybe_reduce_stripes(ZMarkStripeSet* stripes, size_t used_nstripes) {
size_t nstripes = stripes->nstripes(); const size_t nstripes = stripes->nstripes();
if (used_nstripes == nstripes && nstripes > 1u) { if (used_nstripes == nstripes && nstripes > 1u) {
stripes->try_set_nstripes(nstripes, nstripes >> 1); stripes->try_set_nstripes(nstripes, nstripes >> 1);
} }
@ -69,8 +67,7 @@ inline bool ZMarkTerminate::try_terminate(ZMarkStripeSet* stripes, size_t used_n
SuspendibleThreadSetLeaver sts_leaver; SuspendibleThreadSetLeaver sts_leaver;
ZLocker<ZConditionLock> locker(&_lock); ZLocker<ZConditionLock> locker(&_lock);
AtomicAccess::store(&_nworking, _nworking - 1); if (_nworking.sub_then_fetch(1u, memory_order_relaxed) == 0) {
if (_nworking == 0) {
// Last thread entering termination: success // Last thread entering termination: success
_lock.notify_all(); _lock.notify_all();
return true; return true;
@ -83,24 +80,24 @@ inline bool ZMarkTerminate::try_terminate(ZMarkStripeSet* stripes, size_t used_n
// We either got notification about more work // We either got notification about more work
// or got a spurious wakeup; don't terminate // or got a spurious wakeup; don't terminate
if (_nawakening > 0) { if (_nawakening.load_relaxed() > 0) {
AtomicAccess::store(&_nawakening, _nawakening - 1); _nawakening.sub_then_fetch(1u, memory_order_relaxed);
} }
if (_nworking == 0) { if (_nworking.load_relaxed() == 0) {
// We got notified all work is done; terminate // We got notified all work is done; terminate
return true; return true;
} }
AtomicAccess::store(&_nworking, _nworking + 1); _nworking.add_then_fetch(1u, memory_order_relaxed);
return false; return false;
} }
inline void ZMarkTerminate::wake_up() { inline void ZMarkTerminate::wake_up() {
uint nworking = AtomicAccess::load(&_nworking); const uint nworking = _nworking.load_relaxed();
uint nawakening = AtomicAccess::load(&_nawakening); const uint nawakening = _nawakening.load_relaxed();
if (nworking + nawakening == AtomicAccess::load(&_nworkers)) { if (nworking + nawakening == _nworkers) {
// Everyone is working or about to // Everyone is working or about to
return; return;
} }
@ -111,24 +108,24 @@ inline void ZMarkTerminate::wake_up() {
} }
ZLocker<ZConditionLock> locker(&_lock); ZLocker<ZConditionLock> locker(&_lock);
if (_nworking + _nawakening != _nworkers) { if (_nworking.load_relaxed() + _nawakening.load_relaxed() != _nworkers) {
// Everyone is not working // Everyone is not working
AtomicAccess::store(&_nawakening, _nawakening + 1); _nawakening.add_then_fetch(1u, memory_order_relaxed);
_lock.notify(); _lock.notify();
} }
} }
inline bool ZMarkTerminate::saturated() const { inline bool ZMarkTerminate::saturated() const {
uint nworking = AtomicAccess::load(&_nworking); const uint nworking = _nworking.load_relaxed();
uint nawakening = AtomicAccess::load(&_nawakening); const uint nawakening = _nawakening.load_relaxed();
return nworking + nawakening == AtomicAccess::load(&_nworkers); return nworking + nawakening == _nworkers;
} }
inline void ZMarkTerminate::set_resurrected(bool value) { inline void ZMarkTerminate::set_resurrected(bool value) {
// Update resurrected if it changed // Update resurrected if it changed
if (resurrected() != value) { if (resurrected() != value) {
AtomicAccess::store(&_resurrected, value); _resurrected.store_relaxed(value);
if (value) { if (value) {
log_debug(gc, marking)("Resurrection broke termination"); log_debug(gc, marking)("Resurrection broke termination");
} else { } else {
@ -138,7 +135,7 @@ inline void ZMarkTerminate::set_resurrected(bool value) {
} }
inline bool ZMarkTerminate::resurrected() const { inline bool ZMarkTerminate::resurrected() const {
return AtomicAccess::load(&_resurrected); return _resurrected.load_relaxed();
} }
#endif // SHARE_GC_Z_ZMARKTERMINATE_INLINE_HPP #endif // SHARE_GC_Z_ZMARKTERMINATE_INLINE_HPP