< prev index next >

src/hotspot/share/runtime/handshake.cpp

Print this page
rev 47820 : imported patch 10.08.open.rebase_20171114.rehn

@@ -35,12 +35,10 @@
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
 #include "utilities/formatBuffer.hpp"
 #include "utilities/preserveException.hpp"
 
-#define ALL_JAVA_THREADS(X) for (JavaThread* X = Threads::first(); X; X = X->next())
-
 class HandshakeOperation: public StackObj {
 public:
   virtual void do_handshake(JavaThread* thread) = 0;
   virtual void cancel_handshake(JavaThread* thread) = 0;
 };

@@ -92,12 +90,11 @@
   return false;
 }
 
 void VM_Handshake::handle_timeout() {
   LogStreamHandle(Warning, handshake) log_stream;
-  MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-  ALL_JAVA_THREADS(thr) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
     if (thr->has_handshake()) {
       log_stream.print("Thread " PTR_FORMAT " has not cleared its handshake op", p2i(thr));
       thr->print_thread_state_on(&log_stream);
     }
   }

@@ -115,12 +112,12 @@
 
   void doit() {
     TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake));
 
     {
-      MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-      if (Threads::includes(_target)) {
+      ThreadsListHandle tlh;
+      if (tlh.includes(_target)) {
         set_handshake(_target);
         _thread_alive = true;
       }
     }
 

@@ -137,12 +134,26 @@
     do {
       if (handshake_has_timed_out(start_time)) {
         handle_timeout();
       }
 
+      // We need to re-think this with SMR ThreadsList.
+      // There is assumption in code that Threads_lock should be lock
+      // during certain phases.
       MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+      ThreadsListHandle tlh;
+      if (tlh.includes(_target)) { 
+        // Warning threads address might be re-used.
+        // handshake_process_by_vmthread will check the semaphore for us again
+        // Since we can't have more then one handshake in flight a reuse of thread address
+        // should be okey since the new thread will not have an operation.
       _target->handshake_process_by_vmthread();
+      } else {
+        // We can't warn here is since the thread do cancel_handshake after it have been removed
+        // from ThreadsList. So we should just keep looping here until while below return negative
+        // If we have a bug, then we deadlock here, which is good for debugging.
+      }
 
     } while (!poll_for_completed_thread());
   }
 
   VMOp_Type type() const { return VMOp_HandshakeOneThread; }

@@ -155,27 +166,28 @@
   VM_HandshakeAllThreads(HandshakeThreadsOperation* op) : VM_Handshake(op) {}
 
   void doit() {
     TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake));
 
-    int number_of_threads_issued = -1;
-    int number_of_threads_completed = 0;
-    {
-      MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-      number_of_threads_issued = Threads::number_of_threads();
-
-      ALL_JAVA_THREADS(thr) {
+    int number_of_threads_issued = 0;
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
         set_handshake(thr);
+      number_of_threads_issued++;
       }
+
+    if (number_of_threads_issued < 1) {
+      log_debug(handshake)("No threads to handshake.");
+      return;
     }
 
     if (!UseMembar) {
       os::serialize_thread_states();
     }
 
     log_debug(handshake)("Threads signaled, begin processing blocked threads by VMThtread");
     const jlong start_time = os::elapsed_counter();
+    int number_of_threads_completed = 0;
     do {
       // Check if handshake operation has timed out
       if (handshake_has_timed_out(start_time)) {
         handle_timeout();
       }

@@ -182,17 +194,23 @@
 
       // Have VM thread perform the handshake operation for blocked threads.
       // Observing a blocked state may of course be transient but the processing is guarded
       // by semaphores and we optimistically begin by working on the blocked threads
       {
+          // We need to re-think this with SMR ThreadsList.
+          // There is assumption in code that Threads_lock should be lock
+          // during certain phases.
           MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-          ALL_JAVA_THREADS(thr) {
+          for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
+            // A new thread on the ThreadsList will not have an operation.
+            // Hence is skipped in handshake_process_by_vmthread.
             thr->handshake_process_by_vmthread();
           }
       }
 
       while (poll_for_completed_thread()) {
+        // Includes canceled operations by exiting threads.
         number_of_threads_completed++;
       }
 
     } while (number_of_threads_issued != number_of_threads_completed);
   }

@@ -210,11 +228,11 @@
       _thread_cl(cl), _target_thread(NULL), _all_threads(true), _thread_alive(true) {}
   VM_HandshakeFallbackOperation(ThreadClosure* cl, Thread* target) :
       _thread_cl(cl), _target_thread(target), _all_threads(false), _thread_alive(false) {}
 
   void doit() {
-    ALL_JAVA_THREADS(t) {
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
       if (_all_threads || t == _target_thread) {
         if (t == _target_thread) {
           _thread_alive = true;
         }
         _thread_cl->do_thread(t);

@@ -296,12 +314,12 @@
 void HandshakeState::cancel_inner(JavaThread* thread) {
   assert(Thread::current() == thread, "should call from thread");
   assert(thread->thread_state() == _thread_in_vm, "must be in vm state");
 #ifdef DEBUG
   {
-    MutexLockerEx ml(Threads_lock,  Mutex::_no_safepoint_check_flag);
-    assert(!Threads::includes(thread), "java thread must not be on threads list");
+    ThreadsListHandle tlh;
+    assert(!tlh.includes(_target), "java thread must not be on threads list");
   }
 #endif
   HandshakeOperation* op = _operation;
   clear_handshake(thread);
   if (op != NULL) {
< prev index next >