--- old/src/os/linux/vm/os_linux.cpp 2016-10-25 10:40:03.811773979 +0200 +++ new/src/os/linux/vm/os_linux.cpp 2016-10-25 10:40:03.758773943 +0200 @@ -61,6 +61,7 @@ #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" @@ -4161,7 +4162,7 @@ // 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() ; @@ -5809,25 +5810,41 @@ // 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) { @@ -5845,12 +5862,18 @@ // 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") ; @@ -5893,6 +5916,20 @@ 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") ; @@ -5906,12 +5943,20 @@ } } -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) { @@ -5930,11 +5975,11 @@ 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") ; } }