108108
109109#endif // ndef DTRACE_ENABLED
110110
111- // Tunables ...
112- // The knob* variables are effectively final. Once set they should
113- // never be modified hence. Consider using __read_mostly with GCC.
114-
115- int ObjectMonitor::Knob_SpinLimit = 5000 ; // derived by an external tool -
116-
117- static int Knob_Bonus = 100 ; // spin success bonus
118- static int Knob_BonusB = 100 ; // spin success bonus
119- static int Knob_Penalty = 200 ; // spin failure penalty
120- static int Knob_Poverty = 1000 ;
121- static int Knob_FixedSpin = 0 ;
122- static int Knob_PreSpin = 10 ; // 20-100 likely better
123-
124111DEBUG_ONLY (static volatile bool InitDone = false ;)
125112
126113OopStorage* ObjectMonitor::_oop_storage = nullptr;
@@ -406,7 +393,7 @@ bool ObjectMonitor::enter(JavaThread* current) {
406393 // transitions. The following spin is strictly optional ...
407394 // Note that if we acquire the monitor from an initial spin
408395 // we forgo posting JVMTI events and firing DTRACE probes.
409- if (TrySpin (current) > 0 ) {
396+ if (TrySpin (current)) {
410397 assert (owner_raw () == current, " must be current: owner=" INTPTR_FORMAT, p2i (owner_raw ()));
411398 assert (_recursions == 0 , " must be 0: recursions=" INTX_FORMAT, _recursions);
412399 assert (object ()->mark () == markWord::encode (this ),
@@ -535,18 +522,18 @@ bool ObjectMonitor::enter(JavaThread* current) {
535522// Caveat: TryLock() is not necessarily serializing if it returns failure.
536523// Callers must compensate as needed.
537524
538- int ObjectMonitor::TryLock (JavaThread* current) {
525+ ObjectMonitor::TryLockResult ObjectMonitor::TryLock (JavaThread* current) {
539526 void * own = owner_raw ();
540- if (own != nullptr ) return 0 ;
527+ if (own != nullptr ) return TryLockResult::HasOwner ;
541528 if (try_set_owner_from (nullptr , current) == nullptr ) {
542529 assert (_recursions == 0 , " invariant" );
543- return 1 ;
530+ return TryLockResult::Success ;
544531 }
545532 // The lock had been free momentarily, but we lost the race to the lock.
546533 // Interference -- the CAS failed.
547534 // We can either return -1 or retry.
548535 // Retry doesn't make as much sense because the lock was just acquired.
549- return - 1 ;
536+ return TryLockResult::Interference ;
550537}
551538
552539// Deflate the specified ObjectMonitor if not in-use. Returns true if it
@@ -723,7 +710,7 @@ void ObjectMonitor::EnterI(JavaThread* current) {
723710 assert (current->thread_state () == _thread_blocked, " invariant" );
724711
725712 // Try the lock - TATAS
726- if (TryLock (current) > 0 ) {
713+ if (TryLock (current) == TryLockResult::Success ) {
727714 assert (_succ != current, " invariant" );
728715 assert (owner_raw () == current, " invariant" );
729716 assert (_Responsible != current, " invariant" );
@@ -757,7 +744,7 @@ void ObjectMonitor::EnterI(JavaThread* current) {
757744 // to the owner. This has subtle but beneficial affinity
758745 // effects.
759746
760- if (TrySpin (current) > 0 ) {
747+ if (TrySpin (current)) {
761748 assert (owner_raw () == current, " invariant" );
762749 assert (_succ != current, " invariant" );
763750 assert (_Responsible != current, " invariant" );
@@ -794,7 +781,7 @@ void ObjectMonitor::EnterI(JavaThread* current) {
794781
795782 // Interference - the CAS failed because _cxq changed. Just retry.
796783 // As an optional optimization we retry the lock.
797- if (TryLock (current) > 0 ) {
784+ if (TryLock (current) == TryLockResult::Success ) {
798785 assert (_succ != current, " invariant" );
799786 assert (owner_raw () == current, " invariant" );
800787 assert (_Responsible != current, " invariant" );
@@ -847,7 +834,9 @@ void ObjectMonitor::EnterI(JavaThread* current) {
847834
848835 for (;;) {
849836
850- if (TryLock (current) > 0 ) break ;
837+ if (TryLock (current) == TryLockResult::Success) {
838+ break ;
839+ }
851840 assert (owner_raw () != current, " invariant" );
852841
853842 // park self
@@ -862,7 +851,9 @@ void ObjectMonitor::EnterI(JavaThread* current) {
862851 current->_ParkEvent ->park ();
863852 }
864853
865- if (TryLock (current) > 0 ) break ;
854+ if (TryLock (current) == TryLockResult::Success) {
855+ break ;
856+ }
866857
867858 if (try_set_owner_from (DEFLATER_MARKER, current) == DEFLATER_MARKER) {
868859 // Cancelled the in-progress async deflation by changing owner from
@@ -895,7 +886,9 @@ void ObjectMonitor::EnterI(JavaThread* current) {
895886 // We can defer clearing _succ until after the spin completes
896887 // TrySpin() must tolerate being called with _succ == current.
897888 // Try yet another round of adaptive spinning.
898- if (TrySpin (current) > 0 ) break ;
889+ if (TrySpin (current)) {
890+ break ;
891+ }
899892
900893 // We can find that we were unpark()ed and redesignated _succ while
901894 // we were spinning. That's harmless. If we iterate and call park(),
@@ -994,8 +987,9 @@ void ObjectMonitor::ReenterI(JavaThread* current, ObjectWaiter* currentNode) {
994987 guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, " invariant" );
995988 assert (owner_raw () != current, " invariant" );
996989
997- if (TryLock (current) > 0 ) break ;
998- if (TrySpin (current) > 0 ) break ;
990+ if (TrySpin (current)) {
991+ break ;
992+ }
999993
1000994 {
1001995 OSThreadContendState osts (current->osthread ());
@@ -1012,7 +1006,9 @@ void ObjectMonitor::ReenterI(JavaThread* current, ObjectWaiter* currentNode) {
10121006 // Try again, but just so we distinguish between futile wakeups and
10131007 // successful wakeups. The following test isn't algorithmically
10141008 // necessary, but it helps us maintain sensible statistics.
1015- if (TryLock (current) > 0 ) break ;
1009+ if (TryLock (current) == TryLockResult::Success) {
1010+ break ;
1011+ }
10161012
10171013 // The lock is still contested.
10181014 // Keep a tally of the # of futile wakeups.
@@ -1854,39 +1850,78 @@ void ObjectMonitor::notifyAll(TRAPS) {
18541850// hysteresis control to damp the transition rate between spinning and
18551851// not spinning.
18561852
1857- // Spinning: Fixed frequency (100%), vary duration
1858- int ObjectMonitor::TrySpin (JavaThread* current) {
1859- // Dumb, brutal spin. Good for comparative measurements against adaptive spinning.
1860- int ctr = Knob_FixedSpin;
1861- if (ctr != 0 ) {
1862- while (--ctr >= 0 ) {
1863- if (TryLock (current) > 0 ) return 1 ;
1864- SpinPause ();
1853+ int ObjectMonitor::Knob_SpinLimit = 5000 ; // derived by an external tool
1854+
1855+ static int Knob_Bonus = 100 ; // spin success bonus
1856+ static int Knob_Penalty = 200 ; // spin failure penalty
1857+ static int Knob_Poverty = 1000 ;
1858+ static int Knob_FixedSpin = 0 ;
1859+ static int Knob_PreSpin = 10 ; // 20-100 likely better, but it's not better in my testing.
1860+
1861+ inline static int adjust_up (int spin_duration) {
1862+ int x = spin_duration;
1863+ if (x < ObjectMonitor::Knob_SpinLimit) {
1864+ if (x < Knob_Poverty) {
1865+ x = Knob_Poverty;
18651866 }
1866- return 0 ;
1867+ return x + Knob_Bonus;
1868+ } else {
1869+ return spin_duration;
18671870 }
1871+ }
1872+
1873+ inline static int adjust_down (int spin_duration) {
1874+ // TODO: Use an AIMD-like policy to adjust _SpinDuration.
1875+ // AIMD is globally stable.
1876+ int x = spin_duration;
1877+ if (x > 0 ) {
1878+ // Consider an AIMD scheme like: x -= (x >> 3) + 100
1879+ // This is globally sample and tends to damp the response.
1880+ x -= Knob_Penalty;
1881+ if (x < 0 ) { x = 0 ; }
1882+ return x;
1883+ } else {
1884+ return spin_duration;
1885+ }
1886+ }
18681887
1869- for (ctr = Knob_PreSpin + 1 ; --ctr >= 0 ;) {
1870- if (TryLock (current) > 0 ) {
1871- // Increase _SpinDuration ...
1872- // Note that we don't clamp SpinDuration precisely at SpinLimit.
1873- // Raising _SpurDuration to the poverty line is key.
1874- int x = _SpinDuration;
1875- if (x < Knob_SpinLimit) {
1876- if (x < Knob_Poverty) x = Knob_Poverty;
1877- _SpinDuration = x + Knob_BonusB;
1888+ bool ObjectMonitor::short_fixed_spin (JavaThread* current, int spin_count, bool adapt) {
1889+ for (int ctr = 0 ; ctr < spin_count; ctr++) {
1890+ TryLockResult status = TryLock (current);
1891+ if (status == TryLockResult::Success) {
1892+ if (adapt) {
1893+ _SpinDuration = adjust_up (_SpinDuration);
18781894 }
1879- return 1 ;
1895+ return true ;
1896+ } else if (status == TryLockResult::Interference) {
1897+ break ;
18801898 }
18811899 SpinPause ();
18821900 }
1901+ return false ;
1902+ }
1903+
1904+ // Spinning: Fixed frequency (100%), vary duration
1905+ bool ObjectMonitor::TrySpin (JavaThread* current) {
1906+
1907+ // Dumb, brutal spin. Good for comparative measurements against adaptive spinning.
1908+ int knob_fixed_spin = Knob_FixedSpin; // 0 (don't spin: default), 2000 good test
1909+ if (knob_fixed_spin > 0 ) {
1910+ return short_fixed_spin (current, knob_fixed_spin, false );
1911+ }
18831912
18841913 // Admission control - verify preconditions for spinning
18851914 //
18861915 // We always spin a little bit, just to prevent _SpinDuration == 0 from
18871916 // becoming an absorbing state. Put another way, we spin briefly to
18881917 // sample, just in case the system load, parallelism, contention, or lock
18891918 // modality changed.
1919+
1920+ int knob_pre_spin = Knob_PreSpin; // 10 (default), 100, 1000 or 2000
1921+ if (short_fixed_spin (current, knob_pre_spin, true )) {
1922+ return true ;
1923+ }
1924+
18901925 //
18911926 // Consider the following alternative:
18921927 // Periodically set _SpinDuration = _SpinLimit and try a long/full
@@ -1895,8 +1930,8 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
18951930 // This takes us into the realm of 1-out-of-N spinning, where we
18961931 // hold the duration constant but vary the frequency.
18971932
1898- ctr = _SpinDuration;
1899- if (ctr <= 0 ) return 0 ;
1933+ int ctr = _SpinDuration;
1934+ if (ctr <= 0 ) return false ;
19001935
19011936 // We're good to spin ... spin ingress.
19021937 // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades
@@ -1928,7 +1963,7 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
19281963 // might update the poll values and we could be in a thread_blocked
19291964 // state here which is not allowed so just check the poll.
19301965 if (SafepointMechanism::local_poll_armed (current)) {
1931- goto Abort; // abrupt spin egress
1966+ break ;
19321967 }
19331968 SpinPause ();
19341969 }
@@ -1960,26 +1995,21 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
19601995 // If we acquired the lock early in the spin cycle it
19611996 // makes sense to increase _SpinDuration proportionally.
19621997 // Note that we don't clamp SpinDuration precisely at SpinLimit.
1963- int x = _SpinDuration;
1964- if (x < Knob_SpinLimit) {
1965- if (x < Knob_Poverty) x = Knob_Poverty;
1966- _SpinDuration = x + Knob_Bonus;
1967- }
1968- return 1 ;
1998+ _SpinDuration = adjust_up (_SpinDuration);
1999+ return true ;
19692000 }
19702001
19712002 // The CAS failed ... we can take any of the following actions:
19722003 // * penalize: ctr -= CASPenalty
1973- // * exit spin with prejudice -- goto Abort;
2004+ // * exit spin with prejudice -- abort without adapting spinner
19742005 // * exit spin without prejudice.
19752006 // * Since CAS is high-latency, retry again immediately.
1976- prv = ox;
1977- goto Abort;
2007+ break ;
19782008 }
19792009
19802010 // Did lock ownership change hands ?
19812011 if (ox != prv && prv != nullptr ) {
1982- goto Abort ;
2012+ break ;
19832013 }
19842014 prv = ox;
19852015
@@ -1989,30 +2019,23 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
19892019 }
19902020
19912021 // Spin failed with prejudice -- reduce _SpinDuration.
1992- // TODO: Use an AIMD-like policy to adjust _SpinDuration.
1993- // AIMD is globally stable.
1994- {
1995- int x = _SpinDuration;
1996- if (x > 0 ) {
1997- // Consider an AIMD scheme like: x -= (x >> 3) + 100
1998- // This is globally sample and tends to damp the response.
1999- x -= Knob_Penalty;
2000- if (x < 0 ) x = 0 ;
2001- _SpinDuration = x;
2002- }
2022+ if (ctr < 0 ) {
2023+ _SpinDuration = adjust_down (_SpinDuration);
20032024 }
20042025
2005- Abort:
20062026 if (_succ == current) {
20072027 _succ = nullptr ;
20082028 // Invariant: after setting succ=null a contending thread
20092029 // must recheck-retry _owner before parking. This usually happens
20102030 // in the normal usage of TrySpin(), but it's safest
20112031 // to make TrySpin() as foolproof as possible.
20122032 OrderAccess::fence ();
2013- if (TryLock (current) > 0 ) return 1 ;
2033+ if (TryLock (current) == TryLockResult::Success) {
2034+ return true ;
2035+ }
20142036 }
2015- return 0 ;
2037+
2038+ return false ;
20162039}
20172040
20182041
0 commit comments