Mercurial > hg > graal-jvmci-8
diff src/share/vm/runtime/objectMonitor.cpp @ 14909:4ca6dc0799b6
Backout jdk9 merge
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Tue, 01 Apr 2014 13:57:07 +0200 |
parents | 28f281e8de1d |
children | 52b4284cb496 |
line wrap: on
line diff
--- a/src/share/vm/runtime/objectMonitor.cpp Tue Apr 01 14:09:03 2014 +0200 +++ b/src/share/vm/runtime/objectMonitor.cpp Tue Apr 01 13:57:07 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ # include "os_bsd.inline.hpp" #endif -#if defined(__GNUC__) && !defined(IA64) && !defined(PPC64) +#if defined(__GNUC__) && !defined(IA64) // Need to inhibit inlining for older versions of GCC to avoid build-time failures #define ATTR __attribute__((noinline)) #else @@ -78,6 +78,39 @@ len = klassname->utf8_length(); \ } +#ifndef USDT2 + +HS_DTRACE_PROBE_DECL4(hotspot, monitor__notify, + jlong, uintptr_t, char*, int); +HS_DTRACE_PROBE_DECL4(hotspot, monitor__notifyAll, + jlong, uintptr_t, char*, int); +HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__enter, + jlong, uintptr_t, char*, int); +HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__entered, + jlong, uintptr_t, char*, int); +HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__exit, + jlong, uintptr_t, char*, int); + +#define DTRACE_MONITOR_WAIT_PROBE(monitor, obj, thread, millis) \ + { \ + if (DTraceMonitorProbes) { \ + DTRACE_MONITOR_PROBE_COMMON(obj, thread); \ + HS_DTRACE_PROBE5(hotspot, monitor__wait, jtid, \ + (monitor), bytes, len, (millis)); \ + } \ + } + +#define DTRACE_MONITOR_PROBE(probe, monitor, obj, thread) \ + { \ + if (DTraceMonitorProbes) { \ + DTRACE_MONITOR_PROBE_COMMON(obj, thread); \ + HS_DTRACE_PROBE4(hotspot, monitor__##probe, jtid, \ + (uintptr_t)(monitor), bytes, len); \ + } \ + } + +#else /* USDT2 */ + #define DTRACE_MONITOR_WAIT_PROBE(monitor, obj, thread, millis) \ { \ if (DTraceMonitorProbes) { \ @@ -102,6 +135,7 @@ } \ } +#endif /* USDT2 */ #else // ndef DTRACE_ENABLED #define DTRACE_MONITOR_WAIT_PROBE(obj, thread, millis, mon) {;} @@ -200,7 +234,7 @@ // * Taken together, the cxq and the EntryList constitute or form a // single logical queue of threads stalled trying to acquire the lock. // We use two distinct lists to improve the odds of a constant-time -// dequeue operation after acquisition (in the ::enter() epilogue) and +// dequeue operation after acquisition (in the ::enter() epilog) and // to reduce heat on the list ends. (c.f. Michael Scott's "2Q" algorithm). // A key desideratum is to minimize queue & monitor metadata manipulation // that occurs while holding the monitor lock -- that is, we want to @@ -348,12 +382,6 @@ DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt); if (JvmtiExport::should_post_monitor_contended_enter()) { JvmtiExport::post_monitor_contended_enter(jt, this); - - // The current thread does not yet own the monitor and does not - // yet appear on any queues that would get it made the successor. - // This means that the JVMTI_EVENT_MONITOR_CONTENDED_ENTER event - // handler cannot accidentally consume an unpark() meant for the - // ParkEvent associated with this ObjectMonitor. } OSThreadContendState osts(Self->osthread()); @@ -411,12 +439,6 @@ DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt); if (JvmtiExport::should_post_monitor_contended_entered()) { JvmtiExport::post_monitor_contended_entered(jt, this); - - // The current thread already owns the monitor and is not going to - // call park() for the remainder of the monitor enter protocol. So - // it doesn't matter if the JVMTI_EVENT_MONITOR_CONTENDED_ENTERED - // event handler consumed an unpark() issued by the thread that - // just exited the monitor. } if (event.should_commit()) { @@ -655,7 +677,7 @@ // non-null and elect a new "Responsible" timer thread. // // This thread executes: - // ST Responsible=null; MEMBAR (in enter epilogue - here) + // ST Responsible=null; MEMBAR (in enter epilog - here) // LD cxq|EntryList (in subsequent exit) // // Entering threads in the slow/contended path execute: @@ -1434,14 +1456,6 @@ // Note: 'false' parameter is passed here because the // wait was not timed out due to thread interrupt. JvmtiExport::post_monitor_waited(jt, this, false); - - // In this short circuit of the monitor wait protocol, the - // current thread never drops ownership of the monitor and - // never gets added to the wait queue so the current thread - // cannot be made the successor. This means that the - // JVMTI_EVENT_MONITOR_WAITED event handler cannot accidentally - // consume an unpark() meant for the ParkEvent associated with - // this ObjectMonitor. } if (event.should_commit()) { post_monitor_wait_event(&event, 0, millis, false); @@ -1485,6 +1499,21 @@ exit (true, Self) ; // exit the monitor guarantee (_owner != Self, "invariant") ; + // As soon as the ObjectMonitor's ownership is dropped in the exit() + // call above, another thread can enter() the ObjectMonitor, do the + // notify(), and exit() the ObjectMonitor. If the other thread's + // exit() call chooses this thread as the successor and the unpark() + // call happens to occur while this thread is posting a + // MONITOR_CONTENDED_EXIT event, then we run the risk of the event + // handler using RawMonitors and consuming the unpark(). + // + // To avoid the problem, we re-post the event. This does no harm + // even if the original unpark() was not consumed because we are the + // chosen successor for this monitor. + if (node._notified != 0 && _succ == Self) { + node._event->unpark(); + } + // The thread is on the WaitSet list - now park() it. // On MP systems it's conceivable that a brief spin before we park // could be profitable. @@ -1566,25 +1595,6 @@ // post monitor waited event. Note that this is past-tense, we are done waiting. if (JvmtiExport::should_post_monitor_waited()) { JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT); - - if (node._notified != 0 && _succ == Self) { - // In this part of the monitor wait-notify-reenter protocol it - // is possible (and normal) for another thread to do a fastpath - // monitor enter-exit while this thread is still trying to get - // to the reenter portion of the protocol. - // - // The ObjectMonitor was notified and the current thread is - // the successor which also means that an unpark() has already - // been done. The JVMTI_EVENT_MONITOR_WAITED event handler can - // consume the unpark() that was done when the successor was - // set because the same ParkEvent is shared between Java - // monitors and JVM/TI RawMonitors (for now). - // - // We redo the unpark() to ensure forward progress, i.e., we - // don't want all pending threads hanging (parked) with none - // entering the unlocked monitor. - node._event->unpark(); - } } if (event.should_commit()) { @@ -2021,7 +2031,7 @@ TEVENT (Spin abort -- too many spinners) ; return 0 ; } - // Slightly racy, but benign ... + // Slighty racy, but benign ... Adjust (&_Spinner, 1) ; }