< prev index next >

src/hotspot/share/runtime/objectMonitor.cpp

Print this page
rev 51780 : imported patch syncknobs-00-base
rev 51781 : imported patch syncknobs-01-Knob_ReportSettings
rev 51782 : imported patch syncknobs-02-Knob_SpinBackOff
rev 51783 : imported patch syncknobs-03-BackOffMask
rev 51784 : imported patch syncknobs-04-Knob_ExitRelease
rev 51785 : imported patch syncknobs-05-Knob_InlineNotify
rev 51786 : imported patch syncknobs-06-Knob_Verbose
rev 51787 : imported patch syncknobs-07-Knob_VerifyInUse
rev 51788 : imported patch syncknobs-08-Knob_VerifyMatch
rev 51789 : imported patch syncknobs-09-Knob_SpinBase
rev 51790 : imported patch syncknobs-10-Knob_CASPenalty
rev 51791 : imported patch syncknobs-11-Knob_OXPenalty
rev 51792 : imported patch syncknobs-12-Knob_SpinSetSucc
rev 51793 : imported patch syncknobs-13-Knob_SpinEarly
rev 51794 : imported patch syncknobs-14-Knob_SuccEnabled
rev 51795 : imported patch syncknobs-15-Knob_SuccRestrict
rev 51796 : imported patch syncknobs-16-Knob_MaxSpinners
rev 51797 : imported patch syncknobs-17-Knob_SpinAfterFutile
rev 51798 : imported patch syncknobs-18-Knob_OState
rev 51799 : imported patch syncknobs-19-Knob_UsePause
rev 51800 : imported patch syncknobs-20-Knob_ExitPolicy
rev 51801 : imported patch syncknobs-21-Knob_ResetEvent
rev 51802 : imported patch syncknobs-22-Knob_FastHSSEC
rev 51803 : imported patch syncknobs-23-Knob_MoveNotifyee

*** 108,118 **** static int Knob_Penalty = 200; // spin failure penalty static int Knob_Poverty = 1000; 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; // ----------------------------------------------------------------------------- // Theory of operations -- Monitors lists, thread residency, etc: --- 108,117 ----
*** 1521,1581 **** // 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 if (list == NULL) { iterator->_next = iterator->_prev = NULL; _EntryList = iterator; } else { iterator->TState = ObjectWaiter::TS_CXQ; --- 1520,1553 ---- // 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) { 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). ! 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"); } ! // prepend to cxq if (list == NULL) { iterator->_next = iterator->_prev = NULL; _EntryList = iterator; } else { iterator->TState = ObjectWaiter::TS_CXQ;
*** 1585,1630 **** 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 --- 1557,1577 ----
< prev index next >