108
108
109
109
#endif // ndef DTRACE_ENABLED
110
110
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
-
124
111
DEBUG_ONLY (static volatile bool InitDone = false ;)
125
112
126
113
OopStorage* ObjectMonitor::_oop_storage = nullptr;
@@ -406,7 +393,7 @@ bool ObjectMonitor::enter(JavaThread* current) {
406
393
// transitions. The following spin is strictly optional ...
407
394
// Note that if we acquire the monitor from an initial spin
408
395
// we forgo posting JVMTI events and firing DTRACE probes.
409
- if (TrySpin (current) > 0 ) {
396
+ if (TrySpin (current)) {
410
397
assert (owner_raw () == current, " must be current: owner=" INTPTR_FORMAT, p2i (owner_raw ()));
411
398
assert (_recursions == 0 , " must be 0: recursions=" INTX_FORMAT, _recursions);
412
399
assert (object ()->mark () == markWord::encode (this ),
@@ -535,18 +522,18 @@ bool ObjectMonitor::enter(JavaThread* current) {
535
522
// Caveat: TryLock() is not necessarily serializing if it returns failure.
536
523
// Callers must compensate as needed.
537
524
538
- int ObjectMonitor::TryLock (JavaThread* current) {
525
+ ObjectMonitor::TryLockResult ObjectMonitor::TryLock (JavaThread* current) {
539
526
void * own = owner_raw ();
540
- if (own != nullptr ) return 0 ;
527
+ if (own != nullptr ) return TryLockResult::HasOwner ;
541
528
if (try_set_owner_from (nullptr , current) == nullptr ) {
542
529
assert (_recursions == 0 , " invariant" );
543
- return 1 ;
530
+ return TryLockResult::Success ;
544
531
}
545
532
// The lock had been free momentarily, but we lost the race to the lock.
546
533
// Interference -- the CAS failed.
547
534
// We can either return -1 or retry.
548
535
// Retry doesn't make as much sense because the lock was just acquired.
549
- return - 1 ;
536
+ return TryLockResult::Interference ;
550
537
}
551
538
552
539
// Deflate the specified ObjectMonitor if not in-use. Returns true if it
@@ -723,7 +710,7 @@ void ObjectMonitor::EnterI(JavaThread* current) {
723
710
assert (current->thread_state () == _thread_blocked, " invariant" );
724
711
725
712
// Try the lock - TATAS
726
- if (TryLock (current) > 0 ) {
713
+ if (TryLock (current) == TryLockResult::Success ) {
727
714
assert (_succ != current, " invariant" );
728
715
assert (owner_raw () == current, " invariant" );
729
716
assert (_Responsible != current, " invariant" );
@@ -757,7 +744,7 @@ void ObjectMonitor::EnterI(JavaThread* current) {
757
744
// to the owner. This has subtle but beneficial affinity
758
745
// effects.
759
746
760
- if (TrySpin (current) > 0 ) {
747
+ if (TrySpin (current)) {
761
748
assert (owner_raw () == current, " invariant" );
762
749
assert (_succ != current, " invariant" );
763
750
assert (_Responsible != current, " invariant" );
@@ -794,7 +781,7 @@ void ObjectMonitor::EnterI(JavaThread* current) {
794
781
795
782
// Interference - the CAS failed because _cxq changed. Just retry.
796
783
// As an optional optimization we retry the lock.
797
- if (TryLock (current) > 0 ) {
784
+ if (TryLock (current) == TryLockResult::Success ) {
798
785
assert (_succ != current, " invariant" );
799
786
assert (owner_raw () == current, " invariant" );
800
787
assert (_Responsible != current, " invariant" );
@@ -847,7 +834,9 @@ void ObjectMonitor::EnterI(JavaThread* current) {
847
834
848
835
for (;;) {
849
836
850
- if (TryLock (current) > 0 ) break ;
837
+ if (TryLock (current) == TryLockResult::Success) {
838
+ break ;
839
+ }
851
840
assert (owner_raw () != current, " invariant" );
852
841
853
842
// park self
@@ -862,7 +851,9 @@ void ObjectMonitor::EnterI(JavaThread* current) {
862
851
current->_ParkEvent ->park ();
863
852
}
864
853
865
- if (TryLock (current) > 0 ) break ;
854
+ if (TryLock (current) == TryLockResult::Success) {
855
+ break ;
856
+ }
866
857
867
858
if (try_set_owner_from (DEFLATER_MARKER, current) == DEFLATER_MARKER) {
868
859
// Cancelled the in-progress async deflation by changing owner from
@@ -895,7 +886,9 @@ void ObjectMonitor::EnterI(JavaThread* current) {
895
886
// We can defer clearing _succ until after the spin completes
896
887
// TrySpin() must tolerate being called with _succ == current.
897
888
// Try yet another round of adaptive spinning.
898
- if (TrySpin (current) > 0 ) break ;
889
+ if (TrySpin (current)) {
890
+ break ;
891
+ }
899
892
900
893
// We can find that we were unpark()ed and redesignated _succ while
901
894
// we were spinning. That's harmless. If we iterate and call park(),
@@ -994,8 +987,9 @@ void ObjectMonitor::ReenterI(JavaThread* current, ObjectWaiter* currentNode) {
994
987
guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, " invariant" );
995
988
assert (owner_raw () != current, " invariant" );
996
989
997
- if (TryLock (current) > 0 ) break ;
998
- if (TrySpin (current) > 0 ) break ;
990
+ if (TrySpin (current)) {
991
+ break ;
992
+ }
999
993
1000
994
{
1001
995
OSThreadContendState osts (current->osthread ());
@@ -1012,7 +1006,9 @@ void ObjectMonitor::ReenterI(JavaThread* current, ObjectWaiter* currentNode) {
1012
1006
// Try again, but just so we distinguish between futile wakeups and
1013
1007
// successful wakeups. The following test isn't algorithmically
1014
1008
// necessary, but it helps us maintain sensible statistics.
1015
- if (TryLock (current) > 0 ) break ;
1009
+ if (TryLock (current) == TryLockResult::Success) {
1010
+ break ;
1011
+ }
1016
1012
1017
1013
// The lock is still contested.
1018
1014
// Keep a tally of the # of futile wakeups.
@@ -1854,39 +1850,78 @@ void ObjectMonitor::notifyAll(TRAPS) {
1854
1850
// hysteresis control to damp the transition rate between spinning and
1855
1851
// not spinning.
1856
1852
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;
1865
1866
}
1866
- return 0 ;
1867
+ return x + Knob_Bonus;
1868
+ } else {
1869
+ return spin_duration;
1867
1870
}
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
+ }
1868
1887
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);
1878
1894
}
1879
- return 1 ;
1895
+ return true ;
1896
+ } else if (status == TryLockResult::Interference) {
1897
+ break ;
1880
1898
}
1881
1899
SpinPause ();
1882
1900
}
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
+ }
1883
1912
1884
1913
// Admission control - verify preconditions for spinning
1885
1914
//
1886
1915
// We always spin a little bit, just to prevent _SpinDuration == 0 from
1887
1916
// becoming an absorbing state. Put another way, we spin briefly to
1888
1917
// sample, just in case the system load, parallelism, contention, or lock
1889
1918
// 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
+
1890
1925
//
1891
1926
// Consider the following alternative:
1892
1927
// Periodically set _SpinDuration = _SpinLimit and try a long/full
@@ -1895,8 +1930,8 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
1895
1930
// This takes us into the realm of 1-out-of-N spinning, where we
1896
1931
// hold the duration constant but vary the frequency.
1897
1932
1898
- ctr = _SpinDuration;
1899
- if (ctr <= 0 ) return 0 ;
1933
+ int ctr = _SpinDuration;
1934
+ if (ctr <= 0 ) return false ;
1900
1935
1901
1936
// We're good to spin ... spin ingress.
1902
1937
// CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades
@@ -1928,7 +1963,7 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
1928
1963
// might update the poll values and we could be in a thread_blocked
1929
1964
// state here which is not allowed so just check the poll.
1930
1965
if (SafepointMechanism::local_poll_armed (current)) {
1931
- goto Abort; // abrupt spin egress
1966
+ break ;
1932
1967
}
1933
1968
SpinPause ();
1934
1969
}
@@ -1960,26 +1995,21 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
1960
1995
// If we acquired the lock early in the spin cycle it
1961
1996
// makes sense to increase _SpinDuration proportionally.
1962
1997
// 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 ;
1969
2000
}
1970
2001
1971
2002
// The CAS failed ... we can take any of the following actions:
1972
2003
// * penalize: ctr -= CASPenalty
1973
- // * exit spin with prejudice -- goto Abort;
2004
+ // * exit spin with prejudice -- abort without adapting spinner
1974
2005
// * exit spin without prejudice.
1975
2006
// * Since CAS is high-latency, retry again immediately.
1976
- prv = ox;
1977
- goto Abort;
2007
+ break ;
1978
2008
}
1979
2009
1980
2010
// Did lock ownership change hands ?
1981
2011
if (ox != prv && prv != nullptr ) {
1982
- goto Abort ;
2012
+ break ;
1983
2013
}
1984
2014
prv = ox;
1985
2015
@@ -1989,30 +2019,23 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
1989
2019
}
1990
2020
1991
2021
// 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);
2003
2024
}
2004
2025
2005
- Abort:
2006
2026
if (_succ == current) {
2007
2027
_succ = nullptr ;
2008
2028
// Invariant: after setting succ=null a contending thread
2009
2029
// must recheck-retry _owner before parking. This usually happens
2010
2030
// in the normal usage of TrySpin(), but it's safest
2011
2031
// to make TrySpin() as foolproof as possible.
2012
2032
OrderAccess::fence ();
2013
- if (TryLock (current) > 0 ) return 1 ;
2033
+ if (TryLock (current) == TryLockResult::Success) {
2034
+ return true ;
2035
+ }
2014
2036
}
2015
- return 0 ;
2037
+
2038
+ return false ;
2016
2039
}
2017
2040
2018
2041
0 commit comments