1634 // Consider: |
1638 // Consider: |
1635 // If the lock is cool (cxq == null && succ == null) and we're on an MP system |
1639 // If the lock is cool (cxq == null && succ == null) and we're on an MP system |
1636 // then instead of transferring a thread from the WaitSet to the EntryList |
1640 // then instead of transferring a thread from the WaitSet to the EntryList |
1637 // we might just dequeue a thread from the WaitSet and directly unpark() it. |
1641 // we might just dequeue a thread from the WaitSet and directly unpark() it. |
1638 |
1642 |
1639 void ObjectMonitor::notify(TRAPS) { |
1643 void ObjectMonitor::INotify(Thread * Self) { |
1640 CHECK_OWNER(); |
1644 const int policy = Knob_MoveNotifyee; |
1641 if (_WaitSet == NULL) { |
|
1642 TEVENT(Empty-Notify); |
|
1643 return; |
|
1644 } |
|
1645 DTRACE_MONITOR_PROBE(notify, this, object(), THREAD); |
|
1646 |
|
1647 int Policy = Knob_MoveNotifyee; |
|
1648 |
1645 |
1649 Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notify"); |
1646 Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notify"); |
1650 ObjectWaiter * iterator = DequeueWaiter(); |
1647 ObjectWaiter * iterator = DequeueWaiter(); |
1651 if (iterator != NULL) { |
1648 if (iterator != NULL) { |
1652 TEVENT(Notify1 - Transfer); |
1649 TEVENT(Notify1 - Transfer); |
1653 guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant"); |
1650 guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant"); |
1654 guarantee(iterator->_notified == 0, "invariant"); |
1651 guarantee(iterator->_notified == 0, "invariant"); |
1655 if (Policy != 4) { |
1652 // Disposition - what might we do with iterator ? |
|
1653 // a. add it directly to the EntryList - either tail (policy == 1) |
|
1654 // or head (policy == 0). |
|
1655 // b. push it onto the front of the _cxq (policy == 2). |
|
1656 // For now we use (b). |
|
1657 if (policy != 4) { |
1656 iterator->TState = ObjectWaiter::TS_ENTER; |
1658 iterator->TState = ObjectWaiter::TS_ENTER; |
1657 } |
1659 } |
1658 iterator->_notified = 1; |
1660 iterator->_notified = 1; |
1659 Thread * Self = THREAD; |
|
1660 iterator->_notifier_tid = Self->osthread()->thread_id(); |
1661 iterator->_notifier_tid = Self->osthread()->thread_id(); |
1661 |
1662 |
1662 ObjectWaiter * List = _EntryList; |
1663 ObjectWaiter * list = _EntryList; |
1663 if (List != NULL) { |
1664 if (list != NULL) { |
1664 assert(List->_prev == NULL, "invariant"); |
1665 assert(list->_prev == NULL, "invariant"); |
1665 assert(List->TState == ObjectWaiter::TS_ENTER, "invariant"); |
1666 assert(list->TState == ObjectWaiter::TS_ENTER, "invariant"); |
1666 assert(List != iterator, "invariant"); |
1667 assert(list != iterator, "invariant"); |
1667 } |
1668 } |
1668 |
1669 |
1669 if (Policy == 0) { // prepend to EntryList |
1670 if (policy == 0) { // prepend to EntryList |
1670 if (List == NULL) { |
1671 if (list == NULL) { |
1671 iterator->_next = iterator->_prev = NULL; |
1672 iterator->_next = iterator->_prev = NULL; |
1672 _EntryList = iterator; |
1673 _EntryList = iterator; |
1673 } else { |
1674 } else { |
1674 List->_prev = iterator; |
1675 list->_prev = iterator; |
1675 iterator->_next = List; |
1676 iterator->_next = list; |
1676 iterator->_prev = NULL; |
1677 iterator->_prev = NULL; |
1677 _EntryList = iterator; |
1678 _EntryList = iterator; |
1678 } |
1679 } |
1679 } else if (Policy == 1) { // append to EntryList |
1680 } else if (policy == 1) { // append to EntryList |
1680 if (List == NULL) { |
1681 if (list == NULL) { |
1681 iterator->_next = iterator->_prev = NULL; |
1682 iterator->_next = iterator->_prev = NULL; |
1682 _EntryList = iterator; |
1683 _EntryList = iterator; |
1683 } else { |
1684 } else { |
1684 // CONSIDER: finding the tail currently requires a linear-time walk of |
1685 // CONSIDER: finding the tail currently requires a linear-time walk of |
1685 // the EntryList. We can make tail access constant-time by converting to |
1686 // the EntryList. We can make tail access constant-time by converting to |
1686 // a CDLL instead of using our current DLL. |
1687 // a CDLL instead of using our current DLL. |
1687 ObjectWaiter * Tail; |
1688 ObjectWaiter * tail; |
1688 for (Tail = List; Tail->_next != NULL; Tail = Tail->_next) /* empty */; |
1689 for (tail = list; tail->_next != NULL; tail = tail->_next) /* empty */; |
1689 assert(Tail != NULL && Tail->_next == NULL, "invariant"); |
1690 assert(tail != NULL && tail->_next == NULL, "invariant"); |
1690 Tail->_next = iterator; |
1691 tail->_next = iterator; |
1691 iterator->_prev = Tail; |
1692 iterator->_prev = tail; |
1692 iterator->_next = NULL; |
1693 iterator->_next = NULL; |
1693 } |
1694 } |
1694 } else if (Policy == 2) { // prepend to cxq |
1695 } else if (policy == 2) { // prepend to cxq |
1695 // prepend to cxq |
1696 if (list == NULL) { |
1696 if (List == NULL) { |
|
1697 iterator->_next = iterator->_prev = NULL; |
1697 iterator->_next = iterator->_prev = NULL; |
1698 _EntryList = iterator; |
1698 _EntryList = iterator; |
1699 } else { |
1699 } else { |
1700 iterator->TState = ObjectWaiter::TS_CXQ; |
1700 iterator->TState = ObjectWaiter::TS_CXQ; |
1701 for (;;) { |
1701 for (;;) { |
1702 ObjectWaiter * Front = _cxq; |
1702 ObjectWaiter * front = _cxq; |
1703 iterator->_next = Front; |
1703 iterator->_next = front; |
1704 if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) { |
1704 if (Atomic::cmpxchg_ptr(iterator, &_cxq, front) == front) { |
1705 break; |
1705 break; |
1706 } |
1706 } |
1707 } |
1707 } |
1708 } |
1708 } |
1709 } else if (Policy == 3) { // append to cxq |
1709 } else if (policy == 3) { // append to cxq |
1710 iterator->TState = ObjectWaiter::TS_CXQ; |
1710 iterator->TState = ObjectWaiter::TS_CXQ; |
1711 for (;;) { |
1711 for (;;) { |
1712 ObjectWaiter * Tail; |
1712 ObjectWaiter * tail = _cxq; |
1713 Tail = _cxq; |
1713 if (tail == NULL) { |
1714 if (Tail == NULL) { |
|
1715 iterator->_next = NULL; |
1714 iterator->_next = NULL; |
1716 if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) { |
1715 if (Atomic::cmpxchg_ptr(iterator, &_cxq, NULL) == NULL) { |
1717 break; |
1716 break; |
1718 } |
1717 } |
1719 } else { |
1718 } else { |
1720 while (Tail->_next != NULL) Tail = Tail->_next; |
1719 while (tail->_next != NULL) tail = tail->_next; |
1721 Tail->_next = iterator; |
1720 tail->_next = iterator; |
1722 iterator->_prev = Tail; |
1721 iterator->_prev = tail; |
1723 iterator->_next = NULL; |
1722 iterator->_next = NULL; |
1724 break; |
1723 break; |
1725 } |
1724 } |
1726 } |
1725 } |
1727 } else { |
1726 } else { |
1728 ParkEvent * ev = iterator->_event; |
1727 ParkEvent * ev = iterator->_event; |
1729 iterator->TState = ObjectWaiter::TS_RUN; |
1728 iterator->TState = ObjectWaiter::TS_RUN; |
1730 OrderAccess::fence(); |
1729 OrderAccess::fence(); |
1731 ev->unpark(); |
1730 ev->unpark(); |
1732 } |
|
1733 |
|
1734 if (Policy < 4) { |
|
1735 iterator->wait_reenter_begin(this); |
|
1736 } |
1731 } |
1737 |
1732 |
1738 // _WaitSetLock protects the wait queue, not the EntryList. We could |
1733 // _WaitSetLock protects the wait queue, not the EntryList. We could |
1739 // move the add-to-EntryList operation, above, outside the critical section |
1734 // move the add-to-EntryList operation, above, outside the critical section |
1740 // protected by _WaitSetLock. In practice that's not useful. With the |
1735 // protected by _WaitSetLock. In practice that's not useful. With the |
1741 // exception of wait() timeouts and interrupts the monitor owner |
1736 // exception of wait() timeouts and interrupts the monitor owner |
1742 // is the only thread that grabs _WaitSetLock. There's almost no contention |
1737 // is the only thread that grabs _WaitSetLock. There's almost no contention |
1743 // on _WaitSetLock so it's not profitable to reduce the length of the |
1738 // on _WaitSetLock so it's not profitable to reduce the length of the |
1744 // critical section. |
1739 // critical section. |
1745 } |
1740 |
1746 |
1741 if (policy < 4) { |
|
1742 iterator->wait_reenter_begin(this); |
|
1743 } |
|
1744 } |
1747 Thread::SpinRelease(&_WaitSetLock); |
1745 Thread::SpinRelease(&_WaitSetLock); |
1748 |
1746 } |
1749 if (iterator != NULL && ObjectMonitor::_sync_Notifications != NULL) { |
1747 |
1750 ObjectMonitor::_sync_Notifications->inc(); |
1748 // Consider: a not-uncommon synchronization bug is to use notify() when |
1751 } |
1749 // notifyAll() is more appropriate, potentially resulting in stranded |
1752 } |
1750 // threads; this is one example of a lost wakeup. A useful diagnostic |
1753 |
1751 // option is to force all notify() operations to behave as notifyAll(). |
|
1752 // |
|
1753 // Note: We can also detect many such problems with a "minimum wait". |
|
1754 // When the "minimum wait" is set to a small non-zero timeout value |
|
1755 // and the program does not hang whereas it did absent "minimum wait", |
|
1756 // that suggests a lost wakeup bug. The '-XX:SyncFlags=1' option uses |
|
1757 // a "minimum wait" for all park() operations; see the recheckInterval |
|
1758 // variable and MAX_RECHECK_INTERVAL. |
|
1759 |
|
1760 void ObjectMonitor::notify(TRAPS) { |
|
1761 CHECK_OWNER(); |
|
1762 if (_WaitSet == NULL) { |
|
1763 TEVENT(Empty-Notify); |
|
1764 return; |
|
1765 } |
|
1766 DTRACE_MONITOR_PROBE(notify, this, object(), THREAD); |
|
1767 INotify(THREAD); |
|
1768 if (ObjectMonitor::_sync_Notifications != NULL) { |
|
1769 ObjectMonitor::_sync_Notifications->inc(1); |
|
1770 } |
|
1771 } |
|
1772 |
|
1773 |
|
1774 // The current implementation of notifyAll() transfers the waiters one-at-a-time |
|
1775 // from the waitset to the EntryList. This could be done more efficiently with a |
|
1776 // single bulk transfer but in practice it's not time-critical. Beware too, |
|
1777 // that in prepend-mode we invert the order of the waiters. Let's say that the |
|
1778 // waitset is "ABCD" and the EntryList is "XYZ". After a notifyAll() in prepend |
|
1779 // mode the waitset will be empty and the EntryList will be "DCBAXYZ". |
1754 |
1780 |
1755 void ObjectMonitor::notifyAll(TRAPS) { |
1781 void ObjectMonitor::notifyAll(TRAPS) { |
1756 CHECK_OWNER(); |
1782 CHECK_OWNER(); |
1757 ObjectWaiter* iterator; |
|
1758 if (_WaitSet == NULL) { |
1783 if (_WaitSet == NULL) { |
1759 TEVENT(Empty-NotifyAll); |
1784 TEVENT(Empty-NotifyAll); |
1760 return; |
1785 return; |
1761 } |
1786 } |
|
1787 |
1762 DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD); |
1788 DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD); |
1763 |
1789 int tally = 0; |
1764 int Policy = Knob_MoveNotifyee; |
1790 while (_WaitSet != NULL) { |
1765 int Tally = 0; |
1791 tally++; |
1766 Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notifyall"); |
1792 INotify(THREAD); |
1767 |
1793 } |
1768 for (;;) { |
1794 |
1769 iterator = DequeueWaiter(); |
1795 if (tally != 0 && ObjectMonitor::_sync_Notifications != NULL) { |
1770 if (iterator == NULL) break; |
1796 ObjectMonitor::_sync_Notifications->inc(tally); |
1771 TEVENT(NotifyAll - Transfer1); |
|
1772 ++Tally; |
|
1773 |
|
1774 // Disposition - what might we do with iterator ? |
|
1775 // a. add it directly to the EntryList - either tail or head. |
|
1776 // b. push it onto the front of the _cxq. |
|
1777 // For now we use (a). |
|
1778 |
|
1779 guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant"); |
|
1780 guarantee(iterator->_notified == 0, "invariant"); |
|
1781 iterator->_notified = 1; |
|
1782 Thread * Self = THREAD; |
|
1783 iterator->_notifier_tid = Self->osthread()->thread_id(); |
|
1784 if (Policy != 4) { |
|
1785 iterator->TState = ObjectWaiter::TS_ENTER; |
|
1786 } |
|
1787 |
|
1788 ObjectWaiter * List = _EntryList; |
|
1789 if (List != NULL) { |
|
1790 assert(List->_prev == NULL, "invariant"); |
|
1791 assert(List->TState == ObjectWaiter::TS_ENTER, "invariant"); |
|
1792 assert(List != iterator, "invariant"); |
|
1793 } |
|
1794 |
|
1795 if (Policy == 0) { // prepend to EntryList |
|
1796 if (List == NULL) { |
|
1797 iterator->_next = iterator->_prev = NULL; |
|
1798 _EntryList = iterator; |
|
1799 } else { |
|
1800 List->_prev = iterator; |
|
1801 iterator->_next = List; |
|
1802 iterator->_prev = NULL; |
|
1803 _EntryList = iterator; |
|
1804 } |
|
1805 } else if (Policy == 1) { // append to EntryList |
|
1806 if (List == NULL) { |
|
1807 iterator->_next = iterator->_prev = NULL; |
|
1808 _EntryList = iterator; |
|
1809 } else { |
|
1810 // CONSIDER: finding the tail currently requires a linear-time walk of |
|
1811 // the EntryList. We can make tail access constant-time by converting to |
|
1812 // a CDLL instead of using our current DLL. |
|
1813 ObjectWaiter * Tail; |
|
1814 for (Tail = List; Tail->_next != NULL; Tail = Tail->_next) /* empty */; |
|
1815 assert(Tail != NULL && Tail->_next == NULL, "invariant"); |
|
1816 Tail->_next = iterator; |
|
1817 iterator->_prev = Tail; |
|
1818 iterator->_next = NULL; |
|
1819 } |
|
1820 } else if (Policy == 2) { // prepend to cxq |
|
1821 // prepend to cxq |
|
1822 iterator->TState = ObjectWaiter::TS_CXQ; |
|
1823 for (;;) { |
|
1824 ObjectWaiter * Front = _cxq; |
|
1825 iterator->_next = Front; |
|
1826 if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) { |
|
1827 break; |
|
1828 } |
|
1829 } |
|
1830 } else if (Policy == 3) { // append to cxq |
|
1831 iterator->TState = ObjectWaiter::TS_CXQ; |
|
1832 for (;;) { |
|
1833 ObjectWaiter * Tail; |
|
1834 Tail = _cxq; |
|
1835 if (Tail == NULL) { |
|
1836 iterator->_next = NULL; |
|
1837 if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) { |
|
1838 break; |
|
1839 } |
|
1840 } else { |
|
1841 while (Tail->_next != NULL) Tail = Tail->_next; |
|
1842 Tail->_next = iterator; |
|
1843 iterator->_prev = Tail; |
|
1844 iterator->_next = NULL; |
|
1845 break; |
|
1846 } |
|
1847 } |
|
1848 } else { |
|
1849 ParkEvent * ev = iterator->_event; |
|
1850 iterator->TState = ObjectWaiter::TS_RUN; |
|
1851 OrderAccess::fence(); |
|
1852 ev->unpark(); |
|
1853 } |
|
1854 |
|
1855 if (Policy < 4) { |
|
1856 iterator->wait_reenter_begin(this); |
|
1857 } |
|
1858 |
|
1859 // _WaitSetLock protects the wait queue, not the EntryList. We could |
|
1860 // move the add-to-EntryList operation, above, outside the critical section |
|
1861 // protected by _WaitSetLock. In practice that's not useful. With the |
|
1862 // exception of wait() timeouts and interrupts the monitor owner |
|
1863 // is the only thread that grabs _WaitSetLock. There's almost no contention |
|
1864 // on _WaitSetLock so it's not profitable to reduce the length of the |
|
1865 // critical section. |
|
1866 } |
|
1867 |
|
1868 Thread::SpinRelease(&_WaitSetLock); |
|
1869 |
|
1870 if (Tally != 0 && ObjectMonitor::_sync_Notifications != NULL) { |
|
1871 ObjectMonitor::_sync_Notifications->inc(Tally); |
|
1872 } |
1797 } |
1873 } |
1798 } |
1874 |
1799 |
1875 // ----------------------------------------------------------------------------- |
1800 // ----------------------------------------------------------------------------- |
1876 // Adaptive Spinning Support |
1801 // Adaptive Spinning Support |