< 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 >