< prev index next >

src/os/linux/vm/os_linux.cpp

Print this page

        

@@ -59,10 +59,11 @@
 #include "runtime/threadCritical.hpp"
 #include "runtime/timer.hpp"
 #include "services/attachListener.hpp"
 #include "services/memTracker.hpp"
 #include "services/runtimeService.hpp"
+#include "evtrace/traceEvents.hpp"
 #include "utilities/decoder.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/events.hpp"
 #include "utilities/elfFile.hpp"
 #include "utilities/growableArray.hpp"

@@ -4159,11 +4160,11 @@
     if (slp != NULL) slp->unpark() ;
   }
 
   // For JSR166. Unpark even if interrupt status already was set
   if (thread->is_Java_thread())
-    ((JavaThread*)thread)->parker()->unpark();
+    ((JavaThread*)thread)->parker()->unpark((JavaThread*)thread);
 
   ParkEvent * ev = thread->_ParkEvent ;
   if (ev != NULL) ev->unpark() ;
 
 }

@@ -5807,29 +5808,45 @@
 
 void Parker::park(bool isAbsolute, jlong time) {
   // Ideally we'd do something useful while spinning, such
   // as calling unpackTime().
 
+  Thread* thread = Thread::current();
+  assert(thread == AssociatedWith, "must be associated thread");
+  assert(thread->is_Java_thread(), "must be Java thread");
+  JavaThread *jt = (JavaThread *)thread;
+
+  if (EnableEventTracing && EnableEventTracingParkEvents && thread->park_priority() >= 0) {
+    TraceEvents::write_thread_park_begin(jt, isAbsolute, time);
+  }
+
+  // before ThreadBlockInVM below so the event is never written in a safepoint (destruction order)
+  TraceEventThreadParkEnd event(thread);
+
   // Optional fast-path check:
   // Return immediately if a permit is available.
   // We depend on Atomic::xchg() having full barrier semantics
   // since we are doing a lock-free update to _counter.
-  if (Atomic::xchg(0, &_counter) > 0) return;
-
-  Thread* thread = Thread::current();
-  assert(thread->is_Java_thread(), "Must be JavaThread");
-  JavaThread *jt = (JavaThread *)thread;
+  {
+    intptr_t unpark_seq = Atomic::xchg_ptr(0, &_counter);
+    if (unpark_seq > 0) {
+      event.fill(unpark_seq, TraceTypes::park_immediate_fast);
+      return;
+    }
+  }
 
   // Optional optimization -- avoid state transitions if there's an interrupt pending.
   // Check interrupt before trying to wait
   if (Thread::is_interrupted(thread, false)) {
+    event.fill(-1, TraceTypes::park_interrupted_fast);
     return;
   }
 
   // Next, demultiplex/decode time arguments
   timespec absTime;
   if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all
+    event.fill(-1, TraceTypes::park_no_wait_time);
     return;
   }
   if (time > 0) {
     unpackTime(&absTime, isAbsolute, time);
   }

@@ -5843,16 +5860,22 @@
   // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock.
   ThreadBlockInVM tbivm(jt);
 
   // Don't wait if cannot get lock since interference arises from
   // unblocking.  Also. check interrupt before trying wait
-  if (Thread::is_interrupted(thread, false) || pthread_mutex_trylock(_mutex) != 0) {
+  if (Thread::is_interrupted(thread, false)) {
+    event.fill(-1, TraceTypes::park_interrupted_slow);
+    return;
+  }
+  if (pthread_mutex_trylock(_mutex) != 0) {
+    event.fill(-1, TraceTypes::park_locked);
     return;
   }
 
   int status ;
   if (_counter > 0)  { // no wait needed
+    event.fill(_counter, TraceTypes::park_immediate_slow);
     _counter = 0;
     status = pthread_mutex_unlock(_mutex);
     assert (status == 0, "invariant") ;
     // Paranoia to ensure our locked and lock-free paths interact
     // correctly with each other and Java-level accesses.

@@ -5891,10 +5914,24 @@
 
 #ifdef ASSERT
   pthread_sigmask(SIG_SETMASK, &oldsigs, NULL);
 #endif
 
+  TraceTypes::park_return_code return_code;
+  switch (status) {
+    case 0:
+      return_code = TraceTypes::park_normal;
+      break;
+    case ETIMEDOUT:
+      return_code = TraceTypes::park_timedout;
+      break;
+    default:
+      assert(false, "unexpected pthread_cond_(timed)wait return code");
+      return_code = TraceTypes::park_unknown;
+  }
+  event.fill(_counter, return_code);
+
   _counter = 0 ;
   status = pthread_mutex_unlock(_mutex) ;
   assert_status(status == 0, status, "invariant") ;
   // Paranoia to ensure our locked and lock-free paths interact
   // correctly with each other and Java-level accesses.

@@ -5904,16 +5941,24 @@
   if (jt->handle_special_suspend_equivalent_condition()) {
     jt->java_suspend_self();
   }
 }
 
-void Parker::unpark() {
-  int s, status ;
+void Parker::unpark(JavaThread *thread) {
+  int status;
   status = pthread_mutex_lock(_mutex);
   assert (status == 0, "invariant") ;
-  s = _counter;
-  _counter = 1;
+  if (thread != AssociatedWith) {
+    status = pthread_mutex_unlock(_mutex);
+    assert (status == 0, "invariant") ;
+    return;
+  }
+  TraceEventThreadUnpark e(thread);
+  intptr_t s = e.seq();
+  assert(s > 0, "seq must be greater zero");
+  s = Atomic::xchg_ptr(s, &_counter);
+  e.set_chained_seq(s);
   if (s < 1) {
     // thread might be parked
     if (_cur_index != -1) {
       // thread is definitely parked
       if (WorkAroundNPTLTimedWaitHang) {

@@ -5928,15 +5973,15 @@
         assert (status == 0, "invariant");
         status = pthread_cond_signal (&_cond[index]);
         assert (status == 0, "invariant");
       }
     } else {
-      pthread_mutex_unlock(_mutex);
+      status = pthread_mutex_unlock(_mutex);
       assert (status == 0, "invariant") ;
     }
   } else {
-    pthread_mutex_unlock(_mutex);
+    status = pthread_mutex_unlock(_mutex);
     assert (status == 0, "invariant") ;
   }
 }
 
 
< prev index next >