35 #include "runtime/thread.hpp" |
35 #include "runtime/thread.hpp" |
36 #include "runtime/vmThread.hpp" |
36 #include "runtime/vmThread.hpp" |
37 #include "utilities/formatBuffer.hpp" |
37 #include "utilities/formatBuffer.hpp" |
38 #include "utilities/preserveException.hpp" |
38 #include "utilities/preserveException.hpp" |
39 |
39 |
40 #define ALL_JAVA_THREADS(X) for (JavaThread* X = Threads::first(); X; X = X->next()) |
|
41 |
|
42 class HandshakeOperation: public StackObj { |
40 class HandshakeOperation: public StackObj { |
43 public: |
41 public: |
44 virtual void do_handshake(JavaThread* thread) = 0; |
42 virtual void do_handshake(JavaThread* thread) = 0; |
45 virtual void cancel_handshake(JavaThread* thread) = 0; |
43 virtual void cancel_handshake(JavaThread* thread) = 0; |
46 }; |
44 }; |
92 return false; |
90 return false; |
93 } |
91 } |
94 |
92 |
95 void VM_Handshake::handle_timeout() { |
93 void VM_Handshake::handle_timeout() { |
96 LogStreamHandle(Warning, handshake) log_stream; |
94 LogStreamHandle(Warning, handshake) log_stream; |
97 MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
95 for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
98 ALL_JAVA_THREADS(thr) { |
|
99 if (thr->has_handshake()) { |
96 if (thr->has_handshake()) { |
100 log_stream.print("Thread " PTR_FORMAT " has not cleared its handshake op", p2i(thr)); |
97 log_stream.print("Thread " PTR_FORMAT " has not cleared its handshake op", p2i(thr)); |
101 thr->print_thread_state_on(&log_stream); |
98 thr->print_thread_state_on(&log_stream); |
102 } |
99 } |
103 } |
100 } |
115 |
112 |
116 void doit() { |
113 void doit() { |
117 TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
114 TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
118 |
115 |
119 { |
116 { |
120 MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
117 ThreadsListHandle tlh; |
121 if (Threads::includes(_target)) { |
118 if (tlh.includes(_target)) { |
122 set_handshake(_target); |
119 set_handshake(_target); |
123 _thread_alive = true; |
120 _thread_alive = true; |
124 } |
121 } |
125 } |
122 } |
126 |
123 |
137 do { |
134 do { |
138 if (handshake_has_timed_out(start_time)) { |
135 if (handshake_has_timed_out(start_time)) { |
139 handle_timeout(); |
136 handle_timeout(); |
140 } |
137 } |
141 |
138 |
|
139 // We need to re-think this with SMR ThreadsList. |
|
140 // There is an assumption in the code that the Threads_lock should be |
|
141 // locked during certain phases. |
142 MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
142 MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
143 _target->handshake_process_by_vmthread(); |
143 ThreadsListHandle tlh; |
144 |
144 if (tlh.includes(_target)) { |
|
145 // Warning _target's address might be re-used. |
|
146 // handshake_process_by_vmthread will check the semaphore for us again. |
|
147 // Since we can't have more then one handshake in flight a reuse of |
|
148 // _target's address should be okay since the new thread will not have |
|
149 // an operation. |
|
150 _target->handshake_process_by_vmthread(); |
|
151 } else { |
|
152 // We can't warn here since the thread does cancel_handshake after |
|
153 // 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, |
|
155 // then we hang here, which is good for debugging. |
|
156 } |
145 } while (!poll_for_completed_thread()); |
157 } while (!poll_for_completed_thread()); |
146 } |
158 } |
147 |
159 |
148 VMOp_Type type() const { return VMOp_HandshakeOneThread; } |
160 VMOp_Type type() const { return VMOp_HandshakeOneThread; } |
149 |
161 |
155 VM_HandshakeAllThreads(HandshakeThreadsOperation* op) : VM_Handshake(op) {} |
167 VM_HandshakeAllThreads(HandshakeThreadsOperation* op) : VM_Handshake(op) {} |
156 |
168 |
157 void doit() { |
169 void doit() { |
158 TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
170 TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake)); |
159 |
171 |
160 int number_of_threads_issued = -1; |
172 int number_of_threads_issued = 0; |
161 int number_of_threads_completed = 0; |
173 for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
162 { |
174 set_handshake(thr); |
163 MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
175 number_of_threads_issued++; |
164 number_of_threads_issued = Threads::number_of_threads(); |
176 } |
165 |
177 |
166 ALL_JAVA_THREADS(thr) { |
178 if (number_of_threads_issued < 1) { |
167 set_handshake(thr); |
179 log_debug(handshake)("No threads to handshake."); |
168 } |
180 return; |
169 } |
181 } |
170 |
182 |
171 if (!UseMembar) { |
183 if (!UseMembar) { |
172 os::serialize_thread_states(); |
184 os::serialize_thread_states(); |
173 } |
185 } |
174 |
186 |
175 log_debug(handshake)("Threads signaled, begin processing blocked threads by VMThtread"); |
187 log_debug(handshake)("Threads signaled, begin processing blocked threads by VMThtread"); |
176 const jlong start_time = os::elapsed_counter(); |
188 const jlong start_time = os::elapsed_counter(); |
|
189 int number_of_threads_completed = 0; |
177 do { |
190 do { |
178 // Check if handshake operation has timed out |
191 // Check if handshake operation has timed out |
179 if (handshake_has_timed_out(start_time)) { |
192 if (handshake_has_timed_out(start_time)) { |
180 handle_timeout(); |
193 handle_timeout(); |
181 } |
194 } |
182 |
195 |
183 // Have VM thread perform the handshake operation for blocked threads. |
196 // Have VM thread perform the handshake operation for blocked threads. |
184 // Observing a blocked state may of course be transient but the processing is guarded |
197 // Observing a blocked state may of course be transient but the processing is guarded |
185 // by semaphores and we optimistically begin by working on the blocked threads |
198 // by semaphores and we optimistically begin by working on the blocked threads |
186 { |
199 { |
|
200 // We need to re-think this with SMR ThreadsList. |
|
201 // There is an assumption in the code that the Threads_lock should |
|
202 // be locked during certain phases. |
187 MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
203 MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
188 ALL_JAVA_THREADS(thr) { |
204 for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) { |
|
205 // A new thread on the ThreadsList will not have an operation, |
|
206 // hence it is skipped in handshake_process_by_vmthread. |
189 thr->handshake_process_by_vmthread(); |
207 thr->handshake_process_by_vmthread(); |
190 } |
208 } |
191 } |
209 } |
192 |
210 |
193 while (poll_for_completed_thread()) { |
211 while (poll_for_completed_thread()) { |
|
212 // Includes canceled operations by exiting threads. |
194 number_of_threads_completed++; |
213 number_of_threads_completed++; |
195 } |
214 } |
196 |
215 |
197 } while (number_of_threads_issued != number_of_threads_completed); |
216 } while (number_of_threads_issued != number_of_threads_completed); |
198 } |
217 } |
210 _thread_cl(cl), _target_thread(NULL), _all_threads(true), _thread_alive(true) {} |
229 _thread_cl(cl), _target_thread(NULL), _all_threads(true), _thread_alive(true) {} |
211 VM_HandshakeFallbackOperation(ThreadClosure* cl, Thread* target) : |
230 VM_HandshakeFallbackOperation(ThreadClosure* cl, Thread* target) : |
212 _thread_cl(cl), _target_thread(target), _all_threads(false), _thread_alive(false) {} |
231 _thread_cl(cl), _target_thread(target), _all_threads(false), _thread_alive(false) {} |
213 |
232 |
214 void doit() { |
233 void doit() { |
215 ALL_JAVA_THREADS(t) { |
234 for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { |
216 if (_all_threads || t == _target_thread) { |
235 if (_all_threads || t == _target_thread) { |
217 if (t == _target_thread) { |
236 if (t == _target_thread) { |
218 _thread_alive = true; |
237 _thread_alive = true; |
219 } |
238 } |
220 _thread_cl->do_thread(t); |
239 _thread_cl->do_thread(t); |
296 void HandshakeState::cancel_inner(JavaThread* thread) { |
315 void HandshakeState::cancel_inner(JavaThread* thread) { |
297 assert(Thread::current() == thread, "should call from thread"); |
316 assert(Thread::current() == thread, "should call from thread"); |
298 assert(thread->thread_state() == _thread_in_vm, "must be in vm state"); |
317 assert(thread->thread_state() == _thread_in_vm, "must be in vm state"); |
299 #ifdef DEBUG |
318 #ifdef DEBUG |
300 { |
319 { |
301 MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag); |
320 ThreadsListHandle tlh; |
302 assert(!Threads::includes(thread), "java thread must not be on threads list"); |
321 assert(!tlh.includes(_target), "java thread must not be on threads list"); |
303 } |
322 } |
304 #endif |
323 #endif |
305 HandshakeOperation* op = _operation; |
324 HandshakeOperation* op = _operation; |
306 clear_handshake(thread); |
325 clear_handshake(thread); |
307 if (op != NULL) { |
326 if (op != NULL) { |