--- old/src/share/vm/runtime/synchronizer.cpp Mon Mar 9 09:41:03 2015 +++ new/src/share/vm/runtime/synchronizer.cpp Mon Mar 9 09:41:03 2015 @@ -941,7 +941,7 @@ 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) { @@ -1094,15 +1094,20 @@ // 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) { @@ -1110,16 +1115,15 @@ } 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 @@ -1155,6 +1159,10 @@ 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; @@ -1172,11 +1180,15 @@ 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"); } @@ -1411,7 +1423,7 @@ // // 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 @@ -1418,7 +1430,7 @@ // 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(). // @@ -1478,10 +1490,12 @@ 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, - ObjectMonitor** freeHeadp, - ObjectMonitor** freeTailp) { +int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** listheadp, + ObjectMonitor** freeHeadp, + ObjectMonitor** freeTailp) { ObjectMonitor* mid; ObjectMonitor* next; ObjectMonitor* curmidinuse = NULL; @@ -1489,11 +1503,8 @@ 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; @@ -1532,7 +1543,7 @@ 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); @@ -1544,7 +1555,7 @@ // 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;