< prev index next >

src/share/vm/runtime/synchronizer.cpp

Print this page
rev 13114 : 8180932: Parallelize safepoint cleanup
Summary: Provide infrastructure to do safepoint cleanup tasks using parallel worker threads
Reviewed-by: dholmes, rehn


1676     if (obj != NULL && deflate_monitor(mid, obj, freeHeadp, freeTailp)) {
1677       // if deflate_monitor succeeded,
1678       // extract from per-thread in-use list
1679       if (mid == *listHeadp) {
1680         *listHeadp = mid->FreeNext;
1681       } else if (cur_mid_in_use != NULL) {
1682         cur_mid_in_use->FreeNext = mid->FreeNext; // maintain the current thread in-use list
1683       }
1684       next = mid->FreeNext;
1685       mid->FreeNext = NULL;  // This mid is current tail in the freeHeadp list
1686       mid = next;
1687       deflated_count++;
1688     } else {
1689       cur_mid_in_use = mid;
1690       mid = mid->FreeNext;
1691     }
1692   }
1693   return deflated_count;
1694 }
1695 
1696 void ObjectSynchronizer::deflate_idle_monitors() {






1697   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
1698   int nInuse = 0;              // currently associated with objects
1699   int nInCirculation = 0;      // extant
1700   int nScavenged = 0;          // reclaimed
1701   bool deflated = false;
1702 
1703   ObjectMonitor * freeHeadp = NULL;  // Local SLL of scavenged monitors
1704   ObjectMonitor * freeTailp = NULL;
1705 
1706   TEVENT(deflate_idle_monitors);
1707   // Prevent omFlush from changing mids in Thread dtor's during deflation
1708   // And in case the vm thread is acquiring a lock during a safepoint
1709   // See e.g. 6320749
1710   Thread::muxAcquire(&gListLock, "scavenge - return");
1711 
1712   if (MonitorInUseLists) {
1713     int inUse = 0;
1714     for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) {
1715       nInCirculation+= cur->omInUseCount;
1716       int deflated_count = deflate_monitor_list(cur->omInUseList_addr(), &freeHeadp, &freeTailp);
1717       cur->omInUseCount-= deflated_count;
1718       if (ObjectMonitor::Knob_VerifyInUse) {
1719         verifyInUse(cur);
1720       }
1721       nScavenged += deflated_count;
1722       nInuse += cur->omInUseCount;
1723     }
1724 
1725     // For moribund threads, scan gOmInUseList
1726     if (gOmInUseList) {
1727       nInCirculation += gOmInUseCount;
1728       int deflated_count = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &freeHeadp, &freeTailp);
1729       gOmInUseCount-= deflated_count;
1730       nScavenged += deflated_count;
1731       nInuse += gOmInUseCount;
1732     }
1733 
1734   } else {
1735     PaddedEnd<ObjectMonitor> * block =
1736       (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
1737     for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)next(block)) {
1738       // Iterate over all extant monitors - Scavenge all idle monitors.
1739       assert(block->object() == CHAINMARKER, "must be a block header");
1740       nInCirculation += _BLOCKSIZE;
1741       for (int i = 1; i < _BLOCKSIZE; i++) {
1742         ObjectMonitor* mid = (ObjectMonitor*)&block[i];
1743         oop obj = (oop)mid->object();
1744 
1745         if (obj == NULL) {
1746           // The monitor is not associated with an object.
1747           // The monitor should either be a thread-specific private
1748           // free list or the global free list.
1749           // obj == NULL IMPLIES mid->is_busy() == 0
1750           guarantee(!mid->is_busy(), "invariant");
1751           continue;
1752         }
1753         deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp);
1754 
1755         if (deflated) {
1756           mid->FreeNext = NULL;
1757           nScavenged++;
1758         } else {
1759           nInuse++;
1760         }
1761       }
1762     }
1763   }
1764 
1765   gMonitorFreeCount += nScavenged;













1766 
1767   // Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree.
1768 
1769   if (ObjectMonitor::Knob_Verbose) {
1770     tty->print_cr("INFO: Deflate: InCirc=%d InUse=%d Scavenged=%d "
1771                   "ForceMonitorScavenge=%d : pop=%d free=%d",
1772                   nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,
1773                   gMonitorPopulation, gMonitorFreeCount);
1774     tty->flush();
1775   }
1776 
1777   ForceMonitorScavenge = 0;    // Reset
1778 






























