544 // TODO: Defer all thread state transitions until park-time. |
544 // TODO: Defer all thread state transitions until park-time. |
545 // Since state transitions are heavy and inefficient we'd like |
545 // Since state transitions are heavy and inefficient we'd like |
546 // to defer the state transitions until absolutely necessary, |
546 // to defer the state transitions until absolutely necessary, |
547 // and in doing so avoid some transitions ... |
547 // and in doing so avoid some transitions ... |
548 |
548 |
549 TEVENT(Inflated enter - Contention); |
|
550 int nWakeups = 0; |
549 int nWakeups = 0; |
551 int recheckInterval = 1; |
550 int recheckInterval = 1; |
552 |
551 |
553 for (;;) { |
552 for (;;) { |
554 |
553 |
559 Atomic::replace_if_null(Self, &_Responsible); |
558 Atomic::replace_if_null(Self, &_Responsible); |
560 } |
559 } |
561 |
560 |
562 // park self |
561 // park self |
563 if (_Responsible == Self || (SyncFlags & 1)) { |
562 if (_Responsible == Self || (SyncFlags & 1)) { |
564 TEVENT(Inflated enter - park TIMED); |
|
565 Self->_ParkEvent->park((jlong) recheckInterval); |
563 Self->_ParkEvent->park((jlong) recheckInterval); |
566 // Increase the recheckInterval, but clamp the value. |
564 // Increase the recheckInterval, but clamp the value. |
567 recheckInterval *= 8; |
565 recheckInterval *= 8; |
568 if (recheckInterval > MAX_RECHECK_INTERVAL) { |
566 if (recheckInterval > MAX_RECHECK_INTERVAL) { |
569 recheckInterval = MAX_RECHECK_INTERVAL; |
567 recheckInterval = MAX_RECHECK_INTERVAL; |
570 } |
568 } |
571 } else { |
569 } else { |
572 TEVENT(Inflated enter - park UNTIMED); |
|
573 Self->_ParkEvent->park(); |
570 Self->_ParkEvent->park(); |
574 } |
571 } |
575 |
572 |
576 if (TryLock(Self) > 0) break; |
573 if (TryLock(Self) > 0) break; |
577 |
574 |
578 // The lock is still contested. |
575 // The lock is still contested. |
579 // Keep a tally of the # of futile wakeups. |
576 // Keep a tally of the # of futile wakeups. |
580 // Note that the counter is not protected by a lock or updated by atomics. |
577 // Note that the counter is not protected by a lock or updated by atomics. |
581 // That is by design - we trade "lossy" counters which are exposed to |
578 // That is by design - we trade "lossy" counters which are exposed to |
582 // races during updates for a lower probe effect. |
579 // races during updates for a lower probe effect. |
583 TEVENT(Inflated enter - Futile wakeup); |
580 |
584 // This PerfData object can be used in parallel with a safepoint. |
581 // This PerfData object can be used in parallel with a safepoint. |
585 // See the work around in PerfDataManager::destroy(). |
582 // See the work around in PerfDataManager::destroy(). |
586 OM_PERFDATA_OP(FutileWakeups, inc()); |
583 OM_PERFDATA_OP(FutileWakeups, inc()); |
587 ++nWakeups; |
584 ++nWakeups; |
588 |
585 |
705 assert(_owner != Self, "invariant"); |
702 assert(_owner != Self, "invariant"); |
706 |
703 |
707 if (TryLock(Self) > 0) break; |
704 if (TryLock(Self) > 0) break; |
708 if (TrySpin(Self) > 0) break; |
705 if (TrySpin(Self) > 0) break; |
709 |
706 |
710 TEVENT(Wait Reentry - parking); |
|
711 |
|
712 // State transition wrappers around park() ... |
707 // State transition wrappers around park() ... |
713 // ReenterI() wisely defers state transitions until |
708 // ReenterI() wisely defers state transitions until |
714 // it's clear we must park the thread. |
709 // it's clear we must park the thread. |
715 { |
710 { |
716 OSThreadContendState osts(Self->osthread()); |
711 OSThreadContendState osts(Self->osthread()); |
742 // The lock is still contested. |
737 // The lock is still contested. |
743 // Keep a tally of the # of futile wakeups. |
738 // Keep a tally of the # of futile wakeups. |
744 // Note that the counter is not protected by a lock or updated by atomics. |
739 // Note that the counter is not protected by a lock or updated by atomics. |
745 // That is by design - we trade "lossy" counters which are exposed to |
740 // That is by design - we trade "lossy" counters which are exposed to |
746 // races during updates for a lower probe effect. |
741 // races during updates for a lower probe effect. |
747 TEVENT(Wait Reentry - futile wakeup); |
|
748 ++nWakeups; |
742 ++nWakeups; |
749 |
743 |
750 // Assuming this is not a spurious wakeup we'll normally |
744 // Assuming this is not a spurious wakeup we'll normally |
751 // find that _succ == Self. |
745 // find that _succ == Self. |
752 if (_succ == Self) _succ = NULL; |
746 if (_succ == Self) _succ = NULL; |
793 if (nxt != NULL) nxt->_prev = prv; |
787 if (nxt != NULL) nxt->_prev = prv; |
794 if (prv != NULL) prv->_next = nxt; |
788 if (prv != NULL) prv->_next = nxt; |
795 if (SelfNode == _EntryList) _EntryList = nxt; |
789 if (SelfNode == _EntryList) _EntryList = nxt; |
796 assert(nxt == NULL || nxt->TState == ObjectWaiter::TS_ENTER, "invariant"); |
790 assert(nxt == NULL || nxt->TState == ObjectWaiter::TS_ENTER, "invariant"); |
797 assert(prv == NULL || prv->TState == ObjectWaiter::TS_ENTER, "invariant"); |
791 assert(prv == NULL || prv->TState == ObjectWaiter::TS_ENTER, "invariant"); |
798 TEVENT(Unlink from EntryList); |
|
799 } else { |
792 } else { |
800 assert(SelfNode->TState == ObjectWaiter::TS_CXQ, "invariant"); |
793 assert(SelfNode->TState == ObjectWaiter::TS_CXQ, "invariant"); |
801 // Inopportune interleaving -- Self is still on the cxq. |
794 // Inopportune interleaving -- Self is still on the cxq. |
802 // This usually means the enqueue of self raced an exiting thread. |
795 // This usually means the enqueue of self raced an exiting thread. |
803 // Normally we'll find Self near the front of the cxq, so |
796 // Normally we'll find Self near the front of the cxq, so |
832 assert(p != _cxq, "invariant"); |
825 assert(p != _cxq, "invariant"); |
833 assert(q != NULL, "invariant"); |
826 assert(q != NULL, "invariant"); |
834 assert(q->_next == p, "invariant"); |
827 assert(q->_next == p, "invariant"); |
835 q->_next = p->_next; |
828 q->_next = p->_next; |
836 } |
829 } |
837 TEVENT(Unlink from cxq); |
|
838 } |
830 } |
839 |
831 |
840 #ifdef ASSERT |
832 #ifdef ASSERT |
841 // Diagnostic hygiene ... |
833 // Diagnostic hygiene ... |
842 SelfNode->_prev = (ObjectWaiter *) 0xBAD; |
834 SelfNode->_prev = (ObjectWaiter *) 0xBAD; |
921 // see x86_32.ad Fast_Unlock() and the I1 and I2 properties. |
913 // see x86_32.ad Fast_Unlock() and the I1 and I2 properties. |
922 // Upon deeper reflection, however, in a properly run JVM the only |
914 // Upon deeper reflection, however, in a properly run JVM the only |
923 // way we should encounter this situation is in the presence of |
915 // way we should encounter this situation is in the presence of |
924 // unbalanced JNI locking. TODO: CheckJNICalls. |
916 // unbalanced JNI locking. TODO: CheckJNICalls. |
925 // See also: CR4414101 |
917 // See also: CR4414101 |
926 TEVENT(Exit - Throw IMSX); |
|
927 assert(false, "Non-balanced monitor enter/exit! Likely JNI locking"); |
918 assert(false, "Non-balanced monitor enter/exit! Likely JNI locking"); |
928 return; |
919 return; |
929 } |
920 } |
930 } |
921 } |
931 |
922 |
932 if (_recursions != 0) { |
923 if (_recursions != 0) { |
933 _recursions--; // this is simple recursive enter |
924 _recursions--; // this is simple recursive enter |
934 TEVENT(Inflated exit - recursive); |
|
935 return; |
925 return; |
936 } |
926 } |
937 |
927 |
938 // Invariant: after setting Responsible=null an thread must execute |
928 // Invariant: after setting Responsible=null an thread must execute |
939 // a MEMBAR or other serializing instruction before fetching EntryList|cxq. |
929 // a MEMBAR or other serializing instruction before fetching EntryList|cxq. |
966 // Instead, I use release_store(), which is implemented as just a simple |
956 // Instead, I use release_store(), which is implemented as just a simple |
967 // ST on x64, x86 and SPARC. |
957 // ST on x64, x86 and SPARC. |
968 OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock |
958 OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock |
969 OrderAccess::storeload(); // See if we need to wake a successor |
959 OrderAccess::storeload(); // See if we need to wake a successor |
970 if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { |
960 if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { |
971 TEVENT(Inflated exit - simple egress); |
|
972 return; |
961 return; |
973 } |
962 } |
974 TEVENT(Inflated exit - complex egress); |
|
975 // Other threads are blocked trying to acquire the lock. |
963 // Other threads are blocked trying to acquire the lock. |
976 |
964 |
977 // Normally the exiting thread is responsible for ensuring succession, |
965 // Normally the exiting thread is responsible for ensuring succession, |
978 // but if other successors are ready or other entering threads are spinning |
966 // but if other successors are ready or other entering threads are spinning |
979 // then this thread can simply store NULL into _owner and exit without |
967 // then this thread can simply store NULL into _owner and exit without |
1011 // falls to the new owner. |
999 // falls to the new owner. |
1012 // |
1000 // |
1013 if (!Atomic::replace_if_null(THREAD, &_owner)) { |
1001 if (!Atomic::replace_if_null(THREAD, &_owner)) { |
1014 return; |
1002 return; |
1015 } |
1003 } |
1016 TEVENT(Exit - Reacquired); |
|
1017 } else { |
1004 } else { |
1018 if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { |
1005 if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { |
1019 OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock |
1006 OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock |
1020 OrderAccess::storeload(); |
1007 OrderAccess::storeload(); |
1021 // Ratify the previously observed values. |
1008 // Ratify the previously observed values. |
1022 if (_cxq == NULL || _succ != NULL) { |
1009 if (_cxq == NULL || _succ != NULL) { |
1023 TEVENT(Inflated exit - simple egress); |
|
1024 return; |
1010 return; |
1025 } |
1011 } |
1026 |
1012 |
1027 // inopportune interleaving -- the exiting thread (this thread) |
1013 // inopportune interleaving -- the exiting thread (this thread) |
1028 // in the fast-exit path raced an entering thread in the slow-enter |
1014 // in the fast-exit path raced an entering thread in the slow-enter |
1034 // fall-through into the code below which wakes a successor. |
1020 // fall-through into the code below which wakes a successor. |
1035 // B. If the elements forming the EntryList|cxq are TSM |
1021 // B. If the elements forming the EntryList|cxq are TSM |
1036 // we could simply unpark() the lead thread and return |
1022 // we could simply unpark() the lead thread and return |
1037 // without having set _succ. |
1023 // without having set _succ. |
1038 if (!Atomic::replace_if_null(THREAD, &_owner)) { |
1024 if (!Atomic::replace_if_null(THREAD, &_owner)) { |
1039 TEVENT(Inflated exit - reacquired succeeded); |
|
1040 return; |
1025 return; |
1041 } |
1026 } |
1042 TEVENT(Inflated exit - reacquired failed); |
|
1043 } else { |
|
1044 TEVENT(Inflated exit - complex egress); |
|
1045 } |
1027 } |
1046 } |
1028 } |
1047 |
1029 |
1048 guarantee(_owner == THREAD, "invariant"); |
1030 guarantee(_owner == THREAD, "invariant"); |
1049 |
1031 |
1166 assert(w != NULL, "Invariant"); |
1148 assert(w != NULL, "Invariant"); |
1167 ObjectWaiter * u = Atomic::cmpxchg((ObjectWaiter*)NULL, &_cxq, w); |
1149 ObjectWaiter * u = Atomic::cmpxchg((ObjectWaiter*)NULL, &_cxq, w); |
1168 if (u == w) break; |
1150 if (u == w) break; |
1169 w = u; |
1151 w = u; |
1170 } |
1152 } |
1171 TEVENT(Inflated exit - drain cxq into EntryList); |
|
1172 |
1153 |
1173 assert(w != NULL, "invariant"); |
1154 assert(w != NULL, "invariant"); |
1174 assert(_EntryList == NULL, "invariant"); |
1155 assert(_EntryList == NULL, "invariant"); |
1175 |
1156 |
1176 // Convert the LIFO SLL anchored by _cxq into a DLL. |
1157 // Convert the LIFO SLL anchored by _cxq into a DLL. |
1270 assert(jSelf->is_suspend_equivalent(), "invariant"); |
1251 assert(jSelf->is_suspend_equivalent(), "invariant"); |
1271 jSelf->clear_suspend_equivalent(); |
1252 jSelf->clear_suspend_equivalent(); |
1272 if (2 == Mode) OrderAccess::storeload(); |
1253 if (2 == Mode) OrderAccess::storeload(); |
1273 if (!jSelf->is_external_suspend()) return false; |
1254 if (!jSelf->is_external_suspend()) return false; |
1274 // We raced a suspension -- fall thru into the slow path |
1255 // We raced a suspension -- fall thru into the slow path |
1275 TEVENT(ExitSuspendEquivalent - raced); |
|
1276 jSelf->set_suspend_equivalent(); |
1256 jSelf->set_suspend_equivalent(); |
1277 } |
1257 } |
1278 return jSelf->handle_special_suspend_equivalent_condition(); |
1258 return jSelf->handle_special_suspend_equivalent_condition(); |
1279 } |
1259 } |
1280 |
1260 |
1297 Wakee = NULL; |
1277 Wakee = NULL; |
1298 |
1278 |
1299 // Drop the lock |
1279 // Drop the lock |
1300 OrderAccess::release_store(&_owner, (void*)NULL); |
1280 OrderAccess::release_store(&_owner, (void*)NULL); |
1301 OrderAccess::fence(); // ST _owner vs LD in unpark() |
1281 OrderAccess::fence(); // ST _owner vs LD in unpark() |
1302 |
|
1303 if (SafepointMechanism::poll(Self)) { |
|
1304 TEVENT(unpark before SAFEPOINT); |
|
1305 } |
|
1306 |
1282 |
1307 DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self); |
1283 DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self); |
1308 Trigger->unpark(); |
1284 Trigger->unpark(); |
1309 |
1285 |
1310 // Maintain stats and report events to JVMTI |
1286 // Maintain stats and report events to JVMTI |
1370 if (THREAD != _owner) { \ |
1346 if (THREAD != _owner) { \ |
1371 if (THREAD->is_lock_owned((address) _owner)) { \ |
1347 if (THREAD->is_lock_owned((address) _owner)) { \ |
1372 _owner = THREAD; /* Convert from basiclock addr to Thread addr */ \ |
1348 _owner = THREAD; /* Convert from basiclock addr to Thread addr */ \ |
1373 _recursions = 0; \ |
1349 _recursions = 0; \ |
1374 } else { \ |
1350 } else { \ |
1375 TEVENT(Throw IMSX); \ |
|
1376 THROW(vmSymbols::java_lang_IllegalMonitorStateException()); \ |
1351 THROW(vmSymbols::java_lang_IllegalMonitorStateException()); \ |
1377 } \ |
1352 } \ |
1378 } \ |
1353 } \ |
1379 } while (false) |
1354 } while (false) |
1380 |
1355 |
1381 // check_slow() is a misnomer. It's called to simply to throw an IMSX exception. |
1356 // check_slow() is a misnomer. It's called to simply to throw an IMSX exception. |
1382 // TODO-FIXME: remove check_slow() -- it's likely dead. |
1357 // TODO-FIXME: remove check_slow() -- it's likely dead. |
1383 |
1358 |
1384 void ObjectMonitor::check_slow(TRAPS) { |
1359 void ObjectMonitor::check_slow(TRAPS) { |
1385 TEVENT(check_slow - throw IMSX); |
|
1386 assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner"); |
1360 assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner"); |
1387 THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner"); |
1361 THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner"); |
1388 } |
1362 } |
1389 |
1363 |
1390 static int Adjust(volatile int * adr, int dx) { |
1364 static int Adjust(volatile int * adr, int dx) { |
1442 // this ObjectMonitor. |
1416 // this ObjectMonitor. |
1443 } |
1417 } |
1444 if (event.should_commit()) { |
1418 if (event.should_commit()) { |
1445 post_monitor_wait_event(&event, this, 0, millis, false); |
1419 post_monitor_wait_event(&event, this, 0, millis, false); |
1446 } |
1420 } |
1447 TEVENT(Wait - Throw IEX); |
|
1448 THROW(vmSymbols::java_lang_InterruptedException()); |
1421 THROW(vmSymbols::java_lang_InterruptedException()); |
1449 return; |
1422 return; |
1450 } |
1423 } |
1451 |
|
1452 TEVENT(Wait); |
|
1453 |
1424 |
1454 assert(Self->_Stalled == 0, "invariant"); |
1425 assert(Self->_Stalled == 0, "invariant"); |
1455 Self->_Stalled = intptr_t(this); |
1426 Self->_Stalled = intptr_t(this); |
1456 jt->set_current_waiting_monitor(this); |
1427 jt->set_current_waiting_monitor(this); |
1457 |
1428 |
1629 // check if the notification happened |
1600 // check if the notification happened |
1630 if (!WasNotified) { |
1601 if (!WasNotified) { |
1631 // no, it could be timeout or Thread.interrupt() or both |
1602 // no, it could be timeout or Thread.interrupt() or both |
1632 // check for interrupt event, otherwise it is timeout |
1603 // check for interrupt event, otherwise it is timeout |
1633 if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) { |
1604 if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) { |
1634 TEVENT(Wait - throw IEX from epilog); |
|
1635 THROW(vmSymbols::java_lang_InterruptedException()); |
1605 THROW(vmSymbols::java_lang_InterruptedException()); |
1636 } |
1606 } |
1637 } |
1607 } |
1638 |
1608 |
1639 // NOTE: Spurious wake up will be consider as timeout. |
1609 // NOTE: Spurious wake up will be consider as timeout. |
1650 const int policy = Knob_MoveNotifyee; |
1620 const int policy = Knob_MoveNotifyee; |
1651 |
1621 |
1652 Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notify"); |
1622 Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notify"); |
1653 ObjectWaiter * iterator = DequeueWaiter(); |
1623 ObjectWaiter * iterator = DequeueWaiter(); |
1654 if (iterator != NULL) { |
1624 if (iterator != NULL) { |
1655 TEVENT(Notify1 - Transfer); |
|
1656 guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant"); |
1625 guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant"); |
1657 guarantee(iterator->_notified == 0, "invariant"); |
1626 guarantee(iterator->_notified == 0, "invariant"); |
1658 // Disposition - what might we do with iterator ? |
1627 // Disposition - what might we do with iterator ? |
1659 // a. add it directly to the EntryList - either tail (policy == 1) |
1628 // a. add it directly to the EntryList - either tail (policy == 1) |
1660 // or head (policy == 0). |
1629 // or head (policy == 0). |
1764 // variable and MAX_RECHECK_INTERVAL. |
1733 // variable and MAX_RECHECK_INTERVAL. |
1765 |
1734 |
1766 void ObjectMonitor::notify(TRAPS) { |
1735 void ObjectMonitor::notify(TRAPS) { |
1767 CHECK_OWNER(); |
1736 CHECK_OWNER(); |
1768 if (_WaitSet == NULL) { |
1737 if (_WaitSet == NULL) { |
1769 TEVENT(Empty-Notify); |
|
1770 return; |
1738 return; |
1771 } |
1739 } |
1772 DTRACE_MONITOR_PROBE(notify, this, object(), THREAD); |
1740 DTRACE_MONITOR_PROBE(notify, this, object(), THREAD); |
1773 INotify(THREAD); |
1741 INotify(THREAD); |
1774 OM_PERFDATA_OP(Notifications, inc(1)); |
1742 OM_PERFDATA_OP(Notifications, inc(1)); |
1783 // mode the waitset will be empty and the EntryList will be "DCBAXYZ". |
1751 // mode the waitset will be empty and the EntryList will be "DCBAXYZ". |
1784 |
1752 |
1785 void ObjectMonitor::notifyAll(TRAPS) { |
1753 void ObjectMonitor::notifyAll(TRAPS) { |
1786 CHECK_OWNER(); |
1754 CHECK_OWNER(); |
1787 if (_WaitSet == NULL) { |
1755 if (_WaitSet == NULL) { |
1788 TEVENT(Empty-NotifyAll); |
|
1789 return; |
1756 return; |
1790 } |
1757 } |
1791 |
1758 |
1792 DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD); |
1759 DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD); |
1793 int tally = 0; |
1760 int tally = 0; |
1910 if (ctr < Knob_SpinBase) ctr = Knob_SpinBase; |
1877 if (ctr < Knob_SpinBase) ctr = Knob_SpinBase; |
1911 if (ctr <= 0) return 0; |
1878 if (ctr <= 0) return 0; |
1912 |
1879 |
1913 if (Knob_SuccRestrict && _succ != NULL) return 0; |
1880 if (Knob_SuccRestrict && _succ != NULL) return 0; |
1914 if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) { |
1881 if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) { |
1915 TEVENT(Spin abort - notrunnable [TOP]); |
|
1916 return 0; |
1882 return 0; |
1917 } |
1883 } |
1918 |
1884 |
1919 int MaxSpin = Knob_MaxSpinners; |
1885 int MaxSpin = Knob_MaxSpinners; |
1920 if (MaxSpin >= 0) { |
1886 if (MaxSpin >= 0) { |
1921 if (_Spinner > MaxSpin) { |
1887 if (_Spinner > MaxSpin) { |
1922 TEVENT(Spin abort -- too many spinners); |
|
1923 return 0; |
1888 return 0; |
1924 } |
1889 } |
1925 // Slightly racy, but benign ... |
1890 // Slightly racy, but benign ... |
1926 Adjust(&_Spinner, 1); |
1891 Adjust(&_Spinner, 1); |
1927 } |
1892 } |
1954 // this thread, if safe, doesn't steal cycles from GC. |
1919 // this thread, if safe, doesn't steal cycles from GC. |
1955 // This is in keeping with the "no loitering in runtime" rule. |
1920 // This is in keeping with the "no loitering in runtime" rule. |
1956 // We periodically check to see if there's a safepoint pending. |
1921 // We periodically check to see if there's a safepoint pending. |
1957 if ((ctr & 0xFF) == 0) { |
1922 if ((ctr & 0xFF) == 0) { |
1958 if (SafepointMechanism::poll(Self)) { |
1923 if (SafepointMechanism::poll(Self)) { |
1959 TEVENT(Spin: safepoint); |
|
1960 goto Abort; // abrupt spin egress |
1924 goto Abort; // abrupt spin egress |
1961 } |
1925 } |
1962 if (Knob_UsePause & 1) SpinPause(); |
1926 if (Knob_UsePause & 1) SpinPause(); |
1963 } |
1927 } |
1964 |
1928 |
2027 // * penalize: ctr -= Knob_CASPenalty |
1991 // * penalize: ctr -= Knob_CASPenalty |
2028 // * exit spin with prejudice -- goto Abort; |
1992 // * exit spin with prejudice -- goto Abort; |
2029 // * exit spin without prejudice. |
1993 // * exit spin without prejudice. |
2030 // * Since CAS is high-latency, retry again immediately. |
1994 // * Since CAS is high-latency, retry again immediately. |
2031 prv = ox; |
1995 prv = ox; |
2032 TEVENT(Spin: cas failed); |
|
2033 if (caspty == -2) break; |
1996 if (caspty == -2) break; |
2034 if (caspty == -1) goto Abort; |
1997 if (caspty == -1) goto Abort; |
2035 ctr -= caspty; |
1998 ctr -= caspty; |
2036 continue; |
1999 continue; |
2037 } |
2000 } |
2038 |
2001 |
2039 // Did lock ownership change hands ? |
2002 // Did lock ownership change hands ? |
2040 if (ox != prv && prv != NULL) { |
2003 if (ox != prv && prv != NULL) { |
2041 TEVENT(spin: Owner changed) |
|
2042 if (oxpty == -2) break; |
2004 if (oxpty == -2) break; |
2043 if (oxpty == -1) goto Abort; |
2005 if (oxpty == -1) goto Abort; |
2044 ctr -= oxpty; |
2006 ctr -= oxpty; |
2045 } |
2007 } |
2046 prv = ox; |
2008 prv = ox; |
2048 // Abort the spin if the owner is not executing. |
2010 // Abort the spin if the owner is not executing. |
2049 // The owner must be executing in order to drop the lock. |
2011 // The owner must be executing in order to drop the lock. |
2050 // Spinning while the owner is OFFPROC is idiocy. |
2012 // Spinning while the owner is OFFPROC is idiocy. |
2051 // Consider: ctr -= RunnablePenalty ; |
2013 // Consider: ctr -= RunnablePenalty ; |
2052 if (Knob_OState && NotRunnable (Self, ox)) { |
2014 if (Knob_OState && NotRunnable (Self, ox)) { |
2053 TEVENT(Spin abort - notrunnable); |
|
2054 goto Abort; |
2015 goto Abort; |
2055 } |
2016 } |
2056 if (sss && _succ == NULL) _succ = Self; |
2017 if (sss && _succ == NULL) _succ = Self; |
2057 } |
2018 } |
2058 |
2019 |
2059 // Spin failed with prejudice -- reduce _SpinDuration. |
2020 // Spin failed with prejudice -- reduce _SpinDuration. |
2060 // TODO: Use an AIMD-like policy to adjust _SpinDuration. |
2021 // TODO: Use an AIMD-like policy to adjust _SpinDuration. |
2061 // AIMD is globally stable. |
2022 // AIMD is globally stable. |
2062 TEVENT(Spin failure); |
|
2063 { |
2023 { |
2064 int x = _SpinDuration; |
2024 int x = _SpinDuration; |
2065 if (x > 0) { |
2025 if (x > 0) { |
2066 // Consider an AIMD scheme like: x -= (x >> 3) + 100 |
2026 // Consider an AIMD scheme like: x -= (x >> 3) + 100 |
2067 // This is globally sample and tends to damp the response. |
2027 // This is globally sample and tends to damp the response. |