< prev index next >

src/hotspot/share/runtime/objectMonitor.cpp

Print this page
rev 51814 : imported patch syncknobs-00-base
rev 51815 : imported patch syncknobs-01-Knob_ReportSettings
rev 51816 : imported patch syncknobs-02-Knob_SpinBackOff
rev 51817 : imported patch syncknobs-03-BackOffMask
rev 51818 : imported patch syncknobs-04-Knob_ExitRelease
rev 51820 : imported patch syncknobs-05-Knob_InlineNotify
rev 51821 : imported patch syncknobs-06-Knob_Verbose
rev 51822 : imported patch syncknobs-07-Knob_VerifyInUse
rev 51824 : imported patch syncknobs-08-Knob_VerifyMatch
rev 51825 : imported patch syncknobs-09-Knob_SpinBase
rev 51826 : imported patch syncknobs-10-Knob_CASPenalty
rev 51827 : imported patch syncknobs-11-Knob_OXPenalty
rev 51828 : imported patch syncknobs-12-Knob_SpinSetSucc
rev 51829 : imported patch syncknobs-13-Knob_SpinEarly
rev 51830 : imported patch syncknobs-14-Knob_SuccEnabled
rev 51831 : imported patch syncknobs-15-Knob_SuccRestrict
rev 51832 : imported patch syncknobs-16-Knob_MaxSpinners
rev 51833 : imported patch syncknobs-17-Knob_SpinAfterFutile
rev 51834 : imported patch syncknobs-18-Knob_OState
rev 51835 : imported patch syncknobs-19-Knob_UsePause
rev 51836 : imported patch syncknobs-20-Knob_ExitPolicy
rev 51837 : imported patch syncknobs-20.2-Knob_ExitPolicy
rev 51838 : imported patch syncknobs-21-Knob_ResetEvent
rev 51839 : imported patch syncknobs-22-Knob_FastHSSEC
rev 51840 : imported patch syncknobs-23-Knob_MoveNotifyee
rev 51841 : imported patch syncknobs-24-Knob_QMode

@@ -99,43 +99,19 @@
 
 // Tunables ...
 // 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;
-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
-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
-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
 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;
-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
-static int Knob_QMode               = 0;       // EntryList-cxq policy - queue discipline
 static volatile int InitDone        = 0;
 
 // -----------------------------------------------------------------------------
 // Theory of operations -- Monitors lists, thread residency, etc:
 //

@@ -297,11 +273,11 @@
   // Try one round of spinning *before* enqueueing Self
   // and before going through the awkward and expensive state
   // 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");
     Self->_Stalled = 0;
     return;

@@ -459,11 +435,11 @@
   // If the _owner is ready but OFFPROC we could use a YieldTo()
   // operation to donate the remainder of this thread's quantum
   // 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");
     return;
   }

@@ -581,24 +557,18 @@
 
     // Assuming this is not a spurious wakeup we'll normally find _succ == Self.
     // 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(),
     // 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.
     OrderAccess::fence();
   }

@@ -673,13 +643,11 @@
 
 // ReenterI() is a specialized inline form of the latter half of the
 // 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");
   assert(SelfNode != NULL, "invariant");
   assert(SelfNode->_thread == Self, "invariant");

@@ -927,23 +895,14 @@
 #endif
 
   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;
       }

@@ -986,126 +945,14 @@
       // 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;
-        }
-      }
-    }
 
     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) {
       // I'd like to write: guarantee (w->_thread != Self).
       // But in practice an exiting thread may find itself on the EntryList.

@@ -1148,39 +995,19 @@
     // and effectively lengthening the critical section.
     // Invariant: s chases t chases u.
     // 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;
       }
-    }
 
     // In 1-0 mode we need: ST EntryList; MEMBAR #storestore; ST _owner = NULL
     // The MEMBAR is satisfied by the release_store() operation in ExitEpilog().
 
     // See if we can abdicate to a spinner instead of waking a thread.