1779   // Move the scavenged monitors back to the global free list.
1780   if (freeHeadp != NULL) {
1781     guarantee(freeTailp != NULL && nScavenged > 0, "invariant");
1782     assert(freeTailp->FreeNext == NULL, "invariant");

1783     // constant-time list splice - prepend scavenged segment to gFreeList
1784     freeTailp->FreeNext = gFreeList;
1785     gFreeList = freeHeadp;
1786   }
1787   Thread::muxRelease(&gListLock);
1788 
1789   OM_PERFDATA_OP(Deflations, inc(nScavenged));
1790   OM_PERFDATA_OP(MonExtant, set_value(nInCirculation));
1791 
1792   // TODO: Add objectMonitor leak detection.
1793   // Audit/inventory the objectMonitors -- make sure they're all accounted for.
1794   GVars.stwRandom = os::random();
1795   GVars.stwCycle++;
1796 }
1797 
1798 // Monitor cleanup on JavaThread::exit
1799 
1800 // Iterate through monitor cache and attempt to release thread's monitors
1801 // Gives up on a particular monitor if an exception occurs, but continues
1802 // the overall iteration, swallowing the exception.
1803 class ReleaseJavaMonitorsClosure: public MonitorClosure {
1804  private:
1805   TRAPS;
1806 
1807  public:
1808   ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
1809   void do_monitor(ObjectMonitor* mid) {
1810     if (mid->owner() == THREAD) {
1811       if (ObjectMonitor::Knob_VerifyMatch != 0) {
1812         ResourceMark rm;
1813         Handle obj(THREAD, (oop) mid->object());
1814         tty->print("INFO: unexpected locked object:");
1815         javaVFrame::print_locked_object_class_name(tty, obj, "locked");




1676     if (obj != NULL && deflate_monitor(mid, obj, freeHeadp, freeTailp)) {
1677       // if deflate_monitor succeeded,
1678       // extract from per-thread in-use list
1679       if (mid == *listHeadp) {
1680         *listHeadp = mid->FreeNext;
1681       } else if (cur_mid_in_use != NULL) {
1682         cur_mid_in_use->FreeNext = mid->FreeNext; // maintain the current thread in-use list
1683       }
1684       next = mid->FreeNext;
1685       mid->FreeNext = NULL;  // This mid is current tail in the freeHeadp list
1686       mid = next;
1687       deflated_count++;
1688     } else {
1689       cur_mid_in_use = mid;
1690       mid = mid->FreeNext;
1691     }
1692   }
1693   return deflated_count;
1694 }
1695 
1696 void ObjectSynchronizer::prepare_deflate_idle_monitors(DeflateMonitorCounters* counters) {
1697   counters->nInuse = 0;         // currently associated with objects
1698   counters->nInCirculation = 0; // extant
1699   counters->nScavenged = 0;      // reclaimed
1700 }
1701 
1702 void ObjectSynchronizer::deflate_idle_monitors(DeflateMonitorCounters* counters) {
1703   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");



1704   bool deflated = false;
1705 
1706   ObjectMonitor * freeHeadp = NULL;  // Local SLL of scavenged monitors
1707   ObjectMonitor * freeTailp = NULL;
1708 
1709   TEVENT(deflate_idle_monitors);
1710   // Prevent omFlush from changing mids in Thread dtor's during deflation
1711   // And in case the vm thread is acquiring a lock during a safepoint
1712   // See e.g. 6320749
1713   Thread::muxAcquire(&gListLock, "scavenge - return");
1714 
1715   if (MonitorInUseLists) {
1716     // Note: the thread-local monitors lists get deflated in
1717     // a separate pass. See deflate_thread_local_monitors().









1718 
1719     // For moribund threads, scan gOmInUseList
1720     if (gOmInUseList) {
1721       counters->nInCirculation += gOmInUseCount;
1722       int deflated_count = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &freeHeadp, &freeTailp);
1723       gOmInUseCount-= deflated_count;
1724       counters->nScavenged += deflated_count;
1725       counters->nInuse += gOmInUseCount;
1726     }
1727 
1728   } else {
1729     PaddedEnd<ObjectMonitor> * block =
1730       (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
1731     for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)next(block)) {
1732       // Iterate over all extant monitors - Scavenge all idle monitors.
1733       assert(block->object() == CHAINMARKER, "must be a block header");
1734       counters->nInCirculation += _BLOCKSIZE;
1735       for (int i = 1; i < _BLOCKSIZE; i++) {
1736         ObjectMonitor* mid = (ObjectMonitor*)&block[i];
1737         oop obj = (oop)mid->object();
1738 
1739         if (obj == NULL) {
1740           // The monitor is not associated with an object.
1741           // The monitor should either be a thread-specific private
1742           // free list or the global free list.
1743           // obj == NULL IMPLIES mid->is_busy() == 0
1744           guarantee(!mid->is_busy(), "invariant");
1745           continue;
1746         }
1747         deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp);
1748 
1749         if (deflated) {
1750           mid->FreeNext = NULL;
1751           counters->nScavenged++;
1752         } else {
1753           counters->nInuse++;
1754         }
1755       }
1756     }
1757   }
1758 
1759   // Move the scavenged monitors back to the global free list.
1760   if (freeHeadp != NULL) {
1761     guarantee(freeTailp != NULL && counters->nScavenged > 0, "invariant");
1762     assert(freeTailp->FreeNext == NULL, "invariant");
1763     // constant-time list splice - prepend scavenged segment to gFreeList
1764     freeTailp->FreeNext = gFreeList;
1765     gFreeList = freeHeadp;
1766   }
1767   Thread::muxRelease(&gListLock);
1768 
1769 }
1770 
1771 void ObjectSynchronizer::finish_deflate_idle_monitors(DeflateMonitorCounters* counters) {
1772   gMonitorFreeCount += counters->nScavenged;
1773 
1774   // Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree.
1775 
1776   if (ObjectMonitor::Knob_Verbose) {
1777     tty->print_cr("INFO: Deflate: InCirc=%d InUse=%d Scavenged=%d "
1778                   "ForceMonitorScavenge=%d : pop=%d free=%d",
1779                   counters->nInCirculation, counters->nInuse, counters->nScavenged, ForceMonitorScavenge,
1780                   gMonitorPopulation, gMonitorFreeCount);
1781     tty->flush();
1782   }
1783 
1784   ForceMonitorScavenge = 0;    // Reset
1785 
1786   OM_PERFDATA_OP(Deflations, inc(counters->nScavenged));
1787   OM_PERFDATA_OP(MonExtant, set_value(counters->nInCirculation));
1788 
1789   // TODO: Add objectMonitor leak detection.
1790   // Audit/inventory the objectMonitors -- make sure they're all accounted for.
1791   GVars.stwRandom = os::random();
1792   GVars.stwCycle++;
1793 }
1794 
1795 void ObjectSynchronizer::deflate_thread_local_monitors(Thread* thread, DeflateMonitorCounters* counters) {
1796   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
1797   if (! MonitorInUseLists) return;
1798 
1799   ObjectMonitor * freeHeadp = NULL;  // Local SLL of scavenged monitors
1800   ObjectMonitor * freeTailp = NULL;
1801 
1802   int deflated_count = deflate_monitor_list(thread->omInUseList_addr(), &freeHeadp, &freeTailp);
1803 
1804   Thread::muxAcquire(&gListLock, "scavenge - return");
1805 
1806   // Adjust counters
1807   counters->nInCirculation += thread->omInUseCount;
1808   thread->omInUseCount-= deflated_count;
1809   if (ObjectMonitor::Knob_VerifyInUse) {
1810     verifyInUse(thread);
1811   }
1812   counters->nScavenged += deflated_count;
1813   counters->nInuse += thread->omInUseCount;
1814   gMonitorFreeCount += deflated_count;
1815 
1816   // Move the scavenged monitors back to the global free list.
1817   if (freeHeadp != NULL) {
1818     guarantee(freeTailp != NULL && deflated_count > 0, "invariant");
1819     assert(freeTailp->FreeNext == NULL, "invariant");
1820 
1821     // constant-time list splice - prepend scavenged segment to gFreeList
1822     freeTailp->FreeNext = gFreeList;
1823     gFreeList = freeHeadp;
1824   }
1825   Thread::muxRelease(&gListLock);








1826 }
1827 
1828 // Monitor cleanup on JavaThread::exit
1829 
1830 // Iterate through monitor cache and attempt to release thread's monitors
1831 // Gives up on a particular monitor if an exception occurs, but continues
1832 // the overall iteration, swallowing the exception.
1833 class ReleaseJavaMonitorsClosure: public MonitorClosure {
1834  private:
1835   TRAPS;
1836 
1837  public:
1838   ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
1839   void do_monitor(ObjectMonitor* mid) {
1840     if (mid->owner() == THREAD) {
1841       if (ObjectMonitor::Knob_VerifyMatch != 0) {
1842         ResourceMark rm;
1843         Handle obj(THREAD, (oop) mid->object());
1844         tty->print("INFO: unexpected locked object:");
1845         javaVFrame::print_locked_object_class_name(tty, obj, "locked");


< prev index next >