@@ -593,12 +593,15 @@ void ObjectMonitor::enter_with_contention_mark(JavaThread* current, ObjectMonito
593593 OSThreadContendState osts (current->osthread ());
594594
595595 assert (current->thread_state () == _thread_in_vm, " invariant" );
596+ ObjectWaiter node (current);
596597
597598 for (;;) {
598599 ExitOnSuspend eos (this );
599600 {
600601 ThreadBlockInVMPreprocess<ExitOnSuspend> tbivs (current, eos, true /* allow_suspend */ );
601- enter_internal (current);
602+ if (!try_enter_fast (current, &node)) {
603+ enter_internal (current, &node, false /* reenter_path */ );
604+ }
602605 current->set_current_pending_monitor (nullptr );
603606 // We can go to a safepoint at the end of this block. If we
604607 // do a thread dump during that safepoint, then this thread will show
@@ -942,14 +945,17 @@ const char* ObjectMonitor::is_busy_to_string(stringStream* ss) {
942945 return ss->base ();
943946}
944947
945- void ObjectMonitor::enter_internal (JavaThread* current) {
948+ bool ObjectMonitor::try_enter_fast (JavaThread* current, ObjectWaiter* current_node) {
949+ assert (current != nullptr , " invariant" );
946950 assert (current->thread_state () == _thread_blocked, " invariant" );
951+ assert (current_node != nullptr , " invariant" );
952+ assert (current_node->_thread == current, " invariant" );
947953
948954 // Try the lock - TATAS
949955 if (try_lock (current) == TryLockResult::Success) {
950956 assert (!has_successor (current), " invariant" );
951957 assert (has_owner (current), " invariant" );
952- return ;
958+ return true ;
953959 }
954960
955961 assert (InitDone, " Unexpectedly not initialized" );
@@ -964,7 +970,7 @@ void ObjectMonitor::enter_internal(JavaThread* current) {
964970 if (try_spin (current)) {
965971 assert (has_owner (current), " invariant" );
966972 assert (!has_successor (current), " invariant" );
967- return ;
973+ return true ;
968974 }
969975
970976 // The Spin failed -- Enqueue and park the thread ...
@@ -973,54 +979,67 @@ void ObjectMonitor::enter_internal(JavaThread* current) {
973979
974980 // Enqueue "current" on ObjectMonitor's _entry_list.
975981 //
976- // Node acts as a proxy for current.
982+ // current_node acts as a proxy for current.
977983 // As an aside, if were to ever rewrite the synchronization code mostly
978984 // in Java, WaitNodes, ObjectMonitors, and Events would become 1st-class
979985 // Java objects. This would avoid awkward lifecycle and liveness issues,
980986 // as well as eliminate a subset of ABA issues.
981987 // TODO: eliminate ObjectWaiter and enqueue either Threads or Events.
982988
983- ObjectWaiter node (current);
984989 current->_ParkEvent ->reset ();
985990
986- if (try_lock_or_add_to_entry_list (current, &node )) {
987- return ; // We got the lock.
991+ if (try_lock_or_add_to_entry_list (current, current_node )) {
992+ return true ; // We got the lock.
988993 }
994+
989995 // This thread is now added to the _entry_list.
990996
991997 // The lock might have been released while this thread was occupied queueing
992998 // itself onto _entry_list. To close the race and avoid "stranding" and
993- // progress-liveness failure we must resample-retry _owner before parking.
999+ // progress-liveness failure the caller must resample-retry _owner before parking.
9941000 // Note the Dekker/Lamport duality: ST _entry_list; MEMBAR; LD Owner.
995- // In this case the ST-MEMBAR is accomplished with CAS().
996- //
997- // TODO: Defer all thread state transitions until park-time.
998- // Since state transitions are heavy and inefficient we'd like
999- // to defer the state transitions until absolutely necessary,
1000- // and in doing so avoid some transitions ...
1001+ // In this case the ST-MEMBAR is accomplished with CAS() in try_lock_or_add_to_entry_list.
1002+ return false ;
1003+ }
1004+
1005+ void ObjectMonitor::enter_internal (JavaThread* current, ObjectWaiter* current_node, bool reenter_path) {
1006+ assert (current != nullptr , " invariant" );
1007+ assert (current->thread_state () == _thread_blocked, " invariant" );
1008+ assert (current_node != nullptr , " invariant" );
1009+ assert (current_node->_thread == current, " invariant" );
10011010
10021011 // If there are unmounted virtual threads ahead in the _entry_list we want
10031012 // to do a timed-park instead to alleviate some deadlock cases where one
10041013 // of them is picked as the successor but cannot run due to having run out
10051014 // of carriers. This can happen, for example, if this is a pinned virtual
1006- // thread currently loading or initializining a class, and all other carriers
1015+ // thread currently loading or initializing a class, and all other carriers
10071016 // have a pinned vthread waiting for said class to be loaded/initialized.
10081017 // Read counter *after* adding this thread to the _entry_list. Adding to
10091018 // _entry_list uses Atomic::cmpxchg() which already provides a fence that
1010- // prevents this load from floating up previous store.
1019+ // prevents this load from floating up past a previous store.
10111020 // Note that we can have false positives where timed-park is not necessary.
1012- bool do_timed_parked = has_unmounted_vthreads ();
1021+ bool do_timed_park = has_unmounted_vthreads ();
10131022 jlong recheck_interval = 1 ;
10141023
10151024 for (;;) {
1025+ ObjectWaiter::TStates v = current_node->TState ;
1026+ guarantee (v == ObjectWaiter::TS_ENTER, " invariant" );
10161027
10171028 if (try_lock (current) == TryLockResult::Success) {
10181029 break ;
10191030 }
10201031 assert (!has_owner (current), " invariant" );
10211032
1033+ if (reenter_path) {
1034+ // If try_lock failed, spin again - we expect the notifier to release the monitor quickly.
1035+ // Note that spin count may be zero so the above try_lock is necessary.
1036+ if (try_spin (current)) {
1037+ break ;
1038+ }
1039+ }
1040+
10221041 // park self
1023- if (do_timed_parked ) {
1042+ if (do_timed_park ) {
10241043 current->_ParkEvent ->park (recheck_interval);
10251044 // Increase the recheck_interval, but clamp the value.
10261045 recheck_interval *= 8 ;
@@ -1031,18 +1050,23 @@ void ObjectMonitor::enter_internal(JavaThread* current) {
10311050 current->_ParkEvent ->park ();
10321051 }
10331052
1053+ // Try again, but just so we distinguish between futile wakeups and
1054+ // successful wakeups. The following test isn't algorithmically
1055+ // necessary, but it helps us maintain sensible statistics.
10341056 if (try_lock (current) == TryLockResult::Success) {
10351057 break ;
10361058 }
10371059
10381060 // The lock is still contested.
10391061
1040- // Assuming this is not a spurious wakeup we'll normally find _succ == current.
1041- // We can defer clearing _succ until after the spin completes
1042- // try_spin() must tolerate being called with _succ == current.
1043- // Try yet another round of adaptive spinning.
1044- if (try_spin (current)) {
1045- break ;
1062+ if (!reenter_path) {
1063+ // Assuming this is not a spurious wakeup we'll normally find _succ == current.
1064+ // We can defer clearing _succ until after the spin completes and
1065+ // try_spin() must tolerate being called with _succ == current.
1066+ // Try yet another round of adaptive spinning.
1067+ if (try_spin (current)) {
1068+ break ;
1069+ }
10461070 }
10471071
10481072 // We can find that we were unpark()ed and redesignated _succ while
@@ -1051,15 +1075,22 @@ void ObjectMonitor::enter_internal(JavaThread* current) {
10511075 // just spin again. This pattern can repeat, leaving _succ to simply
10521076 // spin on a CPU.
10531077
1054- if (has_successor (current)) clear_successor ();
1078+ if (has_successor (current)) {
1079+ clear_successor ();
1080+ }
10551081
10561082 // Invariant: after clearing _succ a thread *must* retry _owner before parking.
10571083 OrderAccess::fence ();
1084+
1085+ // Will only potentially change on the reenter path - see comment in notify_internal.
1086+ do_timed_park |= current_node->_do_timed_park ;
10581087 }
10591088
1089+ assert (has_owner (current), " invariant" );
1090+
10601091 // Egress :
10611092 // Current has acquired the lock -- Unlink current from the _entry_list.
1062- unlink_after_acquire (current, &node );
1093+ unlink_after_acquire (current, current_node );
10631094 if (has_successor (current)) {
10641095 clear_successor ();
10651096 // Note that we don't need to do OrderAccess::fence() after clearing
@@ -1069,17 +1100,17 @@ void ObjectMonitor::enter_internal(JavaThread* current) {
10691100 // We've acquired ownership with CAS().
10701101 // CAS is serializing -- it has MEMBAR/FENCE-equivalent semantics.
10711102 // But since the CAS() this thread may have also stored into _succ
1072- // or entry_list. These meta-data updates must be visible __before
1103+ // or entry_list. These meta-data updates must be visible __before
10731104 // this thread subsequently drops the lock.
10741105 // Consider what could occur if we didn't enforce this constraint --
10751106 // STs to monitor meta-data and user-data could reorder with (become
10761107 // visible after) the ST in exit that drops ownership of the lock.
10771108 // Some other thread could then acquire the lock, but observe inconsistent
1078- // or old monitor meta-data and heap data. That violates the JMM.
1109+ // or old monitor meta-data and heap data. That violates the JMM.
10791110 // To that end, the exit() operation must have at least STST|LDST
1080- // "release" barrier semantics. Specifically, there must be at least a
1111+ // "release" barrier semantics. Specifically, there must be at least a
10811112 // STST|LDST barrier in exit() before the ST of null into _owner that drops
1082- // the lock. The barrier ensures that changes to monitor meta-data and data
1113+ // the lock. The barrier ensures that changes to monitor meta-data and data
10831114 // protected by the lock will be visible before we release the lock, and
10841115 // therefore before some other thread (CPU) has a chance to acquire the lock.
10851116 // See also: http://gee.cs.oswego.edu/dl/jmm/cookbook.html.
@@ -1088,98 +1119,10 @@ void ObjectMonitor::enter_internal(JavaThread* current) {
10881119 // the ST of null into _owner in the *subsequent* (following) corresponding
10891120 // monitorexit.
10901121
1122+ current_node->TState = ObjectWaiter::TS_RUN;
10911123 return ;
10921124}
10931125
1094- // reenter_internal() is a specialized inline form of the latter half of the
1095- // contended slow-path from enter_internal(). We use reenter_internal() only for
1096- // monitor reentry in wait().
1097- //
1098- // In the future we should reconcile enter_internal() and reenter_internal().
1099-
1100- void ObjectMonitor::reenter_internal (JavaThread* current, ObjectWaiter* currentNode) {
1101- assert (current != nullptr , " invariant" );
1102- assert (current->thread_state () == _thread_blocked, " invariant" );
1103- assert (currentNode != nullptr , " invariant" );
1104- assert (currentNode->_thread == current, " invariant" );
1105- assert (_waiters > 0 , " invariant" );
1106-
1107- // If there are unmounted virtual threads ahead in the _entry_list we want
1108- // to do a timed-park instead to alleviate some deadlock cases where one
1109- // of them is picked as the successor but cannot run due to having run out
1110- // of carriers. This can happen, for example, if a mixed of unmounted and
1111- // pinned vthreads taking up all the carriers are waiting for a class to be
1112- // initialized, and the selected successor is one of the unmounted vthreads.
1113- // Although this method is used for the "notification" case, it could be
1114- // that this thread reached here without been added to the _entry_list yet.
1115- // This can happen if it was interrupted or the wait timed-out at the same
1116- // time. In that case we rely on currentNode->_do_timed_park, which will be
1117- // read on the next loop iteration, after consuming the park permit set by
1118- // the notifier in notify_internal.
1119- // Note that we can have false positives where timed-park is not necessary.
1120- bool do_timed_parked = has_unmounted_vthreads ();
1121- jlong recheck_interval = 1 ;
1122-
1123- for (;;) {
1124- ObjectWaiter::TStates v = currentNode->TState ;
1125- guarantee (v == ObjectWaiter::TS_ENTER, " invariant" );
1126- assert (!has_owner (current), " invariant" );
1127-
1128- // This thread has been notified so try to reacquire the lock.
1129- if (try_lock (current) == TryLockResult::Success) {
1130- break ;
1131- }
1132-
1133- // If that fails, spin again. Note that spin count may be zero so the above TryLock
1134- // is necessary.
1135- if (try_spin (current)) {
1136- break ;
1137- }
1138-
1139- {
1140- OSThreadContendState osts (current->osthread ());
1141- if (do_timed_parked) {
1142- current->_ParkEvent ->park (recheck_interval);
1143- // Increase the recheck_interval, but clamp the value.
1144- recheck_interval *= 8 ;
1145- if (recheck_interval > MAX_RECHECK_INTERVAL) {
1146- recheck_interval = MAX_RECHECK_INTERVAL;
1147- }
1148- } else {
1149- current->_ParkEvent ->park ();
1150- }
1151- }
1152-
1153- // Try again, but just so we distinguish between futile wakeups and
1154- // successful wakeups. The following test isn't algorithmically
1155- // necessary, but it helps us maintain sensible statistics.
1156- if (try_lock (current) == TryLockResult::Success) {
1157- break ;
1158- }
1159-
1160- // The lock is still contested.
1161-
1162- // Assuming this is not a spurious wakeup we'll normally
1163- // find that _succ == current.
1164- if (has_successor (current)) clear_successor ();
1165-
1166- // Invariant: after clearing _succ a contending thread
1167- // *must* retry _owner before parking.
1168- OrderAccess::fence ();
1169-
1170- // See comment in notify_internal
1171- do_timed_parked |= currentNode->_do_timed_park ;
1172- }
1173-
1174- // Current has acquired the lock -- Unlink current from the _entry_list.
1175- assert (has_owner (current), " invariant" );
1176- unlink_after_acquire (current, currentNode);
1177- if (has_successor (current)) clear_successor ();
1178- assert (!has_successor (current), " invariant" );
1179- currentNode->TState = ObjectWaiter::TS_RUN;
1180- OrderAccess::fence (); // see comments at the end of enter_internal()
1181- }
1182-
11831126// This method is called from two places:
11841127// - On monitorenter contention with a null waiter.
11851128// - After Object.wait() times out or the target is interrupted to reenter the
@@ -1971,7 +1914,9 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
19711914 ExitOnSuspend eos (this );
19721915 {
19731916 ThreadBlockInVMPreprocess<ExitOnSuspend> tbivs (current, eos, true /* allow_suspend */ );
1974- reenter_internal (current, &node);
1917+ assert ( _waiters > 0 , " invariant" );
1918+ OSThreadContendState osts (current->osthread ());
1919+ enter_internal (current, &node, true /* reenter_path */ );
19751920 // We can go to a safepoint at the end of this block. If we
19761921 // do a thread dump during that safepoint, then this thread will show
19771922 // as having "-locked" the monitor, but the OS and java.lang.Thread
@@ -2082,12 +2027,12 @@ bool ObjectMonitor::notify_internal(JavaThread* current) {
20822027 // Wake up the thread to alleviate some deadlock cases where the successor
20832028 // that will be picked up when this thread releases the monitor is an unmounted
20842029 // virtual thread that cannot run due to having run out of carriers. Upon waking
2085- // up, the thread will call reenter_internal( ) which will use timed-park in case
2030+ // up, the thread will call enter_internal(..., true ) which will use timed-park in case
20862031 // there is contention and there are still vthreads in the _entry_list.
20872032 // If the target was interrupted or the wait timed-out at the same time, it could
2088- // have reached reenter_internal and read a false value of has_unmounted_vthreads()
2033+ // have reached enter_internal and read a false value of has_unmounted_vthreads()
20892034 // before we added it to the _entry_list above. To deal with that case, we set _do_timed_park
2090- // which will be read by the target on the next loop iteration in reenter_internal .
2035+ // which will be read by the target on the next loop iteration in enter_internal .
20912036 iterator->_do_timed_park = true ;
20922037 JavaThread* t = iterator->thread ();
20932038 t->_ParkEvent ->unpark ();
0 commit comments