@@ -1224,26 +1051,12 @@
 //     Alternately, a Dekker-like mechanism with multiple variables
 //     would suffice:
 //       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();
 }
 
 
 void ObjectMonitor::ExitEpilog(Thread * Self, ObjectWaiter * Wakee) {

@@ -1253,11 +1066,11 @@
   // 1. ST _succ = wakee
   // 2. membar #loadstore|#storestore;
   // 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.
   // The thread associated with Wakee may have grabbed the lock and "Wakee" may be
   // out-of-scope (non-extant).

@@ -1346,16 +1159,10 @@
 void ObjectMonitor::check_slow(TRAPS) {
   assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner");
   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,
                                     jlong timeout,
                                     bool timedout) {

@@ -1597,61 +1404,34 @@
 // If the lock is cool (cxq == null && succ == null) and we're on an MP system
 // then instead of transferring a thread from the WaitSet to the EntryList
 // 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) {
     guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant");
     guarantee(iterator->_notified == 0, "invariant");
     // Disposition - what might we do with iterator ?
     // a.  add it directly to the EntryList - either tail (policy == 1)
     //     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->_notified = 1;
     iterator->_notifier_tid = JFR_THREAD_ID(Self);
 
     ObjectWaiter * list = _EntryList;
     if (list != NULL) {
       assert(list->_prev == NULL, "invariant");
       assert(list->TState == ObjectWaiter::TS_ENTER, "invariant");
       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
+    // prepend to cxq
       if (list == NULL) {
         iterator->_next = iterator->_prev = NULL;
         _EntryList = iterator;
       } else {
         iterator->TState = ObjectWaiter::TS_CXQ;

@@ -1661,46 +1441,21 @@
           if (Atomic::cmpxchg(iterator, &_cxq, front) == front) {
             break;
           }
         }
       }
-    } else if (policy == 3) {      // append to cxq
-      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;
-          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
     // move the add-to-EntryList operation, above, outside the critical section
     // protected by _WaitSetLock.  In practice that's not useful.  With the
     // exception of  wait() timeouts and interrupts the monitor owner
     // is the only thread that grabs _WaitSetLock.  There's almost no contention
     // on _WaitSetLock so it's not profitable to reduce the length of the
     // critical section.
 
-    if (policy < 4) {
       iterator->wait_reenter_begin(this);
     }
-  }
   Thread::SpinRelease(&_WaitSetLock);
 }
 
 // Consider: a not-uncommon synchronization bug is to use notify() when
 // notifyAll() is more appropriate, potentially resulting in stranded

@@ -1852,37 +1607,23 @@
   // the # of failed spin attempts (or iterations) reaches some threshold.
   // This takes us into the realm of 1-out-of-N spinning, where we
   // 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;
-  if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) {
-    return 0;
-  }
-
-  int MaxSpin = Knob_MaxSpinners;
-  if (MaxSpin >= 0) {
-    if (_Spinner > MaxSpin) {
+  if (NotRunnable(Self, (Thread *) _owner)) {
       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
   // to succeed.
-  int hits    = 0;
-  int msk     = 0;
-  int caspty  = Knob_CASPenalty;
-  int oxpty   = Knob_OXPenalty;
-  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:
   // 1.  A successful spin where this thread has acquired the lock.
   // 2.  Spin failure with prejudice

@@ -1901,36 +1642,11 @@
     // We periodically check to see if there's a safepoint pending.
     if ((ctr & 0xFF) == 0) {
       if (SafepointMechanism::poll(Self)) {
         goto Abort;           // abrupt spin egress
       }
-      if (Knob_UsePause & 1) SpinPause();
-    }
-
-    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;
+      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

@@ -1945,14 +1661,13 @@
     if (ox == NULL) {
       ox = (Thread*)Atomic::cmpxchg(Self, &_owner, (void*)NULL);
       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);
 
         // Increase _SpinDuration :
         // The spin was successful (profitable) so we tend toward
         // longer spin attempts in the future.
         // CONSIDER: factor "ctr" into the _SpinDuration adjustment.

@@ -1966,37 +1681,34 @@
         }
         return 1;
       }
 
       // 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 ?
     if (ox != prv && prv != NULL) {
-      if (oxpty == -2) break;
-      if (oxpty == -1) goto Abort;
-      ctr -= oxpty;
+      goto Abort;
     }
     prv = ox;
 
     // Abort the spin if the owner is not executing.
     // 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 (sss && _succ == NULL) _succ = Self;
+    if (_succ == NULL) {
+      _succ = Self;
+    }
   }
 
   // Spin failed with prejudice -- reduce _SpinDuration.
   // TODO: Use an AIMD-like policy to adjust _SpinDuration.
   // AIMD is globally stable.

@@ -2010,12 +1722,11 @@
       _SpinDuration = x;
     }
   }
 
  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
     // in the normal usage of TrySpin(), but it's safest
     // to make TrySpin() as foolproof as possible.

@@ -2202,106 +1913,26 @@
 #undef NEWPERFCOUNTER
 #undef NEWPERFVARIABLE
   }
 }
 
-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) {
     while (InitDone != 1) /* empty */;
     return;
   }
 
   // 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 <Key>=<Value> 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;
-    if (Knob_ReportSettings) {
-      tty->print_cr("INFO: BackOffMask=0x%X", BackOffMask);
-    }
-    // CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1)
-  } else {
+  if (!os::is_MP()) {
     Knob_SpinLimit = 0;
-    Knob_SpinBase  = 0;
     Knob_PreSpin   = 0;
     Knob_FixedSpin = -1;
   }
 
-  os::free(knobs);
   OrderAccess::fence();
   InitDone = 1;
 }
 
< prev index next >