author | mikael |
Thu, 08 Nov 2018 11:45:13 -0800 | |
changeset 52460 | f1bb77833b59 |
parent 52341 | 2b58b8e1d28f |
child 53775 | 5d20b085d893 |
permissions | -rw-r--r-- |
47881 | 1 |
/* |
52013
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
2 |
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. |
47881 | 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 "logging/log.hpp" |
|
27 |
#include "logging/logStream.hpp" |
|
28 |
#include "memory/resourceArea.hpp" |
|
29 |
#include "runtime/handshake.hpp" |
|
49449
ef5d5d343e2a
8199263: Split interfaceSupport.hpp to not require including .inline.hpp files
coleenp
parents:
48105
diff
changeset
|
30 |
#include "runtime/interfaceSupport.inline.hpp" |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
31 |
#include "runtime/orderAccess.hpp" |
47881 | 32 |
#include "runtime/osThread.hpp" |
50192 | 33 |
#include "runtime/semaphore.inline.hpp" |
47881 | 34 |
#include "runtime/task.hpp" |
35 |
#include "runtime/timerTrace.hpp" |
|
36 |
#include "runtime/thread.hpp" |
|
37 |
#include "runtime/vmThread.hpp" |
|
38 |
#include "utilities/formatBuffer.hpp" |
|
39 |
#include "utilities/preserveException.hpp" |
|
40 |
||
41 |
class HandshakeOperation: public StackObj { |
|
42 |
public: |
|
43 |
virtual void do_handshake(JavaThread* thread) = 0; |
|
44 |
}; |
|
45 |
||
46 |
class HandshakeThreadsOperation: public HandshakeOperation { |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
47 |
static Semaphore _done; |
47881 | 48 |
ThreadClosure* _thread_cl; |
49 |
||
50 |
public: |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
51 |
HandshakeThreadsOperation(ThreadClosure* cl) : _thread_cl(cl) {} |
47881 | 52 |
void do_handshake(JavaThread* thread); |
53 |
bool thread_has_completed() { return _done.trywait(); } |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
54 |
|
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
55 |
#ifdef ASSERT |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
56 |
void check_state() { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
57 |
assert(!_done.trywait(), "Must be zero"); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
58 |
} |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
59 |
#endif |
47881 | 60 |
}; |
61 |
||
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
62 |
Semaphore HandshakeThreadsOperation::_done(0); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
63 |
|
47881 | 64 |
class VM_Handshake: public VM_Operation { |
65 |
const jlong _handshake_timeout; |
|
66 |
public: |
|
67 |
bool evaluate_at_safepoint() const { return false; } |
|
68 |
||
69 |
bool evaluate_concurrently() const { return false; } |
|
70 |
||
71 |
protected: |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
72 |
HandshakeThreadsOperation* const _op; |
47881 | 73 |
|
74 |
VM_Handshake(HandshakeThreadsOperation* op) : |
|
51334
cc2c79d22508
8208671: Runtime, JFR, Serviceability changes to allow enabling -Wreorder
tschatzl
parents:
50921
diff
changeset
|
75 |
_handshake_timeout(TimeHelper::millis_to_counter(HandshakeTimeout)), _op(op) {} |
47881 | 76 |
|
77 |
void set_handshake(JavaThread* target) { |
|
78 |
target->set_handshake_operation(_op); |
|
79 |
} |
|
80 |
||
81 |
// This method returns true for threads completed their operation |
|
82 |
// and true for threads canceled their operation. |
|
83 |
// A cancellation can happen if the thread is exiting. |
|
84 |
bool poll_for_completed_thread() { return _op->thread_has_completed(); } |
|
85 |
||
86 |
bool handshake_has_timed_out(jlong start_time); |
|
87 |
static void handle_timeout(); |
|
88 |
}; |
|
89 |
||
90 |
bool VM_Handshake::handshake_has_timed_out(jlong start_time) { |
|
91 |
// Check if handshake operation has timed out |
|
92 |
if (_handshake_timeout > 0) { |
|
93 |
return os::elapsed_counter() >= (start_time + _handshake_timeout); |
|
94 |
} |
|
95 |
return false; |
|
96 |
} |
|
97 |
||
98 |
void VM_Handshake::handle_timeout() { |
|
99 |
LogStreamHandle(Warning, handshake) log_stream; |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
100 |
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
47881 | 101 |
if (thr->has_handshake()) { |
102 |
log_stream.print("Thread " PTR_FORMAT " has not cleared its handshake op", p2i(thr)); |
|
103 |
thr->print_thread_state_on(&log_stream); |
|
104 |
} |
|
105 |
} |
|
106 |
log_stream.flush(); |
|
107 |
fatal("Handshake operation timed out"); |
|
108 |
} |
|
109 |
||
110 |
class VM_HandshakeOneThread: public VM_Handshake { |
|
111 |
JavaThread* _target; |
|
112 |
bool _thread_alive; |
|
113 |
public: |
|
114 |
VM_HandshakeOneThread(HandshakeThreadsOperation* op, JavaThread* target) : |
|
115 |
VM_Handshake(op), _target(target), _thread_alive(false) {} |
|
116 |
||
117 |
void doit() { |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
118 |
DEBUG_ONLY(_op->check_state();) |
47881 | 119 |
TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
120 |
||
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
121 |
ThreadsListHandle tlh; |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
122 |
if (tlh.includes(_target)) { |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
123 |
set_handshake(_target); |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
124 |
_thread_alive = true; |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
125 |
} else { |
47881 | 126 |
return; |
127 |
} |
|
128 |
||
129 |
log_trace(handshake)("Thread signaled, begin processing by VMThtread"); |
|
130 |
jlong start_time = os::elapsed_counter(); |
|
131 |
do { |
|
132 |
if (handshake_has_timed_out(start_time)) { |
|
133 |
handle_timeout(); |
|
134 |
} |
|
135 |
||
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
136 |
// We need to re-think this with SMR ThreadsList. |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
137 |
// There is an assumption in the code that the Threads_lock should be |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
138 |
// locked during certain phases. |
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
139 |
{ |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
140 |
MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
141 |
_target->handshake_process_by_vmthread(); |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
142 |
} |
47881 | 143 |
} while (!poll_for_completed_thread()); |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
144 |
DEBUG_ONLY(_op->check_state();) |
47881 | 145 |
} |
146 |
||
147 |
VMOp_Type type() const { return VMOp_HandshakeOneThread; } |
|
148 |
||
149 |
bool thread_alive() const { return _thread_alive; } |
|
150 |
}; |
|
151 |
||
152 |
class VM_HandshakeAllThreads: public VM_Handshake { |
|
153 |
public: |
|
154 |
VM_HandshakeAllThreads(HandshakeThreadsOperation* op) : VM_Handshake(op) {} |
|
155 |
||
156 |
void doit() { |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
157 |
DEBUG_ONLY(_op->check_state();) |
47881 | 158 |
TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
159 |
||
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
160 |
JavaThreadIteratorWithHandle jtiwh; |
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
161 |
int number_of_threads_issued = 0; |
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
162 |
for (JavaThread *thr = jtiwh.next(); thr != NULL; thr = jtiwh.next()) { |
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
163 |
set_handshake(thr); |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
164 |
number_of_threads_issued++; |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
165 |
} |
47881 | 166 |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
167 |
if (number_of_threads_issued < 1) { |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
168 |
log_debug(handshake)("No threads to handshake."); |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
169 |
return; |
47881 | 170 |
} |
171 |
||
172 |
log_debug(handshake)("Threads signaled, begin processing blocked threads by VMThtread"); |
|
173 |
const jlong start_time = os::elapsed_counter(); |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
174 |
int number_of_threads_completed = 0; |
47881 | 175 |
do { |
176 |
// Check if handshake operation has timed out |
|
177 |
if (handshake_has_timed_out(start_time)) { |
|
178 |
handle_timeout(); |
|
179 |
} |
|
180 |
||
181 |
// Have VM thread perform the handshake operation for blocked threads. |
|
182 |
// Observing a blocked state may of course be transient but the processing is guarded |
|
183 |
// by semaphores and we optimistically begin by working on the blocked threads |
|
184 |
{ |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
185 |
// We need to re-think this with SMR ThreadsList. |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
186 |
// There is an assumption in the code that the Threads_lock should |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
187 |
// be locked during certain phases. |
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
188 |
jtiwh.rewind(); |
47881 | 189 |
MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
190 |
for (JavaThread *thr = jtiwh.next(); thr != NULL; thr = jtiwh.next()) { |
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
191 |
// A new thread on the ThreadsList will not have an operation, |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
192 |
// hence it is skipped in handshake_process_by_vmthread. |
47881 | 193 |
thr->handshake_process_by_vmthread(); |
194 |
} |
|
195 |
} |
|
196 |
||
197 |
while (poll_for_completed_thread()) { |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
198 |
// Includes canceled operations by exiting threads. |
47881 | 199 |
number_of_threads_completed++; |
200 |
} |
|
201 |
||
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
202 |
} while (number_of_threads_issued > number_of_threads_completed); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
203 |
assert(number_of_threads_issued == number_of_threads_completed, "Must be the same"); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
204 |
DEBUG_ONLY(_op->check_state();) |
47881 | 205 |
} |
206 |
||
207 |
VMOp_Type type() const { return VMOp_HandshakeAllThreads; } |
|
208 |
}; |
|
209 |
||
210 |
class VM_HandshakeFallbackOperation : public VM_Operation { |
|
211 |
ThreadClosure* _thread_cl; |
|
212 |
Thread* _target_thread; |
|
213 |
bool _all_threads; |
|
214 |
bool _thread_alive; |
|
215 |
public: |
|
216 |
VM_HandshakeFallbackOperation(ThreadClosure* cl) : |
|
217 |
_thread_cl(cl), _target_thread(NULL), _all_threads(true), _thread_alive(true) {} |
|
218 |
VM_HandshakeFallbackOperation(ThreadClosure* cl, Thread* target) : |
|
219 |
_thread_cl(cl), _target_thread(target), _all_threads(false), _thread_alive(false) {} |
|
220 |
||
221 |
void doit() { |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
222 |
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { |
47881 | 223 |
if (_all_threads || t == _target_thread) { |
224 |
if (t == _target_thread) { |
|
225 |
_thread_alive = true; |
|
226 |
} |
|
227 |
_thread_cl->do_thread(t); |
|
228 |
} |
|
229 |
} |
|
230 |
} |
|
231 |
||
232 |
VMOp_Type type() const { return VMOp_HandshakeFallback; } |
|
233 |
bool thread_alive() const { return _thread_alive; } |
|
234 |
}; |
|
235 |
||
236 |
void HandshakeThreadsOperation::do_handshake(JavaThread* thread) { |
|
237 |
ResourceMark rm; |
|
238 |
FormatBufferResource message("Operation for thread " PTR_FORMAT ", is_vm_thread: %s", |
|
239 |
p2i(thread), BOOL_TO_STR(Thread::current()->is_VM_thread())); |
|
240 |
TraceTime timer(message, TRACETIME_LOG(Debug, handshake, task)); |
|
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
241 |
|
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
242 |
// Only actually execute the operation for non terminated threads. |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
243 |
if (!thread->is_terminated()) { |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
244 |
_thread_cl->do_thread(thread); |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
245 |
} |
47881 | 246 |
|
247 |
// Use the semaphore to inform the VM thread that we have completed the operation |
|
248 |
_done.signal(); |
|
249 |
} |
|
250 |
||
251 |
void Handshake::execute(ThreadClosure* thread_cl) { |
|
252 |
if (ThreadLocalHandshakes) { |
|
253 |
HandshakeThreadsOperation cto(thread_cl); |
|
254 |
VM_HandshakeAllThreads handshake(&cto); |
|
255 |
VMThread::execute(&handshake); |
|
256 |
} else { |
|
257 |
VM_HandshakeFallbackOperation op(thread_cl); |
|
258 |
VMThread::execute(&op); |
|
259 |
} |
|
260 |
} |
|
261 |
||
262 |
bool Handshake::execute(ThreadClosure* thread_cl, JavaThread* target) { |
|
263 |
if (ThreadLocalHandshakes) { |
|
264 |
HandshakeThreadsOperation cto(thread_cl); |
|
265 |
VM_HandshakeOneThread handshake(&cto, target); |
|
266 |
VMThread::execute(&handshake); |
|
267 |
return handshake.thread_alive(); |
|
268 |
} else { |
|
269 |
VM_HandshakeFallbackOperation op(thread_cl, target); |
|
270 |
VMThread::execute(&op); |
|
271 |
return op.thread_alive(); |
|
272 |
} |
|
273 |
} |
|
274 |
||
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
275 |
HandshakeState::HandshakeState() : _operation(NULL), _semaphore(1), _thread_in_process_handshake(false) {} |
47881 | 276 |
|
277 |
void HandshakeState::set_operation(JavaThread* target, HandshakeOperation* op) { |
|
278 |
_operation = op; |
|
50921
7f462e8383f6
8206003: SafepointSynchronize with TLH: StoreStore barriers should be moved out of the loop
mdoerr
parents:
50626
diff
changeset
|
279 |
SafepointMechanism::arm_local_poll_release(target); |
47881 | 280 |
} |
281 |
||
282 |
void HandshakeState::clear_handshake(JavaThread* target) { |
|
283 |
_operation = NULL; |
|
50921
7f462e8383f6
8206003: SafepointSynchronize with TLH: StoreStore barriers should be moved out of the loop
mdoerr
parents:
50626
diff
changeset
|
284 |
SafepointMechanism::disarm_local_poll_release(target); |
47881 | 285 |
} |
286 |
||
287 |
void HandshakeState::process_self_inner(JavaThread* thread) { |
|
288 |
assert(Thread::current() == thread, "should call from thread"); |
|
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
289 |
assert(!thread->is_terminated(), "should not be a terminated thread"); |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
290 |
|
47881 | 291 |
CautiouslyPreserveExceptionMark pem(thread); |
292 |
ThreadInVMForHandshake tivm(thread); |
|
293 |
if (!_semaphore.trywait()) { |
|
50192 | 294 |
_semaphore.wait_with_safepoint_check(thread); |
47881 | 295 |
} |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
296 |
HandshakeOperation* op = OrderAccess::load_acquire(&_operation); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
297 |
if (op != NULL) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
298 |
// Disarm before execute the operation |
47881 | 299 |
clear_handshake(thread); |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
300 |
op->do_handshake(thread); |
47881 | 301 |
} |
302 |
_semaphore.signal(); |
|
303 |
} |
|
304 |
||
305 |
bool HandshakeState::vmthread_can_process_handshake(JavaThread* target) { |
|
51432
90024ea291b4
8207334: VM times out in VM_HandshakeAllThreads::doit() with RunThese30M
rehn
parents:
51334
diff
changeset
|
306 |
// SafepointSynchronize::safepoint_safe() does not consider an externally |
90024ea291b4
8207334: VM times out in VM_HandshakeAllThreads::doit() with RunThese30M
rehn
parents:
51334
diff
changeset
|
307 |
// suspended thread to be safe. However, this function must be called with |
90024ea291b4
8207334: VM times out in VM_HandshakeAllThreads::doit() with RunThese30M
rehn
parents:
51334
diff
changeset
|
308 |
// the Threads_lock held so an externally suspended thread cannot be |
90024ea291b4
8207334: VM times out in VM_HandshakeAllThreads::doit() with RunThese30M
rehn
parents:
51334
diff
changeset
|
309 |
// resumed thus it is safe. |
90024ea291b4
8207334: VM times out in VM_HandshakeAllThreads::doit() with RunThese30M
rehn
parents:
51334
diff
changeset
|
310 |
assert(Threads_lock->owned_by_self(), "Not holding Threads_lock."); |
90024ea291b4
8207334: VM times out in VM_HandshakeAllThreads::doit() with RunThese30M
rehn
parents:
51334
diff
changeset
|
311 |
return SafepointSynchronize::safepoint_safe(target, target->thread_state()) || |
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
312 |
target->is_ext_suspended() || target->is_terminated(); |
47881 | 313 |
} |
314 |
||
52013
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
315 |
static bool possibly_vmthread_can_process_handshake(JavaThread* target) { |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
316 |
// An externally suspended thread cannot be resumed while the |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
317 |
// Threads_lock is held so it is safe. |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
318 |
// Note that this method is allowed to produce false positives. |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
319 |
assert(Threads_lock->owned_by_self(), "Not holding Threads_lock."); |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
320 |
if (target->is_ext_suspended()) { |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
321 |
return true; |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
322 |
} |
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
323 |
if (target->is_terminated()) { |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
324 |
return true; |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
325 |
} |
52013
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
326 |
switch (target->thread_state()) { |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
327 |
case _thread_in_native: |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
328 |
// native threads are safe if they have no java stack or have walkable stack |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
329 |
return !target->has_last_Java_frame() || target->frame_anchor()->walkable(); |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
330 |
|
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
331 |
case _thread_blocked: |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
332 |
return true; |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
333 |
|
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
334 |
default: |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
335 |
return false; |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
336 |
} |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
337 |
} |
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
338 |
|
47881 | 339 |
bool HandshakeState::claim_handshake_for_vmthread() { |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
340 |
if (!_semaphore.trywait()) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
341 |
return false; |
47881 | 342 |
} |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
343 |
if (has_operation()) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
344 |
return true; |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
345 |
} |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
346 |
_semaphore.signal(); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
347 |
return false; |
47881 | 348 |
} |
349 |
||
350 |
void HandshakeState::process_by_vmthread(JavaThread* target) { |
|
351 |
assert(Thread::current()->is_VM_thread(), "should call from vm thread"); |
|
52341
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
352 |
// Threads_lock must be held here, but that is assert()ed in |
2b58b8e1d28f
8212933: Thread-SMR: requesting a VM operation whilst holding a ThreadsListHandle can cause deadlocks
rehn
parents:
52013
diff
changeset
|
353 |
// possibly_vmthread_can_process_handshake(). |
47881 | 354 |
|
355 |
if (!has_operation()) { |
|
356 |
// JT has already cleared its handshake |
|
357 |
return; |
|
358 |
} |
|
359 |
||
52013
92383597fa21
8210303: VM_HandshakeAllThreads fails assert with "failed: blocked and not walkable"
rehn
parents:
51432
diff
changeset
|
360 |
if (!possibly_vmthread_can_process_handshake(target)) { |
47881 | 361 |
// JT is observed in an unsafe state, it must notice the handshake itself |
362 |
return; |
|
363 |
} |
|
364 |
||
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
365 |
// Claim the semaphore if there still an operation to be executed. |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
366 |
if (!claim_handshake_for_vmthread()) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
367 |
return; |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
368 |
} |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
369 |
|
47881 | 370 |
// If we own the semaphore at this point and while owning the semaphore |
371 |
// can observe a safe state the thread cannot possibly continue without |
|
372 |
// getting caught by the semaphore. |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
373 |
if (vmthread_can_process_handshake(target)) { |
47881 | 374 |
guarantee(!_semaphore.trywait(), "we should already own the semaphore"); |
375 |
_operation->do_handshake(target); |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
376 |
// Disarm after VM thread have executed the operation. |
47881 | 377 |
clear_handshake(target); |
378 |
// Release the thread |
|
379 |
} |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
380 |
|
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
381 |
_semaphore.signal(); |
47881 | 382 |
} |