# HG changeset patch # User mikael # Date 1537252034 25200 # Mon Sep 17 23:27:14 2018 -0700 # Node ID 717283f53aee658cd1b2a43dc9257964381a1f8e # Parent 1740b162dc0e98305572dc3444188f25af200bbb imported patch syncknobs-00-base diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -2204,29 +2204,6 @@ } } -static char * kvGet(char * kvList, const char * Key) { - if (kvList == NULL) return NULL; - size_t n = strlen(Key); - char * Search; - for (Search = kvList; *Search; Search += strlen(Search) + 1) { - if (strncmp (Search, Key, n) == 0) { - if (Search[n] == '=') return Search + n + 1; - if (Search[n] == 0) return(char *) "1"; - } - } - return NULL; -} - -static int kvGetInt(char * kvList, const char * Key, int Default) { - char * v = kvGet(kvList, Key); - int rslt = v ? ::strtol(v, NULL, 0) : Default; - if (Knob_ReportSettings && v != NULL) { - tty->print_cr("INFO: SyncKnob: %s %d(%d)", Key, rslt, Default) ; - tty->flush(); - } - return rslt; -} - void ObjectMonitor::DeferredInitialize() { if (InitDone > 0) return; if (Atomic::cmpxchg (-1, &InitDone, 0) != 0) { @@ -2237,55 +2214,6 @@ // One-shot global initialization ... // The initialization is idempotent, so we don't need locks. // In the future consider doing this via os::init_2(). - // SyncKnobs consist of = pairs in the style - // of environment variables. Start by converting ':' to NUL. - - if (SyncKnobs == NULL) SyncKnobs = ""; - - size_t sz = strlen(SyncKnobs); - char * knobs = (char *) os::malloc(sz + 2, mtInternal); - if (knobs == NULL) { - vm_exit_out_of_memory(sz + 2, OOM_MALLOC_ERROR, "Parse SyncKnobs"); - guarantee(0, "invariant"); - } - strcpy(knobs, SyncKnobs); - knobs[sz+1] = 0; - for (char * p = knobs; *p; p++) { - if (*p == ':') *p = 0; - } - - #define SETKNOB(x) { Knob_##x = kvGetInt(knobs, #x, Knob_##x); } - SETKNOB(ReportSettings); - SETKNOB(ExitRelease); - SETKNOB(InlineNotify); - SETKNOB(Verbose); - SETKNOB(VerifyInUse); - SETKNOB(VerifyMatch); - SETKNOB(FixedSpin); - SETKNOB(SpinLimit); - SETKNOB(SpinBase); - SETKNOB(SpinBackOff); - SETKNOB(CASPenalty); - SETKNOB(OXPenalty); - SETKNOB(SpinSetSucc); - SETKNOB(SuccEnabled); - SETKNOB(SuccRestrict); - SETKNOB(Penalty); - SETKNOB(Bonus); - SETKNOB(BonusB); - SETKNOB(Poverty); - SETKNOB(SpinAfterFutile); - SETKNOB(UsePause); - SETKNOB(SpinEarly); - SETKNOB(OState); - SETKNOB(MaxSpinners); - SETKNOB(PreSpin); - SETKNOB(ExitPolicy); - SETKNOB(QMode); - SETKNOB(ResetEvent); - SETKNOB(MoveNotifyee); - SETKNOB(FastHSSEC); - #undef SETKNOB if (os::is_MP()) { BackOffMask = (1 << Knob_SpinBackOff) - 1; @@ -2300,7 +2228,6 @@ Knob_FixedSpin = -1; } - os::free(knobs); OrderAccess::fence(); InitDone = 1; } # HG changeset patch # User mikael # Date 1537252042 25200 # Mon Sep 17 23:27:22 2018 -0700 # Node ID b50b0a381b434f58b0437d447e423c8b9ec31603 # Parent 717283f53aee658cd1b2a43dc9257964381a1f8e imported patch syncknobs-01-Knob_ReportSettings diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -108,7 +108,6 @@ int ObjectMonitor::Knob_VerifyMatch = 0; int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_ReportSettings = 0; static int Knob_SpinBase = 0; // Floor AKA SpinMin static int Knob_SpinBackOff = 0; // spin-loop backoff static int Knob_CASPenalty = -1; // Penalty for failed CAS @@ -2217,9 +2216,6 @@ if (os::is_MP()) { BackOffMask = (1 << Knob_SpinBackOff) - 1; - if (Knob_ReportSettings) { - tty->print_cr("INFO: BackOffMask=0x%X", BackOffMask); - } // CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1) } else { Knob_SpinLimit = 0; # HG changeset patch # User mikael # Date 1537252051 25200 # Mon Sep 17 23:27:31 2018 -0700 # Node ID 750bdfe8744984705b689bb3bb0b038bd1a90749 # Parent b50b0a381b434f58b0437d447e423c8b9ec31603 imported patch syncknobs-02-Knob_SpinBackOff diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -109,7 +109,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - static int Knob_SpinBase = 0; // Floor AKA SpinMin -static int Knob_SpinBackOff = 0; // spin-loop backoff static int Knob_CASPenalty = -1; // Penalty for failed CAS static int Knob_OXPenalty = -1; // Penalty for observed _owner change static int Knob_SpinSetSucc = 1; // spinners set the _succ field @@ -2215,8 +2214,7 @@ // In the future consider doing this via os::init_2(). if (os::is_MP()) { - BackOffMask = (1 << Knob_SpinBackOff) - 1; - // CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1) + BackOffMask = 0; } else { Knob_SpinLimit = 0; Knob_SpinBase = 0; # HG changeset patch # User mikael # Date 1537252059 25200 # Mon Sep 17 23:27:39 2018 -0700 # Node ID 05c2a1d0a6bbd4ca74e4d65c957dcc1dc37d8664 # Parent 750bdfe8744984705b689bb3bb0b038bd1a90749 imported patch syncknobs-03-BackOffMask diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -127,7 +127,6 @@ static int Knob_ExitPolicy = 0; static int Knob_PreSpin = 10; // 20-100 likely better static int Knob_ResetEvent = 0; -static int BackOffMask = 0; static int Knob_FastHSSEC = 0; static int Knob_MoveNotifyee = 2; // notify() - disposition of notifyee @@ -1873,8 +1872,6 @@ // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades // when preparing to LD...CAS _owner, etc and the CAS is likely // to succeed. - int hits = 0; - int msk = 0; int caspty = Knob_CASPenalty; int oxpty = Knob_OXPenalty; int sss = Knob_SpinSetSucc; @@ -1906,29 +1903,6 @@ if (Knob_UsePause & 2) SpinPause(); - // Exponential back-off ... Stay off the bus to reduce coherency traffic. - // This is useful on classic SMP systems, but is of less utility on - // N1-style CMT platforms. - // - // Trade-off: lock acquisition latency vs coherency bandwidth. - // Lock hold times are typically short. A histogram - // of successful spin attempts shows that we usually acquire - // the lock early in the spin. That suggests we want to - // sample _owner frequently in the early phase of the spin, - // but then back-off and sample less frequently as the spin - // progresses. The back-off makes a good citizen on SMP big - // SMP systems. Oversampling _owner can consume excessive - // coherency bandwidth. Relatedly, if we _oversample _owner we - // can inadvertently interfere with the the ST m->owner=null. - // executed by the lock owner. - if (ctr & msk) continue; - ++hits; - if ((hits & 0xF) == 0) { - // The 0xF, above, corresponds to the exponent. - // Consider: (msk+1)|msk - msk = ((msk << 2)|3) & BackOffMask; - } - // Probe _owner with TATAS // If this thread observes the monitor transition or flicker // from locked to unlocked to locked, then the odds that this @@ -2213,9 +2187,7 @@ // The initialization is idempotent, so we don't need locks. // In the future consider doing this via os::init_2(). - if (os::is_MP()) { - BackOffMask = 0; - } else { + if (!os::is_MP()) { Knob_SpinLimit = 0; Knob_SpinBase = 0; Knob_PreSpin = 0; # HG changeset patch # User mikael # Date 1537252067 25200 # Mon Sep 17 23:27:47 2018 -0700 # Node ID 5836df536c1b0850b9e6132422970d72244129ff # Parent 05c2a1d0a6bbd4ca74e4d65c957dcc1dc37d8664 imported patch syncknobs-04-Knob_ExitRelease diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -101,7 +101,6 @@ // The knob* variables are effectively final. Once set they should // never be modified hence. Consider using __read_mostly with GCC. -int ObjectMonitor::Knob_ExitRelease = 0; int ObjectMonitor::Knob_InlineNotify = 1; int ObjectMonitor::Knob_Verbose = 0; int ObjectMonitor::Knob_VerifyInUse = 0; diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -195,7 +195,6 @@ static PerfCounter * _sync_Deflations; static PerfLongVariable * _sync_MonExtant; - static int Knob_ExitRelease; static int Knob_InlineNotify; static int Knob_Verbose; static int Knob_VerifyInUse; diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -1959,7 +1959,7 @@ // // ensure_join() ignores IllegalThreadStateExceptions, and so does // ObjectSynchronizer::release_monitors_owned_by_thread(). - if (exit_type == jni_detach || ObjectMonitor::Knob_ExitRelease) { + if (exit_type == jni_detach) { // Sanity check even though JNI DetachCurrentThread() would have // returned JNI_ERR if there was a Java frame. JavaThread exit // should be done executing Java code by the time we get here. # HG changeset patch # User mikael # Date 1537252079 25200 # Mon Sep 17 23:27:59 2018 -0700 # Node ID ea72067700953fcaf5057a7ac8dbe3e7625208cd # Parent 5836df536c1b0850b9e6132422970d72244129ff imported patch syncknobs-05-Knob_InlineNotify diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -543,10 +543,7 @@ case vmIntrinsics::_notify: case vmIntrinsics::_notifyAll: - if (ObjectMonitor::Knob_InlineNotify) { - return inline_notify(intrinsic_id()); - } - return false; + return inline_notify(intrinsic_id()); case vmIntrinsics::_addExactI: return inline_math_addExactI(false /* add */); case vmIntrinsics::_addExactL: return inline_math_addExactL(false /* add */); diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -101,7 +101,6 @@ // The knob* variables are effectively final. Once set they should // never be modified hence. Consider using __read_mostly with GCC. -int ObjectMonitor::Knob_InlineNotify = 1; int ObjectMonitor::Knob_Verbose = 0; int ObjectMonitor::Knob_VerifyInUse = 0; int ObjectMonitor::Knob_VerifyMatch = 0; diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -195,7 +195,6 @@ static PerfCounter * _sync_Deflations; static PerfLongVariable * _sync_MonExtant; - static int Knob_InlineNotify; static int Knob_Verbose; static int Knob_VerifyInUse; static int Knob_VerifyMatch; # HG changeset patch # User mikael # Date 1537252090 25200 # Mon Sep 17 23:28:10 2018 -0700 # Node ID 70b036fced36c97727d06d7f78c626b3b4492c02 # Parent ea72067700953fcaf5057a7ac8dbe3e7625208cd imported patch syncknobs-06-Knob_Verbose diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -101,7 +101,6 @@ // The knob* variables are effectively final. Once set they should // never be modified hence. Consider using __read_mostly with GCC. -int ObjectMonitor::Knob_Verbose = 0; int ObjectMonitor::Knob_VerifyInUse = 0; int ObjectMonitor::Knob_VerifyMatch = 0; int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -195,7 +195,6 @@ static PerfCounter * _sync_Deflations; static PerfLongVariable * _sync_MonExtant; - static int Knob_Verbose; static int Knob_VerifyInUse; static int Knob_VerifyMatch; static int Knob_SpinLimit; diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1050,22 +1050,11 @@ // TODO: assert thread state is reasonable if (ForceMonitorScavenge == 0 && Atomic::xchg (1, &ForceMonitorScavenge) == 0) { - if (ObjectMonitor::Knob_Verbose) { - tty->print_cr("INFO: Monitor scavenge - Induced STW @%s (%d)", - Whence, ForceMonitorScavenge) ; - tty->flush(); - } // Induce a 'null' safepoint to scavenge monitors // Must VM_Operation instance be heap allocated as the op will be enqueue and posted // to the VMthread and have a lifespan longer than that of this activation record. // The VMThread will delete the op when completed. VMThread::execute(new VM_ScavengeMonitors()); - - if (ObjectMonitor::Knob_Verbose) { - tty->print_cr("INFO: Monitor scavenge - STW posted @%s (%d)", - Whence, ForceMonitorScavenge) ; - tty->flush(); - } } } @@ -1763,14 +1752,6 @@ // Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree. - if (ObjectMonitor::Knob_Verbose) { - tty->print_cr("INFO: Deflate: InCirc=%d InUse=%d Scavenged=%d " - "ForceMonitorScavenge=%d : pop=%d free=%d", - counters->nInCirculation, counters->nInuse, counters->nScavenged, ForceMonitorScavenge, - gMonitorPopulation, gMonitorFreeCount); - tty->flush(); - } - ForceMonitorScavenge = 0; // Reset OM_PERFDATA_OP(Deflations, inc(counters->nScavenged)); diff --git a/src/hotspot/share/runtime/vframe.cpp b/src/hotspot/share/runtime/vframe.cpp --- a/src/hotspot/share/runtime/vframe.cpp +++ b/src/hotspot/share/runtime/vframe.cpp @@ -255,11 +255,6 @@ } } print_locked_object_class_name(st, Handle(THREAD, monitor->owner()), lock_state); - if (ObjectMonitor::Knob_Verbose && mark != NULL) { - st->print("\t- lockbits="); - mark->print_on(st); - st->cr(); - } found_first_monitor = true; } # HG changeset patch # User mikael # Date 1537252102 25200 # Mon Sep 17 23:28:22 2018 -0700 # Node ID 2302fab12e4a51d05139217129a6e3cc81e29edf # Parent 70b036fced36c97727d06d7f78c626b3b4492c02 imported patch syncknobs-07-Knob_VerifyInUse diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -101,7 +101,6 @@ // The knob* variables are effectively final. Once set they should // never be modified hence. Consider using __read_mostly with GCC. -int ObjectMonitor::Knob_VerifyInUse = 0; int ObjectMonitor::Knob_VerifyMatch = 0; int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -195,7 +195,6 @@ static PerfCounter * _sync_Deflations; static PerfLongVariable * _sync_MonExtant; - static int Knob_VerifyInUse; static int Knob_VerifyMatch; static int Knob_SpinLimit; diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1099,9 +1099,6 @@ m->FreeNext = Self->omInUseList; Self->omInUseList = m; Self->omInUseCount++; - if (ObjectMonitor::Knob_VerifyInUse) { - verifyInUse(Self); - } } else { m->FreeNext = NULL; } @@ -1239,9 +1236,6 @@ } extracted = true; Self->omInUseCount--; - if (ObjectMonitor::Knob_VerifyInUse) { - verifyInUse(Self); - } break; } } @@ -1777,9 +1771,6 @@ // Adjust counters counters->nInCirculation += thread->omInUseCount; thread->omInUseCount -= deflated_count; - if (ObjectMonitor::Knob_VerifyInUse) { - verifyInUse(thread); - } counters->nScavenged += deflated_count; counters->nInuse += thread->omInUseCount; # HG changeset patch # User mikael # Date 1537252113 25200 # Mon Sep 17 23:28:33 2018 -0700 # Node ID b27f9b4d1984c37aa16d84ced68d920882127928 # Parent 2302fab12e4a51d05139217129a6e3cc81e29edf imported patch syncknobs-08-Knob_VerifyMatch diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -101,7 +101,6 @@ // The knob* variables are effectively final. Once set they should // never be modified hence. Consider using __read_mostly with GCC. -int ObjectMonitor::Knob_VerifyMatch = 0; int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - static int Knob_SpinBase = 0; // Floor AKA SpinMin diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -195,7 +195,6 @@ static PerfCounter * _sync_Deflations; static PerfLongVariable * _sync_MonExtant; - static int Knob_VerifyMatch; static int Knob_SpinLimit; void* operator new (size_t size) throw(); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1799,15 +1799,6 @@ ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {} void do_monitor(ObjectMonitor* mid) { if (mid->owner() == THREAD) { - if (ObjectMonitor::Knob_VerifyMatch != 0) { - ResourceMark rm; - Handle obj(THREAD, (oop) mid->object()); - tty->print("INFO: unexpected locked object:"); - javaVFrame::print_locked_object_class_name(tty, obj, "locked"); - fatal("exiting JavaThread=" INTPTR_FORMAT - " unexpectedly owns ObjectMonitor=" INTPTR_FORMAT, - p2i(THREAD), p2i(mid)); - } (void)mid->complete_exit(CHECK); } } # HG changeset patch # User mikael # Date 1537252124 25200 # Mon Sep 17 23:28:44 2018 -0700 # Node ID 5ab994c00c9c6ba1bd227c58b1b3b7202d2a363d # Parent b27f9b4d1984c37aa16d84ced68d920882127928 imported patch syncknobs-09-Knob_SpinBase diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -103,7 +103,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_SpinBase = 0; // Floor AKA SpinMin static int Knob_CASPenalty = -1; // Penalty for failed CAS static int Knob_OXPenalty = -1; // Penalty for observed _owner change static int Knob_SpinSetSucc = 1; // spinners set the _succ field @@ -1846,7 +1845,6 @@ // hold the duration constant but vary the frequency. ctr = _SpinDuration; - if (ctr < Knob_SpinBase) ctr = Knob_SpinBase; if (ctr <= 0) return 0; if (Knob_SuccRestrict && _succ != NULL) return 0; @@ -2184,7 +2182,6 @@ if (!os::is_MP()) { Knob_SpinLimit = 0; - Knob_SpinBase = 0; Knob_PreSpin = 0; Knob_FixedSpin = -1; } # HG changeset patch # User mikael # Date 1537252132 25200 # Mon Sep 17 23:28:52 2018 -0700 # Node ID 0809ce67992dffab5541b6ce9b8edd72b850fd60 # Parent 5ab994c00c9c6ba1bd227c58b1b3b7202d2a363d imported patch syncknobs-10-Knob_CASPenalty diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -103,7 +103,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_CASPenalty = -1; // Penalty for failed CAS static int Knob_OXPenalty = -1; // Penalty for observed _owner change static int Knob_SpinSetSucc = 1; // spinners set the _succ field static int Knob_SpinEarly = 1; @@ -1865,7 +1864,6 @@ // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades // when preparing to LD...CAS _owner, etc and the CAS is likely // to succeed. - int caspty = Knob_CASPenalty; int oxpty = Knob_OXPenalty; int sss = Knob_SpinSetSucc; if (sss && _succ == NULL) _succ = Self; @@ -1933,15 +1931,12 @@ } // The CAS failed ... we can take any of the following actions: - // * penalize: ctr -= Knob_CASPenalty + // * penalize: ctr -= CASPenalty // * exit spin with prejudice -- goto Abort; // * exit spin without prejudice. // * Since CAS is high-latency, retry again immediately. prv = ox; - if (caspty == -2) break; - if (caspty == -1) goto Abort; - ctr -= caspty; - continue; + goto Abort; } // Did lock ownership change hands ? # HG changeset patch # User mikael # Date 1537252141 25200 # Mon Sep 17 23:29:01 2018 -0700 # Node ID 0c5ff83c4f9fd8d60e2952c5179b77a91e4c2c85 # Parent 0809ce67992dffab5541b6ce9b8edd72b850fd60 imported patch syncknobs-11-Knob_OXPenalty diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -103,7 +103,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_OXPenalty = -1; // Penalty for observed _owner change static int Knob_SpinSetSucc = 1; // spinners set the _succ field static int Knob_SpinEarly = 1; static int Knob_SuccEnabled = 1; // futile wake throttling @@ -1864,7 +1863,6 @@ // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades // when preparing to LD...CAS _owner, etc and the CAS is likely // to succeed. - int oxpty = Knob_OXPenalty; int sss = Knob_SpinSetSucc; if (sss && _succ == NULL) _succ = Self; Thread * prv = NULL; @@ -1941,9 +1939,7 @@ // Did lock ownership change hands ? if (ox != prv && prv != NULL) { - if (oxpty == -2) break; - if (oxpty == -1) goto Abort; - ctr -= oxpty; + goto Abort; } prv = ox; # HG changeset patch # User mikael # Date 1537252149 25200 # Mon Sep 17 23:29:09 2018 -0700 # Node ID 5e24ebb2cbb4d6ecfd67ec425a073d37c6c8fb05 # Parent 0c5ff83c4f9fd8d60e2952c5179b77a91e4c2c85 imported patch syncknobs-12-Knob_SpinSetSucc diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -103,7 +103,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_SpinSetSucc = 1; // spinners set the _succ field static int Knob_SpinEarly = 1; static int Knob_SuccEnabled = 1; // futile wake throttling static int Knob_SuccRestrict = 0; // Limit successors + spinners to at-most-one @@ -1863,8 +1862,9 @@ // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades // when preparing to LD...CAS _owner, etc and the CAS is likely // to succeed. - int sss = Knob_SpinSetSucc; - if (sss && _succ == NULL) _succ = Self; + if (_succ == NULL) { + _succ = Self; + } Thread * prv = NULL; // There are three ways to exit the following loop: @@ -1908,7 +1908,7 @@ if (ox == NULL) { // The CAS succeeded -- this thread acquired ownership // Take care of some bookkeeping to exit spin state. - if (sss && _succ == Self) { + if (_succ == Self) { _succ = NULL; } if (MaxSpin > 0) Adjust(&_Spinner, -1); @@ -1950,7 +1950,9 @@ if (Knob_OState && NotRunnable (Self, ox)) { goto Abort; } - if (sss && _succ == NULL) _succ = Self; + if (_succ == NULL) { + _succ = Self; + } } // Spin failed with prejudice -- reduce _SpinDuration. @@ -1969,7 +1971,7 @@ Abort: if (MaxSpin >= 0) Adjust(&_Spinner, -1); - if (sss && _succ == Self) { + if (_succ == Self) { _succ = NULL; // Invariant: after setting succ=null a contending thread // must recheck-retry _owner before parking. This usually happens # HG changeset patch # User mikael # Date 1537252157 25200 # Mon Sep 17 23:29:17 2018 -0700 # Node ID 5482676f4b81b485caf8691d174b885b1e6557cb # Parent 5e24ebb2cbb4d6ecfd67ec425a073d37c6c8fb05 imported patch syncknobs-13-Knob_SpinEarly diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -103,7 +103,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_SpinEarly = 1; static int Knob_SuccEnabled = 1; // futile wake throttling static int Knob_SuccRestrict = 0; // Limit successors + spinners to at-most-one static int Knob_MaxSpinners = -1; // Should be a function of # CPUs @@ -287,7 +286,7 @@ // transitions. The following spin is strictly optional ... // Note that if we acquire the monitor from an initial spin // we forgo posting JVMTI events and firing DTRACE probes. - if (Knob_SpinEarly && TrySpin (Self) > 0) { + if (TrySpin(Self) > 0) { assert(_owner == Self, "invariant"); assert(_recursions == 0, "invariant"); assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant"); @@ -449,7 +448,7 @@ // to the owner. This has subtle but beneficial affinity // effects. - if (TrySpin (Self) > 0) { + if (TrySpin(Self) > 0) { assert(_owner == Self, "invariant"); assert(_succ != Self, "invariant"); assert(_Responsible != Self, "invariant"); # HG changeset patch # User mikael # Date 1537252165 25200 # Mon Sep 17 23:29:25 2018 -0700 # Node ID 2eb7bd71a5adb7587d85b5a84c210e443b8a2e84 # Parent 5482676f4b81b485caf8691d174b885b1e6557cb imported patch syncknobs-14-Knob_SuccEnabled diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -103,7 +103,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_SuccEnabled = 1; // futile wake throttling static int Knob_SuccRestrict = 0; // Limit successors + spinners to at-most-one static int Knob_MaxSpinners = -1; // Should be a function of # CPUs static int Knob_Bonus = 100; // spin success bonus @@ -1242,7 +1241,7 @@ // 2. ST _owner = NULL // 3. unpark(wakee) - _succ = Knob_SuccEnabled ? Wakee->_thread : NULL; + _succ = Wakee->_thread; ParkEvent * Trigger = Wakee->_event; // Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again. # HG changeset patch # User mikael # Date 1537252174 25200 # Mon Sep 17 23:29:34 2018 -0700 # Node ID d523a67001060d3fdfa212b4f28ebb7b62123e81 # Parent 2eb7bd71a5adb7587d85b5a84c210e443b8a2e84 imported patch syncknobs-15-Knob_SuccRestrict diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -103,7 +103,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_SuccRestrict = 0; // Limit successors + spinners to at-most-one static int Knob_MaxSpinners = -1; // Should be a function of # CPUs static int Knob_Bonus = 100; // spin success bonus static int Knob_BonusB = 100; // spin success bonus @@ -1842,7 +1841,6 @@ ctr = _SpinDuration; if (ctr <= 0) return 0; - if (Knob_SuccRestrict && _succ != NULL) return 0; if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) { return 0; } # HG changeset patch # User mikael # Date 1537252182 25200 # Mon Sep 17 23:29:42 2018 -0700 # Node ID b40a9fb66e401cb2415681cfd602b86076776046 # Parent d523a67001060d3fdfa212b4f28ebb7b62123e81 imported patch syncknobs-16-Knob_MaxSpinners diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -103,7 +103,6 @@ int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - -static int Knob_MaxSpinners = -1; // Should be a function of # CPUs static int Knob_Bonus = 100; // spin success bonus static int Knob_BonusB = 100; // spin success bonus static int Knob_Penalty = 200; // spin failure penalty @@ -1333,12 +1332,6 @@ THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner"); } -static int Adjust(volatile int * adr, int dx) { - int v; - for (v = *adr; Atomic::cmpxchg(v + dx, adr, v) != v; v = *adr) /* empty */; - return v; -} - static void post_monitor_wait_event(EventJavaMonitorWait* event, ObjectMonitor* monitor, jlong notifier_tid, @@ -1845,15 +1838,6 @@ return 0; } - int MaxSpin = Knob_MaxSpinners; - if (MaxSpin >= 0) { - if (_Spinner > MaxSpin) { - return 0; - } - // Slightly racy, but benign ... - Adjust(&_Spinner, 1); - } - // We're good to spin ... spin ingress. // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades // when preparing to LD...CAS _owner, etc and the CAS is likely @@ -1907,7 +1891,6 @@ if (_succ == Self) { _succ = NULL; } - if (MaxSpin > 0) Adjust(&_Spinner, -1); // Increase _SpinDuration : // The spin was successful (profitable) so we tend toward @@ -1966,7 +1949,6 @@ } Abort: - if (MaxSpin >= 0) Adjust(&_Spinner, -1); if (_succ == Self) { _succ = NULL; // Invariant: after setting succ=null a contending thread # HG changeset patch # User mikael # Date 1537252190 25200 # Mon Sep 17 23:29:50 2018 -0700 # Node ID 5e2e10de92447e5ea7fecd094f8139d1987f2d4d # Parent b40a9fb66e401cb2415681cfd602b86076776046 imported patch syncknobs-17-Knob_SpinAfterFutile diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -107,7 +107,6 @@ static int Knob_BonusB = 100; // spin success bonus static int Knob_Penalty = 200; // spin failure penalty static int Knob_Poverty = 1000; -static int Knob_SpinAfterFutile = 1; // Spin after returning from park() static int Knob_FixedSpin = 0; static int Knob_OState = 3; // Spinner checks thread state of _owner static int Knob_UsePause = 1; @@ -567,7 +566,7 @@ // We can defer clearing _succ until after the spin completes // TrySpin() must tolerate being called with _succ == Self. // Try yet another round of adaptive spinning. - if ((Knob_SpinAfterFutile & 1) && TrySpin(Self) > 0) break; + if (TrySpin(Self) > 0) break; // We can find that we were unpark()ed and redesignated _succ while // we were spinning. That's harmless. If we iterate and call park(), @@ -659,9 +658,7 @@ // contended slow-path from EnterI(). We use ReenterI() only for // monitor reentry in wait(). // -// In the future we should reconcile EnterI() and ReenterI(), adding -// Knob_Reset and Knob_SpinAfterFutile support and restructuring the -// loop accordingly. +// In the future we should reconcile EnterI() and ReenterI(). void ObjectMonitor::ReenterI(Thread * Self, ObjectWaiter * SelfNode) { assert(Self != NULL, "invariant"); # HG changeset patch # User mikael # Date 1537252199 25200 # Mon Sep 17 23:29:59 2018 -0700 # Node ID 6cecfc3535805d77cd699706ecce90ef8ae99b42 # Parent 5e2e10de92447e5ea7fecd094f8139d1987f2d4d imported patch syncknobs-18-Knob_OState diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -108,7 +108,6 @@ static int Knob_Penalty = 200; // spin failure penalty static int Knob_Poverty = 1000; static int Knob_FixedSpin = 0; -static int Knob_OState = 3; // Spinner checks thread state of _owner static int Knob_UsePause = 1; static int Knob_ExitPolicy = 0; static int Knob_PreSpin = 10; // 20-100 likely better @@ -1831,7 +1830,7 @@ ctr = _SpinDuration; if (ctr <= 0) return 0; - if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) { + if (NotRunnable(Self, (Thread *) _owner)) { return 0; } @@ -1923,7 +1922,7 @@ // The owner must be executing in order to drop the lock. // Spinning while the owner is OFFPROC is idiocy. // Consider: ctr -= RunnablePenalty ; - if (Knob_OState && NotRunnable (Self, ox)) { + if (NotRunnable(Self, ox)) { goto Abort; } if (_succ == NULL) { # HG changeset patch # User mikael # Date 1537252207 25200 # Mon Sep 17 23:30:07 2018 -0700 # Node ID 129e6bb4263130c8f2c6e35e925b30d25995830f # Parent 6cecfc3535805d77cd699706ecce90ef8ae99b42 imported patch syncknobs-19-Knob_UsePause diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -108,7 +108,6 @@ static int Knob_Penalty = 200; // spin failure penalty static int Knob_Poverty = 1000; static int Knob_FixedSpin = 0; -static int Knob_UsePause = 1; static int Knob_ExitPolicy = 0; static int Knob_PreSpin = 10; // 20-100 likely better static int Knob_ResetEvent = 0; @@ -1863,11 +1862,9 @@ if (SafepointMechanism::poll(Self)) { goto Abort; // abrupt spin egress } - if (Knob_UsePause & 1) SpinPause(); + SpinPause(); } - if (Knob_UsePause & 2) SpinPause(); - // Probe _owner with TATAS // If this thread observes the monitor transition or flicker // from locked to unlocked to locked, then the odds that this # HG changeset patch # User mikael # Date 1537252216 25200 # Mon Sep 17 23:30:16 2018 -0700 # Node ID ae961aeeb48cdbe78c63556aa21a6dc3d742249b # Parent 129e6bb4263130c8f2c6e35e925b30d25995830f imported patch syncknobs-20-Knob_ExitPolicy diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -108,7 +108,6 @@ static int Knob_Penalty = 200; // spin failure penalty static int Knob_Poverty = 1000; static int Knob_FixedSpin = 0; -static int Knob_ExitPolicy = 0; static int Knob_PreSpin = 10; // 20-100 likely better static int Knob_ResetEvent = 0; @@ -908,89 +907,63 @@ for (;;) { assert(THREAD == _owner, "invariant"); - if (Knob_ExitPolicy == 0) { - // release semantics: prior loads and stores from within the critical section - // must not float (reorder) past the following store that drops the lock. - // On SPARC that requires MEMBAR #loadstore|#storestore. - // But of course in TSO #loadstore|#storestore is not required. - // I'd like to write one of the following: - // A. OrderAccess::release() ; _owner = NULL - // B. OrderAccess::loadstore(); OrderAccess::storestore(); _owner = NULL; - // Unfortunately OrderAccess::release() and OrderAccess::loadstore() both - // store into a _dummy variable. That store is not needed, but can result - // in massive wasteful coherency traffic on classic SMP systems. - // Instead, I use release_store(), which is implemented as just a simple - // ST on x64, x86 and SPARC. - OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock - OrderAccess::storeload(); // See if we need to wake a successor - if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { - return; - } - // Other threads are blocked trying to acquire the lock. + // release semantics: prior loads and stores from within the critical section + // must not float (reorder) past the following store that drops the lock. + // On SPARC that requires MEMBAR #loadstore|#storestore. + // But of course in TSO #loadstore|#storestore is not required. + // I'd like to write one of the following: + // A. OrderAccess::release() ; _owner = NULL + // B. OrderAccess::loadstore(); OrderAccess::storestore(); _owner = NULL; + // Unfortunately OrderAccess::release() and OrderAccess::loadstore() both + // store into a _dummy variable. That store is not needed, but can result + // in massive wasteful coherency traffic on classic SMP systems. + // Instead, I use release_store(), which is implemented as just a simple + // ST on x64, x86 and SPARC. + OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock + OrderAccess::storeload(); // See if we need to wake a successor + if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { + return; + } + // Other threads are blocked trying to acquire the lock. - // Normally the exiting thread is responsible for ensuring succession, - // but if other successors are ready or other entering threads are spinning - // then this thread can simply store NULL into _owner and exit without - // waking a successor. The existence of spinners or ready successors - // guarantees proper succession (liveness). Responsibility passes to the - // ready or running successors. The exiting thread delegates the duty. - // More precisely, if a successor already exists this thread is absolved - // of the responsibility of waking (unparking) one. - // - // The _succ variable is critical to reducing futile wakeup frequency. - // _succ identifies the "heir presumptive" thread that has been made - // ready (unparked) but that has not yet run. We need only one such - // successor thread to guarantee progress. - // See http://www.usenix.org/events/jvm01/full_papers/dice/dice.pdf - // section 3.3 "Futile Wakeup Throttling" for details. - // - // Note that spinners in Enter() also set _succ non-null. - // In the current implementation spinners opportunistically set - // _succ so that exiting threads might avoid waking a successor. - // Another less appealing alternative would be for the exiting thread - // to drop the lock and then spin briefly to see if a spinner managed - // to acquire the lock. If so, the exiting thread could exit - // immediately without waking a successor, otherwise the exiting - // thread would need to dequeue and wake a successor. - // (Note that we'd need to make the post-drop spin short, but no - // shorter than the worst-case round-trip cache-line migration time. - // The dropped lock needs to become visible to the spinner, and then - // the acquisition of the lock by the spinner must become visible to - // the exiting thread). + // Normally the exiting thread is responsible for ensuring succession, + // but if other successors are ready or other entering threads are spinning + // then this thread can simply store NULL into _owner and exit without + // waking a successor. The existence of spinners or ready successors + // guarantees proper succession (liveness). Responsibility passes to the + // ready or running successors. The exiting thread delegates the duty. + // More precisely, if a successor already exists this thread is absolved + // of the responsibility of waking (unparking) one. + // + // The _succ variable is critical to reducing futile wakeup frequency. + // _succ identifies the "heir presumptive" thread that has been made + // ready (unparked) but that has not yet run. We need only one such + // successor thread to guarantee progress. + // See http://www.usenix.org/events/jvm01/full_papers/dice/dice.pdf + // section 3.3 "Futile Wakeup Throttling" for details. + // + // Note that spinners in Enter() also set _succ non-null. + // In the current implementation spinners opportunistically set + // _succ so that exiting threads might avoid waking a successor. + // Another less appealing alternative would be for the exiting thread + // to drop the lock and then spin briefly to see if a spinner managed + // to acquire the lock. If so, the exiting thread could exit + // immediately without waking a successor, otherwise the exiting + // thread would need to dequeue and wake a successor. + // (Note that we'd need to make the post-drop spin short, but no + // shorter than the worst-case round-trip cache-line migration time. + // The dropped lock needs to become visible to the spinner, and then + // the acquisition of the lock by the spinner must become visible to + // the exiting thread). - // It appears that an heir-presumptive (successor) must be made ready. - // Only the current lock owner can manipulate the EntryList or - // drain _cxq, so we need to reacquire the lock. If we fail - // to reacquire the lock the responsibility for ensuring succession - // falls to the new owner. - // - if (!Atomic::replace_if_null(THREAD, &_owner)) { - return; - } - } else { - if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { - OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock - OrderAccess::storeload(); - // Ratify the previously observed values. - if (_cxq == NULL || _succ != NULL) { - return; - } - - // inopportune interleaving -- the exiting thread (this thread) - // in the fast-exit path raced an entering thread in the slow-enter - // path. - // We have two choices: - // A. Try to reacquire the lock. - // If the CAS() fails return immediately, otherwise - // we either restart/rerun the exit operation, or simply - // fall-through into the code below which wakes a successor. - // B. If the elements forming the EntryList|cxq are TSM - // we could simply unpark() the lead thread and return - // without having set _succ. - if (!Atomic::replace_if_null(THREAD, &_owner)) { - return; - } - } + // It appears that an heir-presumptive (successor) must be made ready. + // Only the current lock owner can manipulate the EntryList or + // drain _cxq, so we need to reacquire the lock. If we fail + // to reacquire the lock the responsibility for ensuring succession + // falls to the new owner. + // + if (!Atomic::replace_if_null(THREAD, &_owner)) { + return; } guarantee(_owner == THREAD, "invariant"); # HG changeset patch # User mikael # Date 1537252224 25200 # Mon Sep 17 23:30:24 2018 -0700 # Node ID 38133d59ee0750c3258359894ff727f83f45d49d # Parent ae961aeeb48cdbe78c63556aa21a6dc3d742249b imported patch syncknobs-21-Knob_ResetEvent diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -109,7 +109,6 @@ static int Knob_Poverty = 1000; static int Knob_FixedSpin = 0; static int Knob_PreSpin = 10; // 20-100 likely better -static int Knob_ResetEvent = 0; static int Knob_FastHSSEC = 0; static int Knob_MoveNotifyee = 2; // notify() - disposition of notifyee @@ -569,14 +568,8 @@ // we were spinning. That's harmless. If we iterate and call park(), // park() will consume the event and return immediately and we'll // just spin again. This pattern can repeat, leaving _succ to simply - // spin on a CPU. Enable Knob_ResetEvent to clear pending unparks(). - // Alternately, we can sample fired() here, and if set, forgo spinning - // in the next iteration. + // spin on a CPU. - if ((Knob_ResetEvent & 1) && Self->_ParkEvent->fired()) { - Self->_ParkEvent->reset(); - OrderAccess::fence(); - } if (_succ == Self) _succ = NULL; // Invariant: after clearing _succ a thread *must* retry _owner before parking. # HG changeset patch # User mikael # Date 1537252232 25200 # Mon Sep 17 23:30:32 2018 -0700 # Node ID d89245db33c8ac1fee80455ac3e69fc90b813fa4 # Parent 38133d59ee0750c3258359894ff727f83f45d49d imported patch syncknobs-22-Knob_FastHSSEC diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -110,7 +110,6 @@ static int Knob_FixedSpin = 0; static int Knob_PreSpin = 10; // 20-100 likely better -static int Knob_FastHSSEC = 0; static int Knob_MoveNotifyee = 2; // notify() - disposition of notifyee static int Knob_QMode = 0; // EntryList-cxq policy - queue discipline static volatile int InitDone = 0; @@ -1171,22 +1170,8 @@ // ST Self->_suspend_equivalent = false // MEMBAR // LD Self_>_suspend_flags -// -// UPDATE 2007-10-6: since I've replaced the native Mutex/Monitor subsystem -// with a more efficient implementation, the need to use "FastHSSEC" has -// decreased. - Dave - bool ObjectMonitor::ExitSuspendEquivalent(JavaThread * jSelf) { - const int Mode = Knob_FastHSSEC; - if (Mode && !jSelf->is_external_suspend()) { - assert(jSelf->is_suspend_equivalent(), "invariant"); - jSelf->clear_suspend_equivalent(); - if (2 == Mode) OrderAccess::storeload(); - if (!jSelf->is_external_suspend()) return false; - // We raced a suspension -- fall thru into the slow path - jSelf->set_suspend_equivalent(); - } return jSelf->handle_special_suspend_equivalent_condition(); } # HG changeset patch # User mikael # Date 1537252241 25200 # Mon Sep 17 23:30:41 2018 -0700 # Node ID b5abfa28a206e95d1201db79393ef746ea478aa8 # Parent d89245db33c8ac1fee80455ac3e69fc90b813fa4 imported patch syncknobs-23-Knob_MoveNotifyee diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -110,7 +110,6 @@ static int Knob_FixedSpin = 0; static int Knob_PreSpin = 10; // 20-100 likely better -static int Knob_MoveNotifyee = 2; // notify() - disposition of notifyee static int Knob_QMode = 0; // EntryList-cxq policy - queue discipline static volatile int InitDone = 0; @@ -1523,8 +1522,6 @@ // we might just dequeue a thread from the WaitSet and directly unpark() it. void ObjectMonitor::INotify(Thread * Self) { - const int policy = Knob_MoveNotifyee; - Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notify"); ObjectWaiter * iterator = DequeueWaiter(); if (iterator != NULL) { @@ -1535,9 +1532,9 @@ // or head (policy == 0). // b. push it onto the front of the _cxq (policy == 2). // For now we use (b). - if (policy != 4) { - iterator->TState = ObjectWaiter::TS_ENTER; - } + + iterator->TState = ObjectWaiter::TS_ENTER; + iterator->_notified = 1; iterator->_notifier_tid = JFR_THREAD_ID(Self); @@ -1548,67 +1545,19 @@ assert(list != iterator, "invariant"); } - if (policy == 0) { // prepend to EntryList - if (list == NULL) { - iterator->_next = iterator->_prev = NULL; - _EntryList = iterator; - } else { - list->_prev = iterator; - iterator->_next = list; - iterator->_prev = NULL; - _EntryList = iterator; - } - } else if (policy == 1) { // append to EntryList - if (list == NULL) { - iterator->_next = iterator->_prev = NULL; - _EntryList = iterator; - } else { - // CONSIDER: finding the tail currently requires a linear-time walk of - // the EntryList. We can make tail access constant-time by converting to - // a CDLL instead of using our current DLL. - ObjectWaiter * tail; - for (tail = list; tail->_next != NULL; tail = tail->_next) {} - assert(tail != NULL && tail->_next == NULL, "invariant"); - tail->_next = iterator; - iterator->_prev = tail; - iterator->_next = NULL; - } - } else if (policy == 2) { // prepend to cxq - if (list == NULL) { - iterator->_next = iterator->_prev = NULL; - _EntryList = iterator; - } else { - iterator->TState = ObjectWaiter::TS_CXQ; - for (;;) { - ObjectWaiter * front = _cxq; - iterator->_next = front; - if (Atomic::cmpxchg(iterator, &_cxq, front) == front) { - break; - } - } - } - } else if (policy == 3) { // append to cxq + // prepend to cxq + if (list == NULL) { + iterator->_next = iterator->_prev = NULL; + _EntryList = iterator; + } else { iterator->TState = ObjectWaiter::TS_CXQ; for (;;) { - ObjectWaiter * tail = _cxq; - if (tail == NULL) { - iterator->_next = NULL; - if (Atomic::replace_if_null(iterator, &_cxq)) { - break; - } - } else { - while (tail->_next != NULL) tail = tail->_next; - tail->_next = iterator; - iterator->_prev = tail; - iterator->_next = NULL; + ObjectWaiter * front = _cxq; + iterator->_next = front; + if (Atomic::cmpxchg(iterator, &_cxq, front) == front) { break; } } - } else { - ParkEvent * ev = iterator->_event; - iterator->TState = ObjectWaiter::TS_RUN; - OrderAccess::fence(); - ev->unpark(); } // _WaitSetLock protects the wait queue, not the EntryList. We could @@ -1619,9 +1568,7 @@ // on _WaitSetLock so it's not profitable to reduce the length of the // critical section. - if (policy < 4) { - iterator->wait_reenter_begin(this); - } + iterator->wait_reenter_begin(this); } Thread::SpinRelease(&_WaitSetLock); } # HG changeset patch # User mikael # Date 1537252249 25200 # Mon Sep 17 23:30:49 2018 -0700 # Node ID 7d1b32719c87bc7139ae48b5aa3801b398371711 # Parent b5abfa28a206e95d1201db79393ef746ea478aa8 imported patch syncknobs-24-Knob_QMode diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -110,7 +110,6 @@ static int Knob_FixedSpin = 0; static int Knob_PreSpin = 10; // 20-100 likely better -static int Knob_QMode = 0; // EntryList-cxq policy - queue discipline static volatile int InitDone = 0; // ----------------------------------------------------------------------------- @@ -960,93 +959,6 @@ guarantee(_owner == THREAD, "invariant"); ObjectWaiter * w = NULL; - int QMode = Knob_QMode; - - if (QMode == 2 && _cxq != NULL) { - // QMode == 2 : cxq has precedence over EntryList. - // Try to directly wake a successor from the cxq. - // If successful, the successor will need to unlink itself from cxq. - w = _cxq; - assert(w != NULL, "invariant"); - assert(w->TState == ObjectWaiter::TS_CXQ, "Invariant"); - ExitEpilog(Self, w); - return; - } - - if (QMode == 3 && _cxq != NULL) { - // Aggressively drain cxq into EntryList at the first opportunity. - // This policy ensure that recently-run threads live at the head of EntryList. - // Drain _cxq into EntryList - bulk transfer. - // First, detach _cxq. - // The following loop is tantamount to: w = swap(&cxq, NULL) - w = _cxq; - for (;;) { - assert(w != NULL, "Invariant"); - ObjectWaiter * u = Atomic::cmpxchg((ObjectWaiter*)NULL, &_cxq, w); - if (u == w) break; - w = u; - } - assert(w != NULL, "invariant"); - - ObjectWaiter * q = NULL; - ObjectWaiter * p; - for (p = w; p != NULL; p = p->_next) { - guarantee(p->TState == ObjectWaiter::TS_CXQ, "Invariant"); - p->TState = ObjectWaiter::TS_ENTER; - p->_prev = q; - q = p; - } - - // Append the RATs to the EntryList - // TODO: organize EntryList as a CDLL so we can locate the tail in constant-time. - ObjectWaiter * Tail; - for (Tail = _EntryList; Tail != NULL && Tail->_next != NULL; - Tail = Tail->_next) - /* empty */; - if (Tail == NULL) { - _EntryList = w; - } else { - Tail->_next = w; - w->_prev = Tail; - } - - // Fall thru into code that tries to wake a successor from EntryList - } - - if (QMode == 4 && _cxq != NULL) { - // Aggressively drain cxq into EntryList at the first opportunity. - // This policy ensure that recently-run threads live at the head of EntryList. - - // Drain _cxq into EntryList - bulk transfer. - // First, detach _cxq. - // The following loop is tantamount to: w = swap(&cxq, NULL) - w = _cxq; - for (;;) { - assert(w != NULL, "Invariant"); - ObjectWaiter * u = Atomic::cmpxchg((ObjectWaiter*)NULL, &_cxq, w); - if (u == w) break; - w = u; - } - assert(w != NULL, "invariant"); - - ObjectWaiter * q = NULL; - ObjectWaiter * p; - for (p = w; p != NULL; p = p->_next) { - guarantee(p->TState == ObjectWaiter::TS_CXQ, "Invariant"); - p->TState = ObjectWaiter::TS_ENTER; - p->_prev = q; - q = p; - } - - // Prepend the RATs to the EntryList - if (_EntryList != NULL) { - q->_next = _EntryList; - _EntryList->_prev = q; - } - _EntryList = w; - - // Fall thru into code that tries to wake a successor from EntryList - } w = _EntryList; if (w != NULL) { @@ -1093,34 +1005,14 @@ // TODO-FIXME: consider changing EntryList from a DLL to a CDLL so // we have faster access to the tail. - if (QMode == 1) { - // QMode == 1 : drain cxq to EntryList, reversing order - // We also reverse the order of the list. - ObjectWaiter * s = NULL; - ObjectWaiter * t = w; - ObjectWaiter * u = NULL; - while (t != NULL) { - guarantee(t->TState == ObjectWaiter::TS_CXQ, "invariant"); - t->TState = ObjectWaiter::TS_ENTER; - u = t->_next; - t->_prev = u; - t->_next = s; - s = t; - t = u; - } - _EntryList = s; - assert(s != NULL, "invariant"); - } else { - // QMode == 0 or QMode == 2 - _EntryList = w; - ObjectWaiter * q = NULL; - ObjectWaiter * p; - for (p = w; p != NULL; p = p->_next) { - guarantee(p->TState == ObjectWaiter::TS_CXQ, "Invariant"); - p->TState = ObjectWaiter::TS_ENTER; - p->_prev = q; - q = p; - } + _EntryList = w; + ObjectWaiter * q = NULL; + ObjectWaiter * p; + for (p = w; p != NULL; p = p->_next) { + guarantee(p->TState == ObjectWaiter::TS_CXQ, "Invariant"); + p->TState = ObjectWaiter::TS_ENTER; + p->_prev = q; + q = p; } // In 1-0 mode we need: ST EntryList; MEMBAR #storestore; ST _owner = NULL # HG changeset patch # User mikael # Date 1537252352 25200 # Mon Sep 17 23:32:32 2018 -0700 # Node ID 1a5e07c1280839233440d5a3720cccfdfd61bea6 # Parent 7d1b32719c87bc7139ae48b5aa3801b398371711 [mq]: syncknobs-25-Obsolete diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -577,6 +577,7 @@ { "EmitSync", JDK_Version::undefined(), JDK_Version::jdk(12), JDK_Version::jdk(13) }, { "SyncVerbose", JDK_Version::undefined(), JDK_Version::jdk(12), JDK_Version::jdk(13) }, { "SyncFlags", JDK_Version::undefined(), JDK_Version::jdk(12), JDK_Version::jdk(13) }, + { "SyncKnobs", JDK_Version::undefined(), JDK_Version::jdk(12), JDK_Version::jdk(13) }, #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS { "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() }, diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -827,9 +827,6 @@ "Use LWP-based instead of libthread-based synchronization " \ "(SPARC only)") \ \ - experimental(ccstr, SyncKnobs, NULL, \ - "(Unstable) Various monitor synchronization tunables") \ - \ product(intx, MonitorBound, 0, "Bound Monitor population") \ range(0, max_jint) \ \