< prev index next >
src/share/vm/runtime/synchronizer.cpp
Print this page
rev 13233 : 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 >