author | tschatzl |
Wed, 08 Aug 2018 15:31:07 +0200 | |
changeset 51334 | cc2c79d22508 |
parent 50921 | 7f462e8383f6 |
child 51432 | 90024ea291b4 |
permissions | -rw-r--r-- |
47881 | 1 |
/* |
2 |
* Copyright (c) 2017, 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 "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 |
virtual void cancel_handshake(JavaThread* thread) = 0; |
|
45 |
}; |
|
46 |
||
47 |
class HandshakeThreadsOperation: public HandshakeOperation { |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
48 |
static Semaphore _done; |
47881 | 49 |
ThreadClosure* _thread_cl; |
50 |
||
51 |
public: |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
52 |
HandshakeThreadsOperation(ThreadClosure* cl) : _thread_cl(cl) {} |
47881 | 53 |
void do_handshake(JavaThread* thread); |
54 |
void cancel_handshake(JavaThread* thread) { _done.signal(); }; |
|
55 |
||
56 |
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
|
57 |
|
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
58 |
#ifdef ASSERT |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
59 |
void check_state() { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
60 |
assert(!_done.trywait(), "Must be zero"); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
61 |
} |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
62 |
#endif |
47881 | 63 |
}; |
64 |
||
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
65 |
Semaphore HandshakeThreadsOperation::_done(0); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
66 |
|
47881 | 67 |
class VM_Handshake: public VM_Operation { |
68 |
const jlong _handshake_timeout; |
|
69 |
public: |
|
70 |
bool evaluate_at_safepoint() const { return false; } |
|
71 |
||
72 |
bool evaluate_concurrently() const { return false; } |
|
73 |
||
74 |
protected: |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
75 |
HandshakeThreadsOperation* const _op; |
47881 | 76 |
|
77 |
VM_Handshake(HandshakeThreadsOperation* op) : |
|
51334
cc2c79d22508
8208671: Runtime, JFR, Serviceability changes to allow enabling -Wreorder
tschatzl
parents:
50921
diff
changeset
|
78 |
_handshake_timeout(TimeHelper::millis_to_counter(HandshakeTimeout)), _op(op) {} |
47881 | 79 |
|
80 |
void set_handshake(JavaThread* target) { |
|
81 |
target->set_handshake_operation(_op); |
|
82 |
} |
|
83 |
||
84 |
// This method returns true for threads completed their operation |
|
85 |
// and true for threads canceled their operation. |
|
86 |
// A cancellation can happen if the thread is exiting. |
|
87 |
bool poll_for_completed_thread() { return _op->thread_has_completed(); } |
|
88 |
||
89 |
bool handshake_has_timed_out(jlong start_time); |
|
90 |
static void handle_timeout(); |
|
91 |
}; |
|
92 |
||
93 |
bool VM_Handshake::handshake_has_timed_out(jlong start_time) { |
|
94 |
// Check if handshake operation has timed out |
|
95 |
if (_handshake_timeout > 0) { |
|
96 |
return os::elapsed_counter() >= (start_time + _handshake_timeout); |
|
97 |
} |
|
98 |
return false; |
|
99 |
} |
|
100 |
||
101 |
void VM_Handshake::handle_timeout() { |
|
102 |
LogStreamHandle(Warning, handshake) log_stream; |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
103 |
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
47881 | 104 |
if (thr->has_handshake()) { |
105 |
log_stream.print("Thread " PTR_FORMAT " has not cleared its handshake op", p2i(thr)); |
|
106 |
thr->print_thread_state_on(&log_stream); |
|
107 |
} |
|
108 |
} |
|
109 |
log_stream.flush(); |
|
110 |
fatal("Handshake operation timed out"); |
|
111 |
} |
|
112 |
||
113 |
class VM_HandshakeOneThread: public VM_Handshake { |
|
114 |
JavaThread* _target; |
|
115 |
bool _thread_alive; |
|
116 |
public: |
|
117 |
VM_HandshakeOneThread(HandshakeThreadsOperation* op, JavaThread* target) : |
|
118 |
VM_Handshake(op), _target(target), _thread_alive(false) {} |
|
119 |
||
120 |
void doit() { |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
121 |
DEBUG_ONLY(_op->check_state();) |
47881 | 122 |
TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
123 |
||
124 |
{ |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
125 |
ThreadsListHandle tlh; |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
126 |
if (tlh.includes(_target)) { |
47881 | 127 |
set_handshake(_target); |
128 |
_thread_alive = true; |
|
129 |
} |
|
130 |
} |
|
131 |
||
132 |
if (!_thread_alive) { |
|
133 |
return; |
|
134 |
} |
|
135 |
||
136 |
if (!UseMembar) { |
|
137 |
os::serialize_thread_states(); |
|
138 |
} |
|
139 |
||
140 |
log_trace(handshake)("Thread signaled, begin processing by VMThtread"); |
|
141 |
jlong start_time = os::elapsed_counter(); |
|
142 |
do { |
|
143 |
if (handshake_has_timed_out(start_time)) { |
|
144 |
handle_timeout(); |
|
145 |
} |
|
146 |
||
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
147 |
// 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
|
148 |
// 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
|
149 |
// locked during certain phases. |
47881 | 150 |
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
|
151 |
ThreadsListHandle tlh; |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
152 |
if (tlh.includes(_target)) { |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
153 |
// Warning _target's address might be re-used. |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
154 |
// handshake_process_by_vmthread will check the semaphore for us again. |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
155 |
// Since we can't have more then one handshake in flight a reuse of |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
156 |
// _target's address should be okay since the new thread will not have |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
157 |
// an operation. |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
158 |
_target->handshake_process_by_vmthread(); |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
159 |
} else { |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
160 |
// We can't warn here since the thread does cancel_handshake after |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
161 |
// it has been removed from the ThreadsList. So we should just keep |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
162 |
// looping here until while below returns false. If we have a bug, |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
163 |
// then we hang here, which is good for debugging. |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
164 |
} |
47881 | 165 |
} while (!poll_for_completed_thread()); |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
166 |
DEBUG_ONLY(_op->check_state();) |
47881 | 167 |
} |
168 |
||
169 |
VMOp_Type type() const { return VMOp_HandshakeOneThread; } |
|
170 |
||
171 |
bool thread_alive() const { return _thread_alive; } |
|
172 |
}; |
|
173 |
||
174 |
class VM_HandshakeAllThreads: public VM_Handshake { |
|
175 |
public: |
|
176 |
VM_HandshakeAllThreads(HandshakeThreadsOperation* op) : VM_Handshake(op) {} |
|
177 |
||
178 |
void doit() { |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
179 |
DEBUG_ONLY(_op->check_state();) |
47881 | 180 |
TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
181 |
||
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
182 |
int number_of_threads_issued = 0; |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
183 |
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
184 |
set_handshake(thr); |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
185 |
number_of_threads_issued++; |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
186 |
} |
47881 | 187 |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
188 |
if (number_of_threads_issued < 1) { |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
189 |
log_debug(handshake)("No threads to handshake."); |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
190 |
return; |
47881 | 191 |
} |
192 |
||
193 |
if (!UseMembar) { |
|
194 |
os::serialize_thread_states(); |
|
195 |
} |
|
196 |
||
197 |
log_debug(handshake)("Threads signaled, begin processing blocked threads by VMThtread"); |
|
198 |
const jlong start_time = os::elapsed_counter(); |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
199 |
int number_of_threads_completed = 0; |
47881 | 200 |
do { |
201 |
// Check if handshake operation has timed out |
|
202 |
if (handshake_has_timed_out(start_time)) { |
|
203 |
handle_timeout(); |
|
204 |
} |
|
205 |
||
206 |
// Have VM thread perform the handshake operation for blocked threads. |
|
207 |
// Observing a blocked state may of course be transient but the processing is guarded |
|
208 |
// by semaphores and we optimistically begin by working on the blocked threads |
|
209 |
{ |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
210 |
// 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
|
211 |
// 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
|
212 |
// be locked during certain phases. |
47881 | 213 |
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
|
214 |
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
215 |
// 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
|
216 |
// hence it is skipped in handshake_process_by_vmthread. |
47881 | 217 |
thr->handshake_process_by_vmthread(); |
218 |
} |
|
219 |
} |
|
220 |
||
221 |
while (poll_for_completed_thread()) { |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
222 |
// Includes canceled operations by exiting threads. |
47881 | 223 |
number_of_threads_completed++; |
224 |
} |
|
225 |
||
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
226 |
} 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
|
227 |
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
|
228 |
DEBUG_ONLY(_op->check_state();) |
47881 | 229 |
} |
230 |
||
231 |
VMOp_Type type() const { return VMOp_HandshakeAllThreads; } |
|
232 |
}; |
|
233 |
||
234 |
class VM_HandshakeFallbackOperation : public VM_Operation { |
|
235 |
ThreadClosure* _thread_cl; |
|
236 |
Thread* _target_thread; |
|
237 |
bool _all_threads; |
|
238 |
bool _thread_alive; |
|
239 |
public: |
|
240 |
VM_HandshakeFallbackOperation(ThreadClosure* cl) : |
|
241 |
_thread_cl(cl), _target_thread(NULL), _all_threads(true), _thread_alive(true) {} |
|
242 |
VM_HandshakeFallbackOperation(ThreadClosure* cl, Thread* target) : |
|
243 |
_thread_cl(cl), _target_thread(target), _all_threads(false), _thread_alive(false) {} |
|
244 |
||
245 |
void doit() { |
|
48105
8d15b1369c7a
8167108: inconsistent handling of SR_lock can lead to crashes
dcubed
parents:
47881
diff
changeset
|
246 |
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { |
47881 | 247 |
if (_all_threads || t == _target_thread) { |
248 |
if (t == _target_thread) { |
|
249 |
_thread_alive = true; |
|
250 |
} |
|
251 |
_thread_cl->do_thread(t); |
|
252 |
} |
|
253 |
} |
|
254 |
} |
|
255 |
||
256 |
VMOp_Type type() const { return VMOp_HandshakeFallback; } |
|
257 |
bool thread_alive() const { return _thread_alive; } |
|
258 |
}; |
|
259 |
||
260 |
void HandshakeThreadsOperation::do_handshake(JavaThread* thread) { |
|
261 |
ResourceMark rm; |
|
262 |
FormatBufferResource message("Operation for thread " PTR_FORMAT ", is_vm_thread: %s", |
|
263 |
p2i(thread), BOOL_TO_STR(Thread::current()->is_VM_thread())); |
|
264 |
TraceTime timer(message, TRACETIME_LOG(Debug, handshake, task)); |
|
265 |
_thread_cl->do_thread(thread); |
|
266 |
||
267 |
// Use the semaphore to inform the VM thread that we have completed the operation |
|
268 |
_done.signal(); |
|
269 |
} |
|
270 |
||
271 |
void Handshake::execute(ThreadClosure* thread_cl) { |
|
272 |
if (ThreadLocalHandshakes) { |
|
273 |
HandshakeThreadsOperation cto(thread_cl); |
|
274 |
VM_HandshakeAllThreads handshake(&cto); |
|
275 |
VMThread::execute(&handshake); |
|
276 |
} else { |
|
277 |
VM_HandshakeFallbackOperation op(thread_cl); |
|
278 |
VMThread::execute(&op); |
|
279 |
} |
|
280 |
} |
|
281 |
||
282 |
bool Handshake::execute(ThreadClosure* thread_cl, JavaThread* target) { |
|
283 |
if (ThreadLocalHandshakes) { |
|
284 |
HandshakeThreadsOperation cto(thread_cl); |
|
285 |
VM_HandshakeOneThread handshake(&cto, target); |
|
286 |
VMThread::execute(&handshake); |
|
287 |
return handshake.thread_alive(); |
|
288 |
} else { |
|
289 |
VM_HandshakeFallbackOperation op(thread_cl, target); |
|
290 |
VMThread::execute(&op); |
|
291 |
return op.thread_alive(); |
|
292 |
} |
|
293 |
} |
|
294 |
||
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
295 |
HandshakeState::HandshakeState() : _operation(NULL), _semaphore(1), _thread_in_process_handshake(false) {} |
47881 | 296 |
|
297 |
void HandshakeState::set_operation(JavaThread* target, HandshakeOperation* op) { |
|
298 |
_operation = op; |
|
50921
7f462e8383f6
8206003: SafepointSynchronize with TLH: StoreStore barriers should be moved out of the loop
mdoerr
parents:
50626
diff
changeset
|
299 |
SafepointMechanism::arm_local_poll_release(target); |
47881 | 300 |
} |
301 |
||
302 |
void HandshakeState::clear_handshake(JavaThread* target) { |
|
303 |
_operation = NULL; |
|
50921
7f462e8383f6
8206003: SafepointSynchronize with TLH: StoreStore barriers should be moved out of the loop
mdoerr
parents:
50626
diff
changeset
|
304 |
SafepointMechanism::disarm_local_poll_release(target); |
47881 | 305 |
} |
306 |
||
307 |
void HandshakeState::process_self_inner(JavaThread* thread) { |
|
308 |
assert(Thread::current() == thread, "should call from thread"); |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
309 |
|
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
310 |
if (thread->is_terminated()) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
311 |
// If thread is not on threads list but armed, cancel. |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
312 |
thread->cancel_handshake(); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
313 |
return; |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
314 |
} |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
315 |
|
47881 | 316 |
CautiouslyPreserveExceptionMark pem(thread); |
317 |
ThreadInVMForHandshake tivm(thread); |
|
318 |
if (!_semaphore.trywait()) { |
|
50192 | 319 |
_semaphore.wait_with_safepoint_check(thread); |
47881 | 320 |
} |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
321 |
HandshakeOperation* op = OrderAccess::load_acquire(&_operation); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
322 |
if (op != NULL) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
323 |
// Disarm before execute the operation |
47881 | 324 |
clear_handshake(thread); |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
325 |
op->do_handshake(thread); |
47881 | 326 |
} |
327 |
_semaphore.signal(); |
|
328 |
} |
|
329 |
||
330 |
void HandshakeState::cancel_inner(JavaThread* thread) { |
|
331 |
assert(Thread::current() == thread, "should call from thread"); |
|
332 |
assert(thread->thread_state() == _thread_in_vm, "must be in vm state"); |
|
333 |
HandshakeOperation* op = _operation; |
|
334 |
clear_handshake(thread); |
|
335 |
if (op != NULL) { |
|
336 |
op->cancel_handshake(thread); |
|
337 |
} |
|
338 |
} |
|
339 |
||
340 |
bool HandshakeState::vmthread_can_process_handshake(JavaThread* target) { |
|
341 |
return SafepointSynchronize::safepoint_safe(target, target->thread_state()); |
|
342 |
} |
|
343 |
||
344 |
bool HandshakeState::claim_handshake_for_vmthread() { |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
345 |
if (!_semaphore.trywait()) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
346 |
return false; |
47881 | 347 |
} |
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
348 |
if (has_operation()) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
349 |
return true; |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
350 |
} |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
351 |
_semaphore.signal(); |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
352 |
return false; |
47881 | 353 |
} |
354 |
||
355 |
void HandshakeState::process_by_vmthread(JavaThread* target) { |
|
356 |
assert(Thread::current()->is_VM_thread(), "should call from vm thread"); |
|
357 |
||
358 |
if (!has_operation()) { |
|
359 |
// JT has already cleared its handshake |
|
360 |
return; |
|
361 |
} |
|
362 |
||
363 |
if (!vmthread_can_process_handshake(target)) { |
|
364 |
// JT is observed in an unsafe state, it must notice the handshake itself |
|
365 |
return; |
|
366 |
} |
|
367 |
||
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
368 |
// 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
|
369 |
if (!claim_handshake_for_vmthread()) { |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
370 |
return; |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
371 |
} |
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
372 |
|
47881 | 373 |
// If we own the semaphore at this point and while owning the semaphore |
374 |
// can observe a safe state the thread cannot possibly continue without |
|
375 |
// getting caught by the semaphore. |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
376 |
if (vmthread_can_process_handshake(target)) { |
47881 | 377 |
guarantee(!_semaphore.trywait(), "we should already own the semaphore"); |
378 |
||
379 |
_operation->do_handshake(target); |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
380 |
// Disarm after VM thread have executed the operation. |
47881 | 381 |
clear_handshake(target); |
382 |
// Release the thread |
|
383 |
} |
|
50626
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
384 |
|
9fdfe5ca0e5e
8204166: TLH: Semaphore may not be destroy until signal have returned.
rehn
parents:
50192
diff
changeset
|
385 |
_semaphore.signal(); |
47881 | 386 |
} |