Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/gc/shared/concurrentGCBreakpoints.cpp
40957 views
1
/*
2
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "gc/shared/collectedHeap.hpp"
27
#include "gc/shared/concurrentGCBreakpoints.hpp"
28
#include "logging/log.hpp"
29
#include "memory/universe.hpp"
30
#include "runtime/interfaceSupport.inline.hpp"
31
#include "runtime/mutexLocker.hpp"
32
#include "runtime/thread.hpp"
33
#include "utilities/debug.hpp"
34
35
// States:
36
// _run_to _want_idle _is_stopped
37
// (1) No active request NULL false false
38
// (2) Active run_to() running non-NULL false false
39
// (3) Active run_to() in at() NULL false true
40
// (4) Active run_to_idle() NULL true false
41
const char* ConcurrentGCBreakpoints::_run_to = NULL;
42
bool ConcurrentGCBreakpoints::_want_idle = false;
43
bool ConcurrentGCBreakpoints::_is_stopped = false;
44
45
// True if the collector is idle.
46
bool ConcurrentGCBreakpoints::_is_idle = true;
47
48
void ConcurrentGCBreakpoints::reset_request_state() {
49
_run_to = NULL;
50
_want_idle = false;
51
_is_stopped = false;
52
}
53
54
Monitor* ConcurrentGCBreakpoints::monitor() {
55
return ConcurrentGCBreakpoints_lock;
56
}
57
58
bool ConcurrentGCBreakpoints::is_controlled() {
59
assert_locked_or_safepoint(monitor());
60
return _want_idle || _is_stopped || (_run_to != NULL);
61
}
62
63
#define assert_Java_thread() \
64
assert(Thread::current()->is_Java_thread(), "precondition")
65
66
void ConcurrentGCBreakpoints::run_to_idle_impl(bool acquiring_control) {
67
assert_Java_thread();
68
MonitorLocker ml(monitor());
69
if (acquiring_control) {
70
assert(!is_controlled(), "precondition");
71
log_trace(gc, breakpoint)("acquire_control");
72
} else {
73
assert(is_controlled(), "precondition");
74
log_trace(gc, breakpoint)("run_to_idle");
75
}
76
reset_request_state();
77
_want_idle = true;
78
ml.notify_all();
79
while (!_is_idle) {
80
ml.wait();
81
}
82
}
83
84
void ConcurrentGCBreakpoints::acquire_control() {
85
run_to_idle_impl(true);
86
}
87
88
void ConcurrentGCBreakpoints::release_control() {
89
assert_Java_thread();
90
MonitorLocker ml(monitor());
91
log_trace(gc, breakpoint)("release_control");
92
reset_request_state();
93
ml.notify_all();
94
}
95
96
void ConcurrentGCBreakpoints::run_to_idle() {
97
run_to_idle_impl(false);
98
}
99
100
bool ConcurrentGCBreakpoints::run_to(const char* breakpoint) {
101
assert_Java_thread();
102
assert(breakpoint != NULL, "precondition");
103
104
MonitorLocker ml(monitor());
105
assert(is_controlled(), "precondition");
106
log_trace(gc, breakpoint)("run_to %s", breakpoint);
107
reset_request_state();
108
_run_to = breakpoint;
109
ml.notify_all();
110
111
if (_is_idle) {
112
log_trace(gc, breakpoint)("run_to requesting collection %s", breakpoint);
113
MutexUnlocker mul(monitor());
114
Universe::heap()->collect(GCCause::_wb_breakpoint);
115
}
116
117
// Wait for corresponding at() or a notify_idle().
118
while (true) {
119
if (_want_idle) {
120
// Completed cycle and resumed idle without hitting requested stop.
121
// That replaced our request with a run_to_idle() request.
122
log_trace(gc, breakpoint)("run_to missed %s", breakpoint);
123
return false; // Missed.
124
} else if (_is_stopped) {
125
log_trace(gc, breakpoint)("run_to stopped at %s", breakpoint);
126
return true; // Success.
127
} else {
128
ml.wait();
129
}
130
}
131
}
132
133
void ConcurrentGCBreakpoints::at(const char* breakpoint) {
134
assert(Thread::current()->is_ConcurrentGC_thread(), "precondition");
135
assert(breakpoint != NULL, "precondition");
136
MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
137
138
// Ignore non-matching request state.
139
if ((_run_to == NULL) || (strcmp(_run_to, breakpoint) != 0)) {
140
log_trace(gc, breakpoint)("unmatched breakpoint %s", breakpoint);
141
return;
142
}
143
log_trace(gc, breakpoint)("matched breakpoint %s", breakpoint);
144
145
// Notify request.
146
_run_to = NULL;
147
_is_stopped = true;
148
ml.notify_all(); // Wakeup waiting request.
149
// Wait for request to be cancelled.
150
while (_is_stopped) {
151
ml.wait();
152
}
153
log_trace(gc, breakpoint)("resumed from breakpoint");
154
}
155
156
void ConcurrentGCBreakpoints::notify_active_to_idle() {
157
MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
158
assert(!_is_stopped, "invariant");
159
// Notify pending run_to request of miss by replacing the run_to() request
160
// with a run_to_idle() request.
161
if (_run_to != NULL) {
162
log_debug(gc, breakpoint)
163
("Concurrent cycle completed without reaching breakpoint %s", _run_to);
164
_run_to = NULL;
165
_want_idle = true;
166
}
167
_is_idle = true;
168
monitor()->notify_all();
169
}
170
171
void ConcurrentGCBreakpoints::notify_idle_to_active() {
172
assert_locked_or_safepoint(monitor());
173
_is_idle = false;
174
}
175
176