src/share/vm/runtime/objectMonitor.cpp

changeset 6513
bbfbe9b06038
parent 6453
75ef1a499665
parent 6335
d35df3079834
child 6520
a7d4d4655766
     1.1 --- a/src/share/vm/runtime/objectMonitor.cpp	Mon Mar 10 12:58:02 2014 +0100
     1.2 +++ b/src/share/vm/runtime/objectMonitor.cpp	Thu Mar 13 14:57:01 2014 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -382,6 +382,12 @@
    1.11      DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt);
    1.12      if (JvmtiExport::should_post_monitor_contended_enter()) {
    1.13        JvmtiExport::post_monitor_contended_enter(jt, this);
    1.14 +
    1.15 +      // The current thread does not yet own the monitor and does not
    1.16 +      // yet appear on any queues that would get it made the successor.
    1.17 +      // This means that the JVMTI_EVENT_MONITOR_CONTENDED_ENTER event
    1.18 +      // handler cannot accidentally consume an unpark() meant for the
    1.19 +      // ParkEvent associated with this ObjectMonitor.
    1.20      }
    1.21  
    1.22      OSThreadContendState osts(Self->osthread());
    1.23 @@ -439,6 +445,12 @@
    1.24    DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt);
    1.25    if (JvmtiExport::should_post_monitor_contended_entered()) {
    1.26      JvmtiExport::post_monitor_contended_entered(jt, this);
    1.27 +
    1.28 +    // The current thread already owns the monitor and is not going to
    1.29 +    // call park() for the remainder of the monitor enter protocol. So
    1.30 +    // it doesn't matter if the JVMTI_EVENT_MONITOR_CONTENDED_ENTERED
    1.31 +    // event handler consumed an unpark() issued by the thread that
    1.32 +    // just exited the monitor.
    1.33    }
    1.34  
    1.35    if (event.should_commit()) {
    1.36 @@ -1456,6 +1468,14 @@
    1.37          // Note: 'false' parameter is passed here because the
    1.38          // wait was not timed out due to thread interrupt.
    1.39          JvmtiExport::post_monitor_waited(jt, this, false);
    1.40 +
    1.41 +        // In this short circuit of the monitor wait protocol, the
    1.42 +        // current thread never drops ownership of the monitor and
    1.43 +        // never gets added to the wait queue so the current thread
    1.44 +        // cannot be made the successor. This means that the
    1.45 +        // JVMTI_EVENT_MONITOR_WAITED event handler cannot accidentally
    1.46 +        // consume an unpark() meant for the ParkEvent associated with
    1.47 +        // this ObjectMonitor.
    1.48       }
    1.49       if (event.should_commit()) {
    1.50         post_monitor_wait_event(&event, 0, millis, false);
    1.51 @@ -1499,21 +1519,6 @@
    1.52     exit (true, Self) ;                    // exit the monitor
    1.53     guarantee (_owner != Self, "invariant") ;
    1.54  
    1.55 -   // As soon as the ObjectMonitor's ownership is dropped in the exit()
    1.56 -   // call above, another thread can enter() the ObjectMonitor, do the
    1.57 -   // notify(), and exit() the ObjectMonitor. If the other thread's
    1.58 -   // exit() call chooses this thread as the successor and the unpark()
    1.59 -   // call happens to occur while this thread is posting a
    1.60 -   // MONITOR_CONTENDED_EXIT event, then we run the risk of the event
    1.61 -   // handler using RawMonitors and consuming the unpark().
    1.62 -   //
    1.63 -   // To avoid the problem, we re-post the event. This does no harm
    1.64 -   // even if the original unpark() was not consumed because we are the
    1.65 -   // chosen successor for this monitor.
    1.66 -   if (node._notified != 0 && _succ == Self) {
    1.67 -      node._event->unpark();
    1.68 -   }
    1.69 -
    1.70     // The thread is on the WaitSet list - now park() it.
    1.71     // On MP systems it's conceivable that a brief spin before we park
    1.72     // could be profitable.
    1.73 @@ -1597,6 +1602,33 @@
    1.74         JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT);
    1.75       }
    1.76  
    1.77 +     // Without the fix for 8028280, it is possible for the above call:
    1.78 +     //
    1.79 +     //   Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ;
    1.80 +     //
    1.81 +     // to consume the unpark() that was done when the successor was set.
    1.82 +     // The solution for this very rare possibility is to redo the unpark()
    1.83 +     // outside of the JvmtiExport::should_post_monitor_waited() check.
    1.84 +     //
    1.85 +     if (node._notified != 0 && _succ == Self) {
    1.86 +       // In this part of the monitor wait-notify-reenter protocol it
    1.87 +       // is possible (and normal) for another thread to do a fastpath
    1.88 +       // monitor enter-exit while this thread is still trying to get
    1.89 +       // to the reenter portion of the protocol.
    1.90 +       //
    1.91 +       // The ObjectMonitor was notified and the current thread is
    1.92 +       // the successor which also means that an unpark() has already
    1.93 +       // been done. The JVMTI_EVENT_MONITOR_WAITED event handler can
    1.94 +       // consume the unpark() that was done when the successor was
    1.95 +       // set because the same ParkEvent is shared between Java
    1.96 +       // monitors and JVM/TI RawMonitors (for now).
    1.97 +       //
    1.98 +       // We redo the unpark() to ensure forward progress, i.e., we
    1.99 +       // don't want all pending threads hanging (parked) with none
   1.100 +       // entering the unlocked monitor.
   1.101 +       node._event->unpark();
   1.102 +     }
   1.103 +
   1.104       if (event.should_commit()) {
   1.105         post_monitor_wait_event(&event, node._notifier_tid, millis, ret == OS_TIMEOUT);
   1.106       }

mercurial