src/share/vm/runtime/synchronizer.cpp
Print this page
@@ -939,11 +939,11 @@
ObjectMonitor* mid;
int inusetally = 0;
for (mid = Self->omInUseList; mid != NULL; mid = mid->FreeNext) {
inusetally++;
}
- assert(inusetally == Self->omInUseCount, "inuse count off");
+ assert(inusetally == Self->omInUseCount, "in use count off");
int freetally = 0;
for (mid = Self->omFreeList; mid != NULL; mid = mid->FreeNext) {
freetally++;
}
@@ -1092,36 +1092,40 @@
// In practice there's no need to clamp or limit the number of
// monitors on a thread's omFreeList as the only time we'll call
// omRelease is to return a monitor to the free list after a CAS
// attempt failed. This doesn't allow unbounded #s of monitors to
// accumulate on a thread's free list.
+//
+// Key constraint: all ObjectMonitors on a thread's free list and the global
+// free list must have their object field set to null. This prevents the
+// scavenger -- deflate_idle_monitors -- from reclaiming them.
void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m,
bool fromPerThreadAlloc) {
guarantee(m->object() == NULL, "invariant");
-
+ guarantee(((m->is_busy()|m->_recursions) == 0), "freeing in use monitor");
// Remove from omInUseList
if (MonitorInUseLists && fromPerThreadAlloc) {
ObjectMonitor* curmidinuse = NULL;
- for (ObjectMonitor* mid = Self->omInUseList; mid != NULL;) {
+ bool extracted = false;
+ for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; curmidinuse = mid, mid = mid->FreeNext) {
if (m == mid) {
// extract from per-thread in-use-list
if (mid == Self->omInUseList) {
Self->omInUseList = mid->FreeNext;
} else if (curmidinuse != NULL) {
curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
}
+ extracted = true;
Self->omInUseCount--;
if (ObjectMonitor::Knob_VerifyInUse) {
verifyInUse(Self);
}
break;
- } else {
- curmidinuse = mid;
- mid = mid->FreeNext;
}
}
+ assert(extracted, "Should have extracted from in use list");
}
// FreeNext is used for both omInUseList and omFreeList, so clear old before setting new
m->FreeNext = Self->omFreeList;
Self->omFreeList = m;
@@ -1153,10 +1157,14 @@
Self->omFreeList = NULL;
ObjectMonitor * Tail = NULL;
int Tally = 0;
if (List != NULL) {
ObjectMonitor * s;
+ // The thread is going away, the per-thread free monitors
+ // are freed via set_owner(NULL)
+ // Link them to Tail, which will be linked into the global free list
+ // gFreeList below, under the ListLock
for (s = List; s != NULL; s = s->FreeNext) {
Tally++;
Tail = s;
guarantee(s->object() == NULL, "invariant");
guarantee(!s->is_busy(), "invariant");
@@ -1170,15 +1178,19 @@
ObjectMonitor * InUseTail = NULL;
int InUseTally = 0;
if (InUseList != NULL) {
Self->omInUseList = NULL;
ObjectMonitor *curom;
+ // The thread is going away, however the omInUseList inflated
+ // monitors may still be in use by other threads.
+ // Link them to InUseTail, which will be linked into the global in use list
+ // gOmInUseList below, under the ListLock
for (curom = InUseList; curom != NULL; curom = curom->FreeNext) {
InUseTail = curom;
InUseTally++;
}
- assert(Self->omInUseCount == InUseTally, "inuse count off");
+ assert(Self->omInUseCount == InUseTally, "in use count off");
Self->omInUseCount = 0;
guarantee(InUseTail != NULL && InUseList != NULL, "invariant");
}
Thread::muxAcquire(&ListLock, "omFlush");
@@ -1409,18 +1421,18 @@
// impacts the performance of some applications (e.g., PointBase).
// Broadly, we want to minimize the # of monitors in circulation.
//
// We have added a flag, MonitorInUseLists, which creates a list
// of active monitors for each thread. deflate_idle_monitors()
-// only scans the per-thread inuse lists. omAlloc() puts all
+// only scans the per-thread in use lists. omAlloc() puts all
// assigned monitors on the per-thread list. deflate_idle_monitors()
// returns the non-busy monitors to the global free list.
// When a thread dies, omFlush() adds the list of active monitors for
// that thread to a global gOmInUseList acquiring the
// global list lock. deflate_idle_monitors() acquires the global
// list lock to scan for non-busy monitors to the global free list.
-// An alternative could have used a single global inuse list. The
+// An alternative could have used a single global in use list. The
// downside would have been the additional cost of acquiring the global list lock
// for every omAlloc().
//
// Perversely, the heap size -- and thus the STW safepoint rate --
// typically drives the scavenge rate. Large heaps can mean infrequent GC,
@@ -1476,26 +1488,25 @@
deflated = true;
}
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 ListLock
-int ObjectSynchronizer::walk_monitor_list(ObjectMonitor** listheadp,
+int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** listheadp,
ObjectMonitor** freeHeadp,
ObjectMonitor** freeTailp) {
ObjectMonitor* mid;
ObjectMonitor* next;
ObjectMonitor* curmidinuse = NULL;
int deflatedcount = 0;
for (mid = *listheadp; mid != NULL;) {
oop obj = (oop) mid->object();
- bool deflated = false;
- if (obj != NULL) {
- deflated = deflate_monitor(mid, obj, freeHeadp, freeTailp);
- }
- if (deflated) {
+ if (obj != NULL && deflate_monitor(mid, obj, freeHeadp, freeTailp)) {
+ // if deflate_monitor succeeded,/moribund
// extract from per-thread in-use-list
if (mid == *listheadp) {
*listheadp = mid->FreeNext;
} else if (curmidinuse != NULL) {
curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
@@ -1530,11 +1541,11 @@
if (MonitorInUseLists) {
int inUse = 0;
for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) {
nInCirculation+= cur->omInUseCount;
- int deflatedcount = walk_monitor_list(cur->omInUseList_addr(), &FreeHead, &FreeTail);
+ int deflatedcount = deflate_monitor_list(cur->omInUseList_addr(), &FreeHead, &FreeTail);
cur->omInUseCount-= deflatedcount;
if (ObjectMonitor::Knob_VerifyInUse) {
verifyInUse(cur);
}
nScavenged += deflatedcount;
@@ -1542,11 +1553,11 @@
}
// For moribund threads, scan gOmInUseList
if (gOmInUseList) {
nInCirculation += gOmInUseCount;
- int deflatedcount = walk_monitor_list((ObjectMonitor **)&gOmInUseList, &FreeHead, &FreeTail);
+ int deflatedcount = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &FreeHead, &FreeTail);
gOmInUseCount-= deflatedcount;
nScavenged += deflatedcount;
nInuse += gOmInUseCount;
}