Skip to content

Commit

Permalink
8261759: ZGC: ZWorker Threads Continue Marking After System.exit() ca…
Browse files Browse the repository at this point in the history
…lled

Reviewed-by: sjohanss, ayang
  • Loading branch information
pliden committed Apr 26, 2021
1 parent 31abe68 commit c3ac690
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 17 deletions.
32 changes: 32 additions & 0 deletions src/hotspot/share/gc/z/zAbort.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

#include "precompiled.hpp"
#include "gc/z/zAbort.hpp"
#include "runtime/atomic.hpp"

volatile bool ZAbort::_should_abort = false;

void ZAbort::abort() {
Atomic::release_store_fence(&_should_abort, true);
}
38 changes: 38 additions & 0 deletions src/hotspot/share/gc/z/zAbort.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

#ifndef SHARE_GC_Z_ZABORT_HPP
#define SHARE_GC_Z_ZABORT_HPP

#include "memory/allocation.hpp"

class ZAbort : public AllStatic {
private:
static volatile bool _should_abort;

public:
static bool should_abort();
static void abort();
};

#endif // SHARE_GC_Z_ZABORT_HPP
34 changes: 34 additions & 0 deletions src/hotspot/share/gc/z/zAbort.inline.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

#ifndef SHARE_GC_Z_ZABORT_INLINE_HPP
#define SHARE_GC_Z_ZABORT_INLINE_HPP

#include "gc/z/zAbort.hpp"
#include "runtime/atomic.hpp"

inline bool ZAbort::should_abort() {
return Atomic::load_acquire(&_should_abort);
}

#endif // SHARE_GC_Z_ZABORT_INLINE_HPP
27 changes: 21 additions & 6 deletions src/hotspot/share/gc/z/zDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcVMOperations.hpp"
#include "gc/shared/isGCActiveMark.hpp"
#include "gc/z/zAbort.inline.hpp"
#include "gc/z/zBreakpoint.hpp"
#include "gc/z/zCollectedHeap.hpp"
#include "gc/z/zDriver.hpp"
Expand Down Expand Up @@ -397,38 +398,51 @@ class ZDriverGCScope : public StackObj {
}
};

// Macro to execute a termination check after a concurrent phase. Note
// that it's important that the termination check comes after the call
// to the function f, since we can't abort between pause_relocate_start()
// and concurrent_relocate(). We need to let concurrent_relocate() call
// abort_page() on the remaining entries in the relocation set.
#define concurrent(f) \
do { \
concurrent_##f(); \
if (should_terminate()) { \
return; \
} \
} while (false)

void ZDriver::gc(GCCause::Cause cause) {
ZDriverGCScope scope(cause);

// Phase 1: Pause Mark Start
pause_mark_start();

// Phase 2: Concurrent Mark
concurrent_mark();
concurrent(mark);

// Phase 3: Pause Mark End
while (!pause_mark_end()) {
// Phase 3.5: Concurrent Mark Continue
concurrent_mark_continue();
concurrent(mark_continue);
}

// Phase 4: Concurrent Process Non-Strong References
concurrent_process_non_strong_references();
concurrent(process_non_strong_references);

// Phase 5: Concurrent Reset Relocation Set
concurrent_reset_relocation_set();
concurrent(reset_relocation_set);

// Phase 6: Pause Verify
pause_verify();

// Phase 7: Concurrent Select Relocation Set
concurrent_select_relocation_set();
concurrent(select_relocation_set);

// Phase 8: Pause Relocate Start
pause_relocate_start();

// Phase 9: Concurrent Relocate
concurrent_relocate();
concurrent(relocate);
}

