26 #include "logging/log.hpp" |
26 #include "logging/log.hpp" |
27 #include "logging/logStream.hpp" |
27 #include "logging/logStream.hpp" |
28 #include "memory/resourceArea.hpp" |
28 #include "memory/resourceArea.hpp" |
29 #include "runtime/handshake.hpp" |
29 #include "runtime/handshake.hpp" |
30 #include "runtime/interfaceSupport.inline.hpp" |
30 #include "runtime/interfaceSupport.inline.hpp" |
|
31 #include "runtime/orderAccess.hpp" |
31 #include "runtime/osThread.hpp" |
32 #include "runtime/osThread.hpp" |
32 #include "runtime/semaphore.inline.hpp" |
33 #include "runtime/semaphore.inline.hpp" |
33 #include "runtime/task.hpp" |
34 #include "runtime/task.hpp" |
34 #include "runtime/timerTrace.hpp" |
35 #include "runtime/timerTrace.hpp" |
35 #include "runtime/thread.hpp" |
36 #include "runtime/thread.hpp" |
42 virtual void do_handshake(JavaThread* thread) = 0; |
43 virtual void do_handshake(JavaThread* thread) = 0; |
43 virtual void cancel_handshake(JavaThread* thread) = 0; |
44 virtual void cancel_handshake(JavaThread* thread) = 0; |
44 }; |
45 }; |
45 |
46 |
46 class HandshakeThreadsOperation: public HandshakeOperation { |
47 class HandshakeThreadsOperation: public HandshakeOperation { |
47 Semaphore _done; |
48 static Semaphore _done; |
48 ThreadClosure* _thread_cl; |
49 ThreadClosure* _thread_cl; |
49 |
50 |
50 public: |
51 public: |
51 HandshakeThreadsOperation(ThreadClosure* cl) : _done(0), _thread_cl(cl) {} |
52 HandshakeThreadsOperation(ThreadClosure* cl) : _thread_cl(cl) {} |
52 void do_handshake(JavaThread* thread); |
53 void do_handshake(JavaThread* thread); |
53 void cancel_handshake(JavaThread* thread) { _done.signal(); }; |
54 void cancel_handshake(JavaThread* thread) { _done.signal(); }; |
54 |
55 |
55 bool thread_has_completed() { return _done.trywait(); } |
56 bool thread_has_completed() { return _done.trywait(); } |
56 }; |
57 |
|
58 #ifdef ASSERT |
|
59 void check_state() { |
|
60 assert(!_done.trywait(), "Must be zero"); |
|
61 } |
|
62 #endif |
|
63 }; |
|
64 |
|
65 Semaphore HandshakeThreadsOperation::_done(0); |
57 |
66 |
58 class VM_Handshake: public VM_Operation { |
67 class VM_Handshake: public VM_Operation { |
59 HandshakeThreadsOperation* const _op; |
|
60 const jlong _handshake_timeout; |
68 const jlong _handshake_timeout; |
61 public: |
69 public: |
62 bool evaluate_at_safepoint() const { return false; } |
70 bool evaluate_at_safepoint() const { return false; } |
63 |
71 |
64 bool evaluate_concurrently() const { return false; } |
72 bool evaluate_concurrently() const { return false; } |
65 |
73 |
66 protected: |
74 protected: |
|
75 HandshakeThreadsOperation* const _op; |
67 |
76 |
68 VM_Handshake(HandshakeThreadsOperation* op) : |
77 VM_Handshake(HandshakeThreadsOperation* op) : |
69 _op(op), |
78 _op(op), |
70 _handshake_timeout(TimeHelper::millis_to_counter(HandshakeTimeout)) {} |
79 _handshake_timeout(TimeHelper::millis_to_counter(HandshakeTimeout)) {} |
71 |
80 |
100 } |
109 } |
101 log_stream.flush(); |
110 log_stream.flush(); |
102 fatal("Handshake operation timed out"); |
111 fatal("Handshake operation timed out"); |
103 } |
112 } |
104 |
113 |
105 |
|
106 class VM_HandshakeOneThread: public VM_Handshake { |
114 class VM_HandshakeOneThread: public VM_Handshake { |
107 JavaThread* _target; |
115 JavaThread* _target; |
108 bool _thread_alive; |
116 bool _thread_alive; |
109 public: |
117 public: |
110 VM_HandshakeOneThread(HandshakeThreadsOperation* op, JavaThread* target) : |
118 VM_HandshakeOneThread(HandshakeThreadsOperation* op, JavaThread* target) : |
111 VM_Handshake(op), _target(target), _thread_alive(false) {} |
119 VM_Handshake(op), _target(target), _thread_alive(false) {} |
112 |
120 |
113 void doit() { |
121 void doit() { |
|
122 DEBUG_ONLY(_op->check_state();) |
114 TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
123 TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
115 |
124 |
116 { |
125 { |
117 ThreadsListHandle tlh; |
126 ThreadsListHandle tlh; |
118 if (tlh.includes(_target)) { |
127 if (tlh.includes(_target)) { |
153 // it has been removed from the ThreadsList. So we should just keep |
162 // it has been removed from the ThreadsList. So we should just keep |
154 // looping here until while below returns false. If we have a bug, |
163 // looping here until while below returns false. If we have a bug, |
155 // then we hang here, which is good for debugging. |
164 // then we hang here, which is good for debugging. |
156 } |
165 } |
157 } while (!poll_for_completed_thread()); |
166 } while (!poll_for_completed_thread()); |
|
167 DEBUG_ONLY(_op->check_state();) |
158 } |
168 } |
159 |
169 |
160 VMOp_Type type() const { return VMOp_HandshakeOneThread; } |
170 VMOp_Type type() const { return VMOp_HandshakeOneThread; } |
161 |
171 |
162 bool thread_alive() const { return _thread_alive; } |
172 bool thread_alive() const { return _thread_alive; } |
165 class VM_HandshakeAllThreads: public VM_Handshake { |
175 class VM_HandshakeAllThreads: public VM_Handshake { |
166 public: |
176 public: |
167 VM_HandshakeAllThreads(HandshakeThreadsOperation* op) : VM_Handshake(op) {} |
177 VM_HandshakeAllThreads(HandshakeThreadsOperation* op) : VM_Handshake(op) {} |
168 |
178 |
169 void doit() { |
179 void doit() { |
|
180 DEBUG_ONLY(_op->check_state();) |
170 TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
181 TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
171 |
182 |
172 int number_of_threads_issued = 0; |
183 int number_of_threads_issued = 0; |
173 for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
184 for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
174 set_handshake(thr); |
185 set_handshake(thr); |
211 while (poll_for_completed_thread()) { |
222 while (poll_for_completed_thread()) { |
212 // Includes canceled operations by exiting threads. |
223 // Includes canceled operations by exiting threads. |
213 number_of_threads_completed++; |
224 number_of_threads_completed++; |
214 } |
225 } |
215 |
226 |
216 } while (number_of_threads_issued != number_of_threads_completed); |
227 } while (number_of_threads_issued > number_of_threads_completed); |
|
228 assert(number_of_threads_issued == number_of_threads_completed, "Must be the same"); |
|
229 DEBUG_ONLY(_op->check_state();) |
217 } |
230 } |
218 |
231 |
219 VMOp_Type type() const { return VMOp_HandshakeAllThreads; } |
232 VMOp_Type type() const { return VMOp_HandshakeAllThreads; } |
220 }; |
233 }; |
221 |
234 |
243 |
256 |
244 VMOp_Type type() const { return VMOp_HandshakeFallback; } |
257 VMOp_Type type() const { return VMOp_HandshakeFallback; } |
245 bool thread_alive() const { return _thread_alive; } |
258 bool thread_alive() const { return _thread_alive; } |
246 }; |
259 }; |
247 |
260 |
248 #undef ALL_JAVA_THREADS |
|
249 |
|
250 void HandshakeThreadsOperation::do_handshake(JavaThread* thread) { |
261 void HandshakeThreadsOperation::do_handshake(JavaThread* thread) { |
251 ResourceMark rm; |
262 ResourceMark rm; |
252 FormatBufferResource message("Operation for thread " PTR_FORMAT ", is_vm_thread: %s", |
263 FormatBufferResource message("Operation for thread " PTR_FORMAT ", is_vm_thread: %s", |
253 p2i(thread), BOOL_TO_STR(Thread::current()->is_VM_thread())); |
264 p2i(thread), BOOL_TO_STR(Thread::current()->is_VM_thread())); |
254 TraceTime timer(message, TRACETIME_LOG(Debug, handshake, task)); |
265 TraceTime timer(message, TRACETIME_LOG(Debug, handshake, task)); |
280 VMThread::execute(&op); |
291 VMThread::execute(&op); |
281 return op.thread_alive(); |
292 return op.thread_alive(); |
282 } |
293 } |
283 } |
294 } |
284 |
295 |
285 HandshakeState::HandshakeState() : _operation(NULL), _semaphore(1), _vmthread_holds_semaphore(false), _thread_in_process_handshake(false) {} |
296 HandshakeState::HandshakeState() : _operation(NULL), _semaphore(1), _thread_in_process_handshake(false) {} |
286 |
297 |
287 void HandshakeState::set_operation(JavaThread* target, HandshakeOperation* op) { |
298 void HandshakeState::set_operation(JavaThread* target, HandshakeOperation* op) { |
288 _operation = op; |
299 _operation = op; |
289 SafepointMechanism::arm_local_poll(target); |
300 SafepointMechanism::arm_local_poll(target); |
290 } |
301 } |
294 SafepointMechanism::disarm_local_poll(target); |
305 SafepointMechanism::disarm_local_poll(target); |
295 } |
306 } |
296 |
307 |
297 void HandshakeState::process_self_inner(JavaThread* thread) { |
308 void HandshakeState::process_self_inner(JavaThread* thread) { |
298 assert(Thread::current() == thread, "should call from thread"); |
309 assert(Thread::current() == thread, "should call from thread"); |
|
310 |
|
311 if (thread->is_terminated()) { |
|
312 // If thread is not on threads list but armed, cancel. |
|
313 thread->cancel_handshake(); |
|
314 return; |
|
315 } |
|
316 |
299 CautiouslyPreserveExceptionMark pem(thread); |
317 CautiouslyPreserveExceptionMark pem(thread); |
300 ThreadInVMForHandshake tivm(thread); |
318 ThreadInVMForHandshake tivm(thread); |
301 if (!_semaphore.trywait()) { |
319 if (!_semaphore.trywait()) { |
302 _semaphore.wait_with_safepoint_check(thread); |
320 _semaphore.wait_with_safepoint_check(thread); |
303 } |
321 } |
304 if (has_operation()) { |
322 HandshakeOperation* op = OrderAccess::load_acquire(&_operation); |
305 HandshakeOperation* op = _operation; |
323 if (op != NULL) { |
|
324 // Disarm before execute the operation |
306 clear_handshake(thread); |
325 clear_handshake(thread); |
307 if (op != NULL) { |
326 op->do_handshake(thread); |
308 op->do_handshake(thread); |
|
309 } |
|
310 } |
327 } |
311 _semaphore.signal(); |
328 _semaphore.signal(); |
312 } |
329 } |
313 |
330 |
314 void HandshakeState::cancel_inner(JavaThread* thread) { |
331 void HandshakeState::cancel_inner(JavaThread* thread) { |
315 assert(Thread::current() == thread, "should call from thread"); |
332 assert(Thread::current() == thread, "should call from thread"); |
316 assert(thread->thread_state() == _thread_in_vm, "must be in vm state"); |
333 assert(thread->thread_state() == _thread_in_vm, "must be in vm state"); |
317 #ifdef DEBUG |
|
318 { |
|
319 ThreadsListHandle tlh; |
|
320 assert(!tlh.includes(_target), "java thread must not be on threads list"); |
|
321 } |
|
322 #endif |
|
323 HandshakeOperation* op = _operation; |
334 HandshakeOperation* op = _operation; |
324 clear_handshake(thread); |
335 clear_handshake(thread); |
325 if (op != NULL) { |
336 if (op != NULL) { |
326 op->cancel_handshake(thread); |
337 op->cancel_handshake(thread); |
327 } |
338 } |
330 bool HandshakeState::vmthread_can_process_handshake(JavaThread* target) { |
341 bool HandshakeState::vmthread_can_process_handshake(JavaThread* target) { |
331 return SafepointSynchronize::safepoint_safe(target, target->thread_state()); |
342 return SafepointSynchronize::safepoint_safe(target, target->thread_state()); |
332 } |
343 } |
333 |
344 |
334 bool HandshakeState::claim_handshake_for_vmthread() { |
345 bool HandshakeState::claim_handshake_for_vmthread() { |
335 if (_semaphore.trywait()) { |
346 if (!_semaphore.trywait()) { |
336 if (has_operation()) { |
347 return false; |
337 _vmthread_holds_semaphore = true; |
348 } |
338 } else { |
349 if (has_operation()) { |
339 _semaphore.signal(); |
350 return true; |
340 } |
351 } |
341 } |
352 _semaphore.signal(); |
342 return _vmthread_holds_semaphore; |
353 return false; |
343 } |
354 } |
344 |
355 |
345 void HandshakeState::process_by_vmthread(JavaThread* target) { |
356 void HandshakeState::process_by_vmthread(JavaThread* target) { |
346 assert(Thread::current()->is_VM_thread(), "should call from vm thread"); |
357 assert(Thread::current()->is_VM_thread(), "should call from vm thread"); |
347 |
358 |
353 if (!vmthread_can_process_handshake(target)) { |
364 if (!vmthread_can_process_handshake(target)) { |
354 // JT is observed in an unsafe state, it must notice the handshake itself |
365 // JT is observed in an unsafe state, it must notice the handshake itself |
355 return; |
366 return; |
356 } |
367 } |
357 |
368 |
|
369 // Claim the semaphore if there still an operation to be executed. |
|
370 if (!claim_handshake_for_vmthread()) { |
|
371 return; |
|
372 } |
|
373 |
358 // If we own the semaphore at this point and while owning the semaphore |
374 // If we own the semaphore at this point and while owning the semaphore |
359 // can observe a safe state the thread cannot possibly continue without |
375 // can observe a safe state the thread cannot possibly continue without |
360 // getting caught by the semaphore. |
376 // getting caught by the semaphore. |
361 if (claim_handshake_for_vmthread() && vmthread_can_process_handshake(target)) { |
377 if (vmthread_can_process_handshake(target)) { |
362 guarantee(!_semaphore.trywait(), "we should already own the semaphore"); |
378 guarantee(!_semaphore.trywait(), "we should already own the semaphore"); |
363 |
379 |
364 _operation->do_handshake(target); |
380 _operation->do_handshake(target); |
|
381 // Disarm after VM thread have executed the operation. |
365 clear_handshake(target); |
382 clear_handshake(target); |
366 _vmthread_holds_semaphore = false; |
|
367 // Release the thread |
383 // Release the thread |
368 _semaphore.signal(); |
384 } |
369 } |
385 |
370 } |
386 _semaphore.signal(); |
|
387 } |