Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/shenandoah/shenandoahEvacOOMHandler.cpp
38920 views
1
/*
2
* Copyright (c) 2018, Red Hat, Inc. All rights reserved.
3
*
4
* This code is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 2 only, as
6
* published by the Free Software Foundation.
7
*
8
* This code is distributed in the hope that it will be useful, but WITHOUT
9
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11
* version 2 for more details (a copy is included in the LICENSE file that
12
* accompanied this code).
13
*
14
* You should have received a copy of the GNU General Public License version
15
* 2 along with this work; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*
18
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19
* or visit www.oracle.com if you need additional information or have any
20
* questions.
21
*
22
*/
23
24
#include "precompiled.hpp"
25
26
#include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
27
#include "gc_implementation/shenandoah/shenandoahUtils.hpp"
28
#include "gc_implementation/shenandoah/shenandoahEvacOOMHandler.hpp"
29
30
const jint ShenandoahEvacOOMHandler::OOM_MARKER_MASK = 0x80000000;
31
32
ShenandoahEvacOOMHandler::ShenandoahEvacOOMHandler() :
33
_threads_in_evac(0) {
34
}
35
36
void ShenandoahEvacOOMHandler::wait_for_no_evac_threads() {
37
while ((OrderAccess::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) != 0) {
38
os::naked_short_sleep(1);
39
}
40
// At this point we are sure that no threads can evacuate anything. Raise
41
// the thread-local oom_during_evac flag to indicate that any attempt
42
// to evacuate should simply return the forwarding pointer instead (which is safe now).
43
Thread::current()->set_oom_during_evac(true);
44
}
45
46
void ShenandoahEvacOOMHandler::enter_evacuation() {
47
jint threads_in_evac = OrderAccess::load_acquire(&_threads_in_evac);
48
49
assert(!Thread::current()->is_evac_allowed(), "sanity");
50
assert(!Thread::current()->is_oom_during_evac(), "TL oom-during-evac must not be set");
51
52
if ((threads_in_evac & OOM_MARKER_MASK) != 0) {
53
wait_for_no_evac_threads();
54
return;
55
}
56
57
while (true) {
58
jint other = Atomic::cmpxchg(threads_in_evac + 1, &_threads_in_evac, threads_in_evac);
59
if (other == threads_in_evac) {
60
// Success: caller may safely enter evacuation
61
DEBUG_ONLY(Thread::current()->set_evac_allowed(true));
62
return;
63
} else {
64
// Failure:
65
// - if offender has OOM_MARKER_MASK, then loop until no more threads in evac
66
// - otherwise re-try CAS
67
if ((other & OOM_MARKER_MASK) != 0) {
68
wait_for_no_evac_threads();
69
return;
70
}
71
threads_in_evac = other;
72
}
73
}
74
}
75
76
void ShenandoahEvacOOMHandler::leave_evacuation() {
77
if (!Thread::current()->is_oom_during_evac()) {
78
assert((OrderAccess::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) > 0, "sanity");
79
// NOTE: It's ok to simply decrement, even with mask set, because unmasked value is positive.
80
Atomic::dec(&_threads_in_evac);
81
} else {
82
// If we get here, the current thread has already gone through the
83
// OOM-during-evac protocol and has thus either never entered or successfully left
84
// the evacuation region. Simply flip its TL oom-during-evac flag back off.
85
Thread::current()->set_oom_during_evac(false);
86
}
87
DEBUG_ONLY(Thread::current()->set_evac_allowed(false));
88
assert(!Thread::current()->is_oom_during_evac(), "TL oom-during-evac must be turned off");
89
}
90
91
void ShenandoahEvacOOMHandler::handle_out_of_memory_during_evacuation() {
92
assert(Thread::current()->is_evac_allowed(), "sanity");
93
assert(!Thread::current()->is_oom_during_evac(), "TL oom-during-evac must not be set");
94
95
jint threads_in_evac = OrderAccess::load_acquire(&_threads_in_evac);
96
while (true) {
97
jint other = Atomic::cmpxchg((threads_in_evac - 1) | OOM_MARKER_MASK,
98
&_threads_in_evac, threads_in_evac);
99
if (other == threads_in_evac) {
100
// Success: wait for other threads to get out of the protocol and return.
101
wait_for_no_evac_threads();
102
return;
103
} else {
104
// Failure: try again with updated new value.
105
threads_in_evac = other;
106
}
107
}
108
}
109
110
void ShenandoahEvacOOMHandler::clear() {
111
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at a safepoint");
112
assert((OrderAccess::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) == 0, "sanity");
113
OrderAccess::release_store_fence(&_threads_in_evac, 0);
114
}
115
116
ShenandoahEvacOOMScope::ShenandoahEvacOOMScope() {
117
ShenandoahHeap::heap()->enter_evacuation();
118
}
119
120
ShenandoahEvacOOMScope::~ShenandoahEvacOOMScope() {
121
ShenandoahHeap::heap()->leave_evacuation();
122
}
123
124