void ZDriver::run_service() {
Expand Down Expand Up @@ -456,5 +470,6 @@ void ZDriver::run_service() {
}

void ZDriver::stop_service() {
ZAbort::abort();
_gc_cycle_port.send_async(GCCause::_no_gc);
}
25 changes: 22 additions & 3 deletions src/hotspot/share/gc/z/zForwarding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ bool ZForwarding::retain_page() {

if (ref_count < 0) {
// Claimed
wait_page_released();
const bool success = wait_page_released();
assert(success, "Should always succeed");
return false;
}

Expand Down Expand Up @@ -129,14 +130,24 @@ void ZForwarding::release_page() {
}
}

void ZForwarding::wait_page_released() const {
bool ZForwarding::wait_page_released() const {
if (Atomic::load_acquire(&_ref_count) != 0) {
ZStatTimer timer(ZCriticalPhaseRelocationStall);
ZLocker<ZConditionLock> locker(&_ref_lock);
if (_ref_abort) {
return false;
}

ZStatTimer timer(ZCriticalPhaseRelocationStall);
while (Atomic::load_acquire(&_ref_count) != 0) {
if (_ref_abort) {
return false;
}

_ref_lock.wait();
}
}

return true;
}

ZPage* ZForwarding::detach_page() {
Expand All @@ -154,6 +165,14 @@ ZPage* ZForwarding::detach_page() {
return page;
}

void ZForwarding::abort_page() {
ZLocker<ZConditionLock> locker(&_ref_lock);
assert(Atomic::load(&_ref_count) > 0, "Invalid state");
assert(!_ref_abort, "Invalid state");
_ref_abort = true;
_ref_lock.notify_all();
}

void ZForwarding::verify() const {
guarantee(_ref_count != 0, "Invalid reference count");
guarantee(_page != NULL, "Invalid page");
Expand Down
4 changes: 3 additions & 1 deletion src/hotspot/share/gc/z/zForwarding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class ZForwarding {
ZPage* _page;
mutable ZConditionLock _ref_lock;
volatile int32_t _ref_count;
bool _ref_abort;
bool _in_place;

ZForwardingEntry* entries() const;
Expand All @@ -70,8 +71,9 @@ class ZForwarding {
bool retain_page();
ZPage* claim_page();
void release_page();
void wait_page_released() const;
bool wait_page_released() const;
ZPage* detach_page();
void abort_page();

void set_in_place();
bool in_place() const;
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/gc/z/zForwarding.inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ inline ZForwarding::ZForwarding(ZPage* page, size_t nentries) :
_page(page),
_ref_lock(),
_ref_count(1),
_ref_abort(false),
_in_place(false) {}

inline uint8_t ZForwarding::type() const {
Expand Down
11 changes: 8 additions & 3 deletions src/hotspot/share/gc/z/zMark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "classfile/classLoaderDataGraph.hpp"
#include "code/nmethod.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/z/zAbort.inline.hpp"
#include "gc/z/zBarrier.inline.hpp"
#include "gc/z/zHeap.inline.hpp"
#include "gc/z/zLock.inline.hpp"
Expand Down Expand Up @@ -346,7 +347,7 @@ bool ZMark::drain(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, ZMarkCach
}

// Success
return true;
return !timeout->has_expired();
}

bool ZMark::try_steal_local(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) {
Expand Down Expand Up @@ -497,7 +498,8 @@ bool ZMark::try_terminate() {
class ZMarkNoTimeout : public StackObj {
public:
bool has_expired() {
return false;
// No timeout, but check for signal to abort
return ZAbort::should_abort();
}
};

Expand All @@ -506,7 +508,10 @@ void ZMark::work_without_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkTh
ZMarkNoTimeout no_timeout;

for (;;) {
drain(stripe, stacks, cache, &no_timeout);
if (!drain(stripe, stacks, cache, &no_timeout)) {
// Abort
break;
}

if (try_steal(stripe, stacks)) {
// Stole work
Expand Down
21 changes: 17 additions & 4 deletions src/hotspot/share/gc/z/zRelocate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "precompiled.hpp"
#include "gc/shared/gc_globals.hpp"
#include "gc/z/zAbort.inline.hpp"
#include "gc/z/zAddress.inline.hpp"
#include "gc/z/zBarrier.inline.hpp"
#include "gc/z/zForwarding.inline.hpp"
Expand Down Expand Up @@ -103,9 +104,14 @@ uintptr_t ZRelocate::relocate_object(ZForwarding* forwarding, uintptr_t from_add
return to_addr;
}

// Failed to relocate object. Wait for a worker thread to
// complete relocation of this page, and then forward object.
forwarding->wait_page_released();
// Failed to relocate object. Wait for a worker thread to complete
// relocation of this page, and then forward the object. If the GC
// aborts the relocation phase before the page has been relocated,
// then wait return false and we just forward the object in-place.
if (!forwarding->wait_page_released()) {
// Forward object in-place
return forwarding_insert(forwarding, from_addr, from_addr, &cursor);
}
}

// Forward object
Expand Down Expand Up @@ -339,8 +345,15 @@ class ZRelocateClosure : public ObjectClosure {
}

void do_forwarding(ZForwarding* forwarding) {
// Relocate objects
_forwarding = forwarding;

// Check if we should abort
if (ZAbort::should_abort()) {
_forwarding->abort_page();
return;
}

// Relocate objects
_forwarding->object_iterate(this);

// Verify
Expand Down
15 changes: 15 additions & 0 deletions src/hotspot/share/gc/z/zStat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "precompiled.hpp"
#include "gc/shared/gc_globals.hpp"
#include "gc/z/zAbort.inline.hpp"
#include "gc/z/zCollectedHeap.hpp"
#include "gc/z/zCPU.inline.hpp"
#include "gc/z/zGlobals.hpp"
Expand Down Expand Up @@ -642,6 +643,12 @@ void ZStatPhaseCycle::register_start(const Ticks& start) const {
}

void ZStatPhaseCycle::register_end(const Ticks& start, const Ticks& end) const {
if (ZAbort::should_abort()) {
log_info(gc)("Garbage Collection (%s) Aborted",
GCCause::to_string(ZCollectedHeap::heap()->gc_cause()));
return;
}

timer()->register_gc_end(end);

ZCollectedHeap::heap()->print_heap_after_gc();
Expand Down Expand Up @@ -712,6 +719,10 @@ void ZStatPhaseConcurrent::register_start(const Ticks& start) const {
}

void ZStatPhaseConcurrent::register_end(const Ticks& start, const Ticks& end) const {
if (ZAbort::should_abort()) {
return;
}

timer()->register_gc_concurrent_end(end);

const Tickspan duration = end - start;
Expand All @@ -730,6 +741,10 @@ void ZStatSubPhase::register_start(const Ticks& start) const {
}

void ZStatSubPhase::register_end(const Ticks& start, const Ticks& end) const {
if (ZAbort::should_abort()) {
return;
}

ZTracer::tracer()->report_thread_phase(name(), start, end);

const Tickspan duration = end - start;
Expand Down

1 comment on commit c3ac690

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.