< prev index next >

src/share/vm/runtime/synchronizer.cpp

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

*** 1659,1669 **** return deflated; } // Walk a given monitor list, and deflate idle monitors // The given list could be a per-thread list or a global list ! // Caller acquires gListLock int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** listHeadp, ObjectMonitor** freeHeadp, ObjectMonitor** freeTailp) { ObjectMonitor* mid; ObjectMonitor* next; --- 1659,1679 ---- return deflated; } // Walk a given monitor list, and deflate idle monitors // The given list could be a per-thread list or a global list ! // Caller acquires gListLock. ! // ! // In the case of parallel processing of thread local monitor lists, ! // work is done by Threads::parallel_threads_do() which ensures that ! // each Java thread is processed by exactly one worker thread, and ! // thus avoid conflicts that would arise when worker threads would ! // process the same monitor lists concurrently. ! // ! // See also ParallelSPCleanupTask and ! // SafepointSynchronizer::do_cleanup_tasks() in safepoint.cpp and ! // Threads::parallel_java_threads_do() in thread.cpp. int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** listHeadp, ObjectMonitor** freeHeadp, ObjectMonitor** freeTailp) { ObjectMonitor* mid; ObjectMonitor* next;
*** 1690,1704 **** } } return deflated_count; } ! void ObjectSynchronizer::deflate_idle_monitors() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - int nInuse = 0; // currently associated with objects - int nInCirculation = 0; // extant - int nScavenged = 0; // reclaimed bool deflated = false; ObjectMonitor * freeHeadp = NULL; // Local SLL of scavenged monitors ObjectMonitor * freeTailp = NULL; --- 1700,1717 ---- } } return deflated_count; } ! void ObjectSynchronizer::prepare_deflate_idle_monitors(DeflateMonitorCounters* counters) { ! counters->nInuse = 0; // currently associated with objects ! counters->nInCirculation = 0; // extant ! counters->nScavenged = 0; // reclaimed ! } ! ! void ObjectSynchronizer::deflate_idle_monitors(DeflateMonitorCounters* counters) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); bool deflated = false; ObjectMonitor * freeHeadp = NULL; // Local SLL of scavenged monitors ObjectMonitor * freeTailp = NULL;
*** 1707,1744 **** // And in case the vm thread is acquiring a lock during a safepoint // See e.g. 6320749 Thread::muxAcquire(&gListLock, "scavenge - return"); if (MonitorInUseLists) { ! int inUse = 0; ! for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) { ! nInCirculation+= cur->omInUseCount; ! int deflated_count = deflate_monitor_list(cur->omInUseList_addr(), &freeHeadp, &freeTailp); ! cur->omInUseCount-= deflated_count; ! if (ObjectMonitor::Knob_VerifyInUse) { ! verifyInUse(cur); ! } ! nScavenged += deflated_count; ! nInuse += cur->omInUseCount; ! } // For moribund threads, scan gOmInUseList if (gOmInUseList) { ! nInCirculation += gOmInUseCount; int deflated_count = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &freeHeadp, &freeTailp); ! gOmInUseCount-= deflated_count; ! nScavenged += deflated_count; ! nInuse += gOmInUseCount; } } else { PaddedEnd<ObjectMonitor> * block = (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList); for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)next(block)) { // Iterate over all extant monitors - Scavenge all idle monitors. assert(block->object() == CHAINMARKER, "must be a block header"); ! nInCirculation += _BLOCKSIZE; for (int i = 1; i < _BLOCKSIZE; i++) { ObjectMonitor* mid = (ObjectMonitor*)&block[i]; oop obj = (oop)mid->object(); if (obj == NULL) { --- 1720,1748 ---- // And in case the vm thread is acquiring a lock during a safepoint // See e.g. 6320749 Thread::muxAcquire(&gListLock, "scavenge - return"); if (MonitorInUseLists) { ! // Note: the thread-local monitors lists get deflated in ! // a separate pass. See deflate_thread_local_monitors(). // For moribund threads, scan gOmInUseList if (gOmInUseList) { ! counters->nInCirculation += gOmInUseCount; int deflated_count = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &freeHeadp, &freeTailp); ! gOmInUseCount -= deflated_count; ! counters->nScavenged += deflated_count; ! counters->nInuse += gOmInUseCount; } } else { PaddedEnd<ObjectMonitor> * block = (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList); for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)next(block)) { // Iterate over all extant monitors - Scavenge all idle monitors. assert(block->object() == CHAINMARKER, "must be a block header"); ! counters->nInCirculation += _BLOCKSIZE; for (int i = 1; i < _BLOCKSIZE; i++) { ObjectMonitor* mid = (ObjectMonitor*)&block[i]; oop obj = (oop)mid->object(); if (obj == NULL) {
*** 1751,1799 **** } deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp); if (deflated) { mid->FreeNext = NULL; ! nScavenged++; } else { ! nInuse++; } } } } ! gMonitorFreeCount += nScavenged; // Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree. if (ObjectMonitor::Knob_Verbose) { tty->print_cr("INFO: Deflate: InCirc=%d InUse=%d Scavenged=%d " "ForceMonitorScavenge=%d : pop=%d free=%d", ! nInCirculation, nInuse, nScavenged, ForceMonitorScavenge, gMonitorPopulation, gMonitorFreeCount); tty->flush(); } ForceMonitorScavenge = 0; // Reset // Move the scavenged monitors back to the global free list. if (freeHeadp != NULL) { ! guarantee(freeTailp != NULL && nScavenged > 0, "invariant"); assert(freeTailp->FreeNext == NULL, "invariant"); // constant-time list splice - prepend scavenged segment to gFreeList freeTailp->FreeNext = gFreeList; gFreeList = freeHeadp; } Thread::muxRelease(&gListLock); - - OM_PERFDATA_OP(Deflations, inc(nScavenged)); - OM_PERFDATA_OP(MonExtant, set_value(nInCirculation)); - - // TODO: Add objectMonitor leak detection. - // Audit/inventory the objectMonitors -- make sure they're all accounted for. - GVars.stwRandom = os::random(); - GVars.stwCycle++; } // Monitor cleanup on JavaThread::exit // Iterate through monitor cache and attempt to release thread's monitors --- 1755,1838 ---- } deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp); if (deflated) { mid->FreeNext = NULL; ! counters->nScavenged++; } else { ! counters->nInuse++; } } } } ! // Move the scavenged monitors back to the global free list. ! if (freeHeadp != NULL) { ! guarantee(freeTailp != NULL && counters->nScavenged > 0, "invariant"); ! assert(freeTailp->FreeNext == NULL, "invariant"); ! // constant-time list splice - prepend scavenged segment to gFreeList ! freeTailp->FreeNext = gFreeList; ! gFreeList = freeHeadp; ! } ! Thread::muxRelease(&gListLock); ! ! } ! ! void ObjectSynchronizer::finish_deflate_idle_monitors(DeflateMonitorCounters* counters) { ! gMonitorFreeCount += counters->nScavenged; // Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree. if (ObjectMonitor::Knob_Verbose) { tty->print_cr("INFO: Deflate: InCirc=%d InUse=%d Scavenged=%d " "ForceMonitorScavenge=%d : pop=%d free=%d", ! counters->nInCirculation, counters->nInuse, counters->nScavenged, ForceMonitorScavenge, gMonitorPopulation, gMonitorFreeCount); tty->flush(); } ForceMonitorScavenge = 0; // Reset + OM_PERFDATA_OP(Deflations, inc(counters->nScavenged)); + OM_PERFDATA_OP(MonExtant, set_value(counters->nInCirculation)); + + // TODO: Add objectMonitor leak detection. + // Audit/inventory the objectMonitors -- make sure they're all accounted for. + GVars.stwRandom = os::random(); + GVars.stwCycle++; + } + + void ObjectSynchronizer::deflate_thread_local_monitors(Thread* thread, DeflateMonitorCounters* counters) { + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); + if (!MonitorInUseLists) return; + + ObjectMonitor * freeHeadp = NULL; // Local SLL of scavenged monitors + ObjectMonitor * freeTailp = NULL; + + int deflated_count = deflate_monitor_list(thread->omInUseList_addr(), &freeHeadp, &freeTailp); + + Thread::muxAcquire(&gListLock, "scavenge - return"); + + // Adjust counters + counters->nInCirculation += thread->omInUseCount; + thread->omInUseCount -= deflated_count; + if (ObjectMonitor::Knob_VerifyInUse) { + verifyInUse(thread); + } + counters->nScavenged += deflated_count; + counters->nInuse += thread->omInUseCount; + // Move the scavenged monitors back to the global free list. if (freeHeadp != NULL) { ! guarantee(freeTailp != NULL && deflated_count > 0, "invariant"); assert(freeTailp->FreeNext == NULL, "invariant"); + // constant-time list splice - prepend scavenged segment to gFreeList freeTailp->FreeNext = gFreeList; gFreeList = freeHeadp; } Thread::muxRelease(&gListLock); } // Monitor cleanup on JavaThread::exit // Iterate through monitor cache and attempt to release thread's monitors
< prev index next >