Details

Description

I've attached a test case, Inflation.java, that shows a growth in the number of extant monitors asympotitically up to T * MAXPRIVATE where T is the number of live threads and MAXPRIVATE is a constant defined in synchronizer.cpp, currently 1024. Instructions for running the program are in comments at the top of Inflation.java. More details about the pathology are comments in that file.

An extremely simple fix that I tested is to :

(a) add a new Thread.omFreeEpoch field, initialized to 0 in the thread ctor

(b) in synchronizer.cpp omAlloc(), we change

Self->omFreeProvision += 1 + (Self->omFreeProvision/2) ;

to
int Epoch = GVars.stwCycle ;
if (Self->omFreeEpoch == Epoch) {
Self->omFreeProvision += 1 + (Self->omFreeProvision/2) ;
if (Self->omFreeProvision > MAXPRIVATE ) Self->omFreeProvision = MAXPRIVATE ;
} else {
// Avoid the scenario where we can have asymptotic growth
// of the number of monitors up to T * MAXPRIVATE where T is the
// number of extant threads. This can occur if threads
// were to loop, inflating, and then sleeping, and during the sleep period
// the monitor was idle and GC activity cause safepoints.
// In that case monitors rapidly circulate from the global free list to local lists,
// to then be inflated, to then be default in deflate_idle_monitors and then
// to return to the global free list. Such circulation tends to cause
// omFreeProvision to creep up to MAXPRIVATE, which in turn causes more
// monitors to be created as threads draw larger segments from the global list.
// Either decay (halve) or reset omFreeProvision.
// In addition, we might consider an enhancement to trim or cull the
// thread-local free lists at STW-time.
Self->omFreeProvision = 16 ;
}
Self->omFreeEpoch = Epoch ;