< prev index next >
src/hotspot/share/runtime/synchronizer.cpp
Print this page
rev 56044 : imported patch 8230184.patch
rev 56046 : v2.00 -> v2.05 (CR5/v2.05/8-for-jdk13) patches combined into one; merge with 8229212.patch; merge with jdk-14+11; merge with 8230184.patch.
rev 56047 : renames, comment cleanups and additions, whitespace and indent fixes; add PaddedObjectMonitor typdef to make 'PaddedEnd<ObjectMonitor' cleanups easier; add a couple of missing 'private' decls; delete unused next() function; merge pieces from dcubed.monitor_deflate_conc.v2.06d in dcubed.monitor_deflate_conc.v2.06[ac]; merge with 8229212.patch; merge with jdk-14+11; merge with 8230184.patch.
rev 56048 : Add OM_CACHE_LINE_SIZE so that ObjectMonitor cache line sizes can be experimented with independently of DEFAULT_CACHE_LINE_SIZE; for SPARC and X64 configs that use 128 for DEFAULT_CACHE_LINE_SIZE, we are experimenting with 64; move _previous_owner_tid and _allocation_state fields to share the cache line with ObjectMonitor::_header; put ObjectMonitor::_ref_count on its own cache line after _owner; add 'int* count_p' parameter to deflate_monitor_list() and deflate_monitor_list_using_JT() and push counter updates down to where the ObjectMonitors are actually removed from the in-use lists; monitors_iterate() async deflation check should use negative ref_count; add 'JavaThread* target' param to deflate_per_thread_idle_monitors_using_JT() add deflate_common_idle_monitors_using_JT() to make it clear which JavaThread* is the target of the work and which is the calling JavaThread* (self); g_free_list, g_om_in_use_list and g_om_in_use_count are now static to synchronizer.cpp (reduce scope); add more diagnostic info to some assert()'s; minor code cleanups and code motion; save_om_ptr() should detect a race with a deflating thread that is bailing out and cause a retry when the ref_count field is not positive; merge with jdk-14+11; add special GC support for TestHumongousClassLoader.java; merge with 8230184.patch.
*** 116,138 ****
#define NINFLATIONLOCKS 256
static volatile intptr_t gInflationLocks[NINFLATIONLOCKS];
// global list of blocks of monitors
PaddedObjectMonitor* volatile ObjectSynchronizer::g_block_list = NULL;
// Global ObjectMonitor free list. Newly allocated and deflated
// ObjectMonitors are prepended here.
! ObjectMonitor* volatile ObjectSynchronizer::g_free_list = NULL;
// Global ObjectMonitor in-use list. When a JavaThread is exiting,
// ObjectMonitors on its per-thread in-use list are prepended here.
! ObjectMonitor* volatile ObjectSynchronizer::g_om_in_use_list = NULL;
! int ObjectSynchronizer::g_om_in_use_count = 0; // # on g_om_in_use_list
! bool volatile ObjectSynchronizer::_is_async_deflation_requested = false;
! bool volatile ObjectSynchronizer::_is_special_deflation_requested = false;
! jlong ObjectSynchronizer::_last_async_deflation_time_ns = 0;
static volatile intptr_t gListLock = 0; // protects global monitor lists
static volatile int g_om_free_count = 0; // # on g_free_list
static volatile int g_om_population = 0; // # Extant -- in circulation
#define CHAINMARKER (cast_to_oop<intptr_t>(-1))
--- 116,139 ----
#define NINFLATIONLOCKS 256
static volatile intptr_t gInflationLocks[NINFLATIONLOCKS];
// global list of blocks of monitors
PaddedObjectMonitor* volatile ObjectSynchronizer::g_block_list = NULL;
+ bool volatile ObjectSynchronizer::_is_async_deflation_requested = false;
+ bool volatile ObjectSynchronizer::_is_special_deflation_requested = false;
+ jlong ObjectSynchronizer::_last_async_deflation_time_ns = 0;
+
// Global ObjectMonitor free list. Newly allocated and deflated
// ObjectMonitors are prepended here.
! static ObjectMonitor* volatile g_free_list = NULL;
// Global ObjectMonitor in-use list. When a JavaThread is exiting,
// ObjectMonitors on its per-thread in-use list are prepended here.
! static ObjectMonitor* volatile g_om_in_use_list = NULL;
static volatile intptr_t gListLock = 0; // protects global monitor lists
static volatile int g_om_free_count = 0; // # on g_free_list
+ static volatile int g_om_in_use_count = 0; // # on g_om_in_use_list
static volatile int g_om_population = 0; // # Extant -- in circulation
#define CHAINMARKER (cast_to_oop<intptr_t>(-1))
*** 580,598 ****
// As a general policy we use "volatile" to control compiler-based reordering
// and explicit fences (barriers) to control for architectural reordering
// performed by the CPU(s) or platform.
struct SharedGlobals {
! char _pad_prefix[DEFAULT_CACHE_LINE_SIZE];
// These are highly shared mostly-read variables.
// To avoid false-sharing they need to be the sole occupants of a cache line.
volatile int stw_random;
volatile int stw_cycle;
! DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile int) * 2);
// Hot RW variable -- Sequester to avoid false-sharing
volatile int hc_sequence;
! DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile int));
};
static SharedGlobals GVars;
static int MonitorScavengeThreshold = 1000000;
static volatile int ForceMonitorScavenge = 0; // Scavenge required and pending
--- 581,599 ----
// As a general policy we use "volatile" to control compiler-based reordering
// and explicit fences (barriers) to control for architectural reordering
// performed by the CPU(s) or platform.
struct SharedGlobals {
! char _pad_prefix[OM_CACHE_LINE_SIZE];
// These are highly shared mostly-read variables.
// To avoid false-sharing they need to be the sole occupants of a cache line.
volatile int stw_random;
volatile int stw_cycle;
! DEFINE_PAD_MINUS_SIZE(1, OM_CACHE_LINE_SIZE, sizeof(volatile int) * 2);
// Hot RW variable -- Sequester to avoid false-sharing
volatile int hc_sequence;
! DEFINE_PAD_MINUS_SIZE(2, OM_CACHE_LINE_SIZE, sizeof(volatile int));
};
static SharedGlobals GVars;
static int MonitorScavengeThreshold = 1000000;
static volatile int ForceMonitorScavenge = 0; // Scavenge required and pending
*** 996,1011 ****
ObjectMonitor* mid = (ObjectMonitor *)(block + i);
if (mid->is_active()) {
ObjectMonitorHandle omh(mid);
if (mid->object() == NULL ||
! (AsyncDeflateIdleMonitors && mid->_owner == DEFLATER_MARKER)) {
// Only process with closure if the object is set.
// For async deflation, race here if monitor is not owned!
// The above ref_count bump (in ObjectMonitorHandle ctr)
// will cause subsequent async deflation to skip it.
! // However, previous or concurrent async deflation is a race.
continue;
}
closure->do_monitor(mid);
}
}
--- 997,1013 ----
ObjectMonitor* mid = (ObjectMonitor *)(block + i);
if (mid->is_active()) {
ObjectMonitorHandle omh(mid);
if (mid->object() == NULL ||
! (AsyncDeflateIdleMonitors && mid->ref_count() < 0)) {
// Only process with closure if the object is set.
// For async deflation, race here if monitor is not owned!
// The above ref_count bump (in ObjectMonitorHandle ctr)
// will cause subsequent async deflation to skip it.
! // However, previous or concurrent async deflation is a race
! // so skip this ObjectMonitor if it is being async deflated.
continue;
}
closure->do_monitor(mid);
}
}
*** 1096,1107 ****
void ObjectSynchronizer::list_oops_do(ObjectMonitor* list, OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
// The oops_do() phase does not overlap with monitor deflation
// so no need to update the ObjectMonitor's ref_count for this
// ObjectMonitor* use.
! ObjectMonitor* mid;
! for (mid = list; mid != NULL; mid = mid->_next_om) {
if (mid->object() != NULL) {
f->do_oop((oop*)mid->object_addr());
}
}
}
--- 1098,1108 ----
void ObjectSynchronizer::list_oops_do(ObjectMonitor* list, OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
// The oops_do() phase does not overlap with monitor deflation
// so no need to update the ObjectMonitor's ref_count for this
// ObjectMonitor* use.
! for (ObjectMonitor* mid = list; mid != NULL; mid = mid->_next_om) {
if (mid->object() != NULL) {
f->do_oop((oop*)mid->object_addr());
}
}
}
*** 1200,1210 ****
// Clean up your own mess (Gibbs Rule 45). Otherwise, skip this
// deflation. deflate_global_idle_monitors_using_JT() is called
// by the ServiceThread. Per-thread async deflation is triggered
// by the ServiceThread via om_request_deflation.
debug_only(jt->check_for_valid_safepoint_state(false);)
! ObjectSynchronizer::deflate_per_thread_idle_monitors_using_JT();
}
}
stringStream ss;
for (;;) {
--- 1201,1211 ----
// Clean up your own mess (Gibbs Rule 45). Otherwise, skip this
// deflation. deflate_global_idle_monitors_using_JT() is called
// by the ServiceThread. Per-thread async deflation is triggered
// by the ServiceThread via om_request_deflation.
debug_only(jt->check_for_valid_safepoint_state(false);)
! ObjectSynchronizer::deflate_per_thread_idle_monitors_using_JT(jt);
}
}
stringStream ss;
for (;;) {
*** 1287,1300 ****
// A better solution would be to use C++ placement-new.
// BEWARE: As it stands currently, we don't run the ctors!
assert(_BLOCKSIZE > 1, "invariant");
size_t neededsize = sizeof(PaddedObjectMonitor) * _BLOCKSIZE;
PaddedObjectMonitor* temp;
! size_t aligned_size = neededsize + (DEFAULT_CACHE_LINE_SIZE - 1);
void* real_malloc_addr = (void*)NEW_C_HEAP_ARRAY(char, aligned_size,
mtInternal);
! temp = (PaddedObjectMonitor*)align_up(real_malloc_addr, DEFAULT_CACHE_LINE_SIZE);
// NOTE: (almost) no way to recover if allocation failed.
// We might be able to induce a STW safepoint and scavenge enough
// ObjectMonitors to permit progress.
if (temp == NULL) {
--- 1288,1301 ----
// A better solution would be to use C++ placement-new.
// BEWARE: As it stands currently, we don't run the ctors!
assert(_BLOCKSIZE > 1, "invariant");
size_t neededsize = sizeof(PaddedObjectMonitor) * _BLOCKSIZE;
PaddedObjectMonitor* temp;
! size_t aligned_size = neededsize + (OM_CACHE_LINE_SIZE - 1);
void* real_malloc_addr = (void*)NEW_C_HEAP_ARRAY(char, aligned_size,
mtInternal);
! temp = (PaddedObjectMonitor*)align_up(real_malloc_addr, OM_CACHE_LINE_SIZE);
// NOTE: (almost) no way to recover if allocation failed.
// We might be able to induce a STW safepoint and scavenge enough
// ObjectMonitors to permit progress.
if (temp == NULL) {
*** 1412,1461 ****
// With AsyncDeflateIdleMonitors, deflate_global_idle_monitors_using_JT()
// and deflate_per_thread_idle_monitors_using_JT() (in another thread) can
// run at the same time as om_flush() so we have to be careful.
void ObjectSynchronizer::om_flush(Thread* self) {
! ObjectMonitor* free_list = self->om_free_list;
! ObjectMonitor* free_tail = NULL;
! int free_count = 0;
! if (free_list != NULL) {
! ObjectMonitor* s;
! // The thread is going away. Set 'free_tail' to the last per-thread free
! // monitor which will be linked to g_free_list below under the gListLock.
! stringStream ss;
! for (s = free_list; s != NULL; s = s->_next_om) {
! free_count++;
! free_tail = s;
! guarantee(s->object() == NULL, "invariant");
! guarantee(!s->is_busy(), "must be !is_busy: %s", s->is_busy_to_string(&ss));
! }
! guarantee(free_tail != NULL, "invariant");
! ADIM_guarantee(self->om_free_count == free_count, "free-count off");
! self->om_free_list = NULL;
! self->om_free_count = 0;
! }
!
ObjectMonitor* in_use_list = self->om_in_use_list;
ObjectMonitor* in_use_tail = NULL;
- int in_use_count = 0;
if (in_use_list != NULL) {
// The thread is going away, however the ObjectMonitors on the
// om_in_use_list may still be in-use by other threads. Link
// them to in_use_tail, which will be linked into the global
// in-use list g_om_in_use_list below, under the gListLock.
! ObjectMonitor *cur_om;
! for (cur_om = in_use_list; cur_om != NULL; cur_om = cur_om->_next_om) {
in_use_tail = cur_om;
in_use_count++;
ADIM_guarantee(cur_om->is_active(), "invariant");
}
guarantee(in_use_tail != NULL, "invariant");
ADIM_guarantee(self->om_in_use_count == in_use_count, "in-use count off");
self->om_in_use_list = NULL;
self->om_in_use_count = 0;
}
Thread::muxAcquire(&gListLock, "om_flush");
if (free_tail != NULL) {
free_tail->_next_om = g_free_list;
g_free_list = free_list;
g_om_free_count += free_count;
--- 1413,1460 ----
// With AsyncDeflateIdleMonitors, deflate_global_idle_monitors_using_JT()
// and deflate_per_thread_idle_monitors_using_JT() (in another thread) can
// run at the same time as om_flush() so we have to be careful.
void ObjectSynchronizer::om_flush(Thread* self) {
! int in_use_count = 0;
ObjectMonitor* in_use_list = self->om_in_use_list;
ObjectMonitor* in_use_tail = NULL;
if (in_use_list != NULL) {
// The thread is going away, however the ObjectMonitors on the
// om_in_use_list may still be in-use by other threads. Link
// them to in_use_tail, which will be linked into the global
// in-use list g_om_in_use_list below, under the gListLock.
! for (ObjectMonitor* cur_om = in_use_list; cur_om != NULL; cur_om = cur_om->_next_om) {
in_use_tail = cur_om;
in_use_count++;
ADIM_guarantee(cur_om->is_active(), "invariant");
}
guarantee(in_use_tail != NULL, "invariant");
ADIM_guarantee(self->om_in_use_count == in_use_count, "in-use count off");
self->om_in_use_list = NULL;
self->om_in_use_count = 0;
}
+ int free_count = 0;
+ ObjectMonitor* free_list = self->om_free_list;
+ ObjectMonitor* free_tail = NULL;
+ if (free_list != NULL) {
+ // The thread is going away. Set 'free_tail' to the last per-thread free
+ // monitor which will be linked to g_free_list below under the gListLock.
+ stringStream ss;
+ for (ObjectMonitor* s = free_list; s != NULL; s = s->_next_om) {
+ free_count++;
+ free_tail = s;
+ guarantee(s->object() == NULL, "invariant");
+ guarantee(!s->is_busy(), "must be !is_busy: %s", s->is_busy_to_string(&ss));
+ }
+ guarantee(free_tail != NULL, "invariant");
+ ADIM_guarantee(self->om_free_count == free_count, "free-count off");
+ self->om_free_list = NULL;
+ self->om_free_count = 0;
+ }
+
Thread::muxAcquire(&gListLock, "om_flush");
if (free_tail != NULL) {
free_tail->_next_om = g_free_list;
g_free_list = free_list;
g_om_free_count += free_count;
*** 1853,1863 ****
if (*free_tail_p != NULL) {
// We append to the list so the caller can use mid->_next_om
// to fix the linkages in its context.
ObjectMonitor* prevtail = *free_tail_p;
// Should have been cleaned up by the caller:
! assert(prevtail->_next_om == NULL, "cleaned up deflated?");
prevtail->_next_om = mid;
}
*free_tail_p = mid;
// At this point, mid->_next_om still refers to its current
// value and another ObjectMonitor's _next_om field still
--- 1852,1863 ----
if (*free_tail_p != NULL) {
// We append to the list so the caller can use mid->_next_om
// to fix the linkages in its context.
ObjectMonitor* prevtail = *free_tail_p;
// Should have been cleaned up by the caller:
! assert(prevtail->_next_om == NULL, "must be NULL: _next_om="
! INTPTR_FORMAT, p2i(prevtail->_next_om));
prevtail->_next_om = mid;
}
*free_tail_p = mid;
// At this point, mid->_next_om still refers to its current
// value and another ObjectMonitor's _next_om field still
*** 2020,2034 ****
//
// See also ParallelSPCleanupTask and
// SafepointSynchronize::do_cleanup_tasks() in safepoint.cpp and
// Threads::parallel_java_threads_do() in thread.cpp.
int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** list_p,
ObjectMonitor** free_head_p,
ObjectMonitor** free_tail_p) {
ObjectMonitor* mid;
ObjectMonitor* next;
- ObjectMonitor* cur_mid_in_use = NULL;
int deflated_count = 0;
for (mid = *list_p; mid != NULL;) {
oop obj = (oop) mid->object();
if (obj != NULL && deflate_monitor(mid, obj, free_head_p, free_tail_p)) {
--- 2020,2035 ----
//
// See also ParallelSPCleanupTask and
// SafepointSynchronize::do_cleanup_tasks() in safepoint.cpp and
// Threads::parallel_java_threads_do() in thread.cpp.
int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** list_p,
+ int* count_p,
ObjectMonitor** free_head_p,
ObjectMonitor** free_tail_p) {
+ ObjectMonitor* cur_mid_in_use = NULL;
ObjectMonitor* mid;
ObjectMonitor* next;
int deflated_count = 0;
for (mid = *list_p; mid != NULL;) {
oop obj = (oop) mid->object();
if (obj != NULL && deflate_monitor(mid, obj, free_head_p, free_tail_p)) {
*** 2042,2051 ****
--- 2043,2053 ----
}
next = mid->_next_om;
mid->_next_om = NULL; // This mid is current tail in the free_head_p list
mid = next;
deflated_count++;
+ *count_p = *count_p - 1;
} else {
cur_mid_in_use = mid;
mid = mid->_next_om;
}
}
*** 2058,2076 ****
// Caller acquires gListLock as appropriate. If a safepoint has started,
// then we save state via saved_mid_in_use_p and return to the caller to
// honor the safepoint.
//
int ObjectSynchronizer::deflate_monitor_list_using_JT(ObjectMonitor** list_p,
ObjectMonitor** free_head_p,
ObjectMonitor** free_tail_p,
ObjectMonitor** saved_mid_in_use_p) {
assert(AsyncDeflateIdleMonitors, "sanity check");
assert(Thread::current()->is_Java_thread(), "precondition");
ObjectMonitor* mid;
ObjectMonitor* next;
- ObjectMonitor* cur_mid_in_use = NULL;
int deflated_count = 0;
if (*saved_mid_in_use_p == NULL) {
// No saved state so start at the beginning.
mid = *list_p;
--- 2060,2079 ----
// Caller acquires gListLock as appropriate. If a safepoint has started,
// then we save state via saved_mid_in_use_p and return to the caller to
// honor the safepoint.
//
int ObjectSynchronizer::deflate_monitor_list_using_JT(ObjectMonitor** list_p,
+ int* count_p,
ObjectMonitor** free_head_p,
ObjectMonitor** free_tail_p,
ObjectMonitor** saved_mid_in_use_p) {
assert(AsyncDeflateIdleMonitors, "sanity check");
assert(Thread::current()->is_Java_thread(), "precondition");
+ ObjectMonitor* cur_mid_in_use = NULL;
ObjectMonitor* mid;
ObjectMonitor* next;
int deflated_count = 0;
if (*saved_mid_in_use_p == NULL) {
// No saved state so start at the beginning.
mid = *list_p;
*** 2098,2107 ****
--- 2101,2111 ----
mid->_next_om = NULL;
// At this point mid is disconnected from the in-use list
// and is the current tail in the free_head_p list.
mid = next;
deflated_count++;
+ *count_p = *count_p - 1;
} else {
// mid is considered in-use if it does not have an associated
// Java object or mid is not old or deflation did not succeed.
// A mid->is_new() node can be seen here when it is freshly
// returned by om_alloc() (and skips the deflation code path).
*** 2167,2191 ****
// Note: the thread-local monitors lists get deflated in
// a separate pass. See deflate_thread_local_monitors().
// For moribund threads, scan g_om_in_use_list
int deflated_count = 0;
! if (g_om_in_use_list) {
counters->n_in_circulation += g_om_in_use_count;
! deflated_count = deflate_monitor_list((ObjectMonitor **)&g_om_in_use_list, &free_head_p, &free_tail_p);
! g_om_in_use_count -= deflated_count;
! counters->n_scavenged += deflated_count;
counters->n_in_use += g_om_in_use_count;
}
if (free_head_p != NULL) {
// Move the deflated ObjectMonitors back to the global free list.
! guarantee(free_tail_p != NULL && counters->n_scavenged > 0, "invariant");
! assert(free_tail_p->_next_om == NULL, "invariant");
// constant-time list splice - prepend scavenged segment to g_free_list
free_tail_p->_next_om = g_free_list;
g_free_list = free_head_p;
}
Thread::muxRelease(&gListLock);
timer.stop();
LogStreamHandle(Debug, monitorinflation) lsh_debug;
--- 2171,2196 ----
// Note: the thread-local monitors lists get deflated in
// a separate pass. See deflate_thread_local_monitors().
// For moribund threads, scan g_om_in_use_list
int deflated_count = 0;
! if (g_om_in_use_list != NULL) {
! // Update n_in_circulation before g_om_in_use_count is updated by deflation.
counters->n_in_circulation += g_om_in_use_count;
! deflated_count = deflate_monitor_list((ObjectMonitor**)&g_om_in_use_list, (int*)&g_om_in_use_count, &free_head_p, &free_tail_p);
counters->n_in_use += g_om_in_use_count;
}
if (free_head_p != NULL) {
// Move the deflated ObjectMonitors back to the global free list.
! guarantee(free_tail_p != NULL && deflated_count > 0, "invariant");
! assert(free_tail_p->_next_om == NULL, "must be NULL: _next_om="
! INTPTR_FORMAT, p2i(free_tail_p->_next_om));
// constant-time list splice - prepend scavenged segment to g_free_list
free_tail_p->_next_om = g_free_list;
g_free_list = free_head_p;
+ counters->n_scavenged += deflated_count;
}
Thread::muxRelease(&gListLock);
timer.stop();
LogStreamHandle(Debug, monitorinflation) lsh_debug;
*** 2209,2233 ****
JavaThread* self = JavaThread::current();
deflate_common_idle_monitors_using_JT(true /* is_global */, self);
}
! // Deflate per-thread idle ObjectMonitors using a JavaThread.
//
! void ObjectSynchronizer::deflate_per_thread_idle_monitors_using_JT() {
assert(AsyncDeflateIdleMonitors, "sanity check");
assert(Thread::current()->is_Java_thread(), "precondition");
- JavaThread* self = JavaThread::current();
! self->om_request_deflation = false;
! deflate_common_idle_monitors_using_JT(false /* !is_global */, self);
}
// Deflate global or per-thread idle ObjectMonitors using a JavaThread.
//
! void ObjectSynchronizer::deflate_common_idle_monitors_using_JT(bool is_global, JavaThread* self) {
int deflated_count = 0;
ObjectMonitor* free_head_p = NULL; // Local SLL of scavenged ObjectMonitors
ObjectMonitor* free_tail_p = NULL;
ObjectMonitor* saved_mid_in_use_p = NULL;
elapsedTimer timer;
--- 2214,2239 ----
JavaThread* self = JavaThread::current();
deflate_common_idle_monitors_using_JT(true /* is_global */, self);
}
! // Deflate the specified JavaThread's idle ObjectMonitors using a JavaThread.
//
! void ObjectSynchronizer::deflate_per_thread_idle_monitors_using_JT(JavaThread* target) {
assert(AsyncDeflateIdleMonitors, "sanity check");
assert(Thread::current()->is_Java_thread(), "precondition");
! target->om_request_deflation = false;
! deflate_common_idle_monitors_using_JT(false /* !is_global */, target);
}
// Deflate global or per-thread idle ObjectMonitors using a JavaThread.
//
! void ObjectSynchronizer::deflate_common_idle_monitors_using_JT(bool is_global, JavaThread* target) {
! JavaThread* self = JavaThread::current();
!
int deflated_count = 0;
ObjectMonitor* free_head_p = NULL; // Local SLL of scavenged ObjectMonitors
ObjectMonitor* free_tail_p = NULL;
ObjectMonitor* saved_mid_in_use_p = NULL;
elapsedTimer timer;
*** 2238,2274 ****
if (is_global) {
Thread::muxAcquire(&gListLock, "deflate_global_idle_monitors_using_JT(1)");
OM_PERFDATA_OP(MonExtant, set_value(g_om_in_use_count));
} else {
! OM_PERFDATA_OP(MonExtant, inc(self->om_in_use_count));
}
do {
int local_deflated_count;
if (is_global) {
! local_deflated_count = deflate_monitor_list_using_JT((ObjectMonitor **)&g_om_in_use_list, &free_head_p, &free_tail_p, &saved_mid_in_use_p);
! g_om_in_use_count -= local_deflated_count;
} else {
! local_deflated_count = deflate_monitor_list_using_JT(self->om_in_use_list_addr(), &free_head_p, &free_tail_p, &saved_mid_in_use_p);
! self->om_in_use_count -= local_deflated_count;
}
deflated_count += local_deflated_count;
if (free_head_p != NULL) {
// Move the deflated ObjectMonitors to the global free list.
guarantee(free_tail_p != NULL && local_deflated_count > 0, "free_tail_p=" INTPTR_FORMAT ", local_deflated_count=%d", p2i(free_tail_p), local_deflated_count);
! assert(free_tail_p->_next_om == NULL, "invariant");
if (!is_global) {
Thread::muxAcquire(&gListLock, "deflate_per_thread_idle_monitors_using_JT(2)");
}
// Constant-time list splice - prepend scavenged segment to g_free_list.
free_tail_p->_next_om = g_free_list;
g_free_list = free_head_p;
- g_om_free_count += local_deflated_count;
OM_PERFDATA_OP(Deflations, inc(local_deflated_count));
if (!is_global) {
Thread::muxRelease(&gListLock);
}
}
--- 2244,2278 ----
if (is_global) {
Thread::muxAcquire(&gListLock, "deflate_global_idle_monitors_using_JT(1)");
OM_PERFDATA_OP(MonExtant, set_value(g_om_in_use_count));
} else {
! OM_PERFDATA_OP(MonExtant, inc(target->om_in_use_count));
}
do {
int local_deflated_count;
if (is_global) {
! local_deflated_count = deflate_monitor_list_using_JT((ObjectMonitor**)&g_om_in_use_list, (int*)&g_om_in_use_count, &free_head_p, &free_tail_p, &saved_mid_in_use_p);
} else {
! local_deflated_count = deflate_monitor_list_using_JT(&target->om_in_use_list, &target->om_in_use_count, &free_head_p, &free_tail_p, &saved_mid_in_use_p);
}
deflated_count += local_deflated_count;
if (free_head_p != NULL) {
// Move the deflated ObjectMonitors to the global free list.
guarantee(free_tail_p != NULL && local_deflated_count > 0, "free_tail_p=" INTPTR_FORMAT ", local_deflated_count=%d", p2i(free_tail_p), local_deflated_count);
! assert(free_tail_p->_next_om == NULL, "must be NULL: _next_om="
! INTPTR_FORMAT, p2i(free_tail_p->_next_om));
if (!is_global) {
Thread::muxAcquire(&gListLock, "deflate_per_thread_idle_monitors_using_JT(2)");
}
// Constant-time list splice - prepend scavenged segment to g_free_list.
free_tail_p->_next_om = g_free_list;
g_free_list = free_head_p;
OM_PERFDATA_OP(Deflations, inc(local_deflated_count));
if (!is_global) {
Thread::muxRelease(&gListLock);
}
}
*** 2281,2291 ****
timer.stop();
{
if (is_global) {
log_debug(monitorinflation)("pausing deflation of global idle monitors for a safepoint.");
} else {
! log_debug(monitorinflation)("jt=" INTPTR_FORMAT ": pausing deflation of per-thread idle monitors for a safepoint.", p2i(self));
}
assert(SafepointSynchronize::is_synchronizing(), "sanity check");
ThreadBlockInVM blocker(self);
}
// Prepare for another loop after the safepoint.
--- 2285,2295 ----
timer.stop();
{
if (is_global) {
log_debug(monitorinflation)("pausing deflation of global idle monitors for a safepoint.");
} else {
! log_debug(monitorinflation)("jt=" INTPTR_FORMAT ": pausing deflation of per-thread idle monitors for a safepoint.", p2i(target));
}
assert(SafepointSynchronize::is_synchronizing(), "sanity check");
ThreadBlockInVM blocker(self);
}
// Prepare for another loop after the safepoint.
*** 2314,2324 ****
}
if (ls != NULL) {
if (is_global) {
ls->print_cr("async-deflating global idle monitors, %3.7f secs, %d monitors", timer.seconds(), deflated_count);
} else {
! ls->print_cr("jt=" INTPTR_FORMAT ": async-deflating per-thread idle monitors, %3.7f secs, %d monitors", p2i(self), timer.seconds(), deflated_count);
}
}
}
void ObjectSynchronizer::finish_deflate_idle_monitors(DeflateMonitorCounters* counters) {
--- 2318,2328 ----
}
if (ls != NULL) {
if (is_global) {
ls->print_cr("async-deflating global idle monitors, %3.7f secs, %d monitors", timer.seconds(), deflated_count);
} else {
! ls->print_cr("jt=" INTPTR_FORMAT ": async-deflating per-thread idle monitors, %3.7f secs, %d monitors", p2i(target), timer.seconds(), deflated_count);
}
}
}
void ObjectSynchronizer::finish_deflate_idle_monitors(DeflateMonitorCounters* counters) {
*** 2333,2344 ****
bool needs_special_deflation = is_special_deflation_requested();
if (!AsyncDeflateIdleMonitors || needs_special_deflation) {
// AsyncDeflateIdleMonitors does not use these counters unless
// there is a special deflation request.
- g_om_free_count += counters->n_scavenged;
-
OM_PERFDATA_OP(Deflations, inc(counters->n_scavenged));
OM_PERFDATA_OP(MonExtant, set_value(counters->n_in_circulation));
}
if (log_is_enabled(Debug, monitorinflation)) {
--- 2337,2346 ----
*** 2383,2411 ****
if (log_is_enabled(Info, safepoint, cleanup) ||
log_is_enabled(Info, monitorinflation)) {
timer.start();
}
! int deflated_count = deflate_monitor_list(thread->om_in_use_list_addr(), &free_head_p, &free_tail_p);
!
! Thread::muxAcquire(&gListLock, "deflate_thread_local_monitors");
!
! // Adjust counters
counters->n_in_circulation += thread->om_in_use_count;
! thread->om_in_use_count -= deflated_count;
! counters->n_scavenged += deflated_count;
counters->n_in_use += thread->om_in_use_count;
! counters->per_thread_scavenged += deflated_count;
if (free_head_p != NULL) {
// Move the deflated ObjectMonitors back to the global free list.
guarantee(free_tail_p != NULL && deflated_count > 0, "invariant");
! assert(free_tail_p->_next_om == NULL, "invariant");
// constant-time list splice - prepend scavenged segment to g_free_list
free_tail_p->_next_om = g_free_list;
g_free_list = free_head_p;
}
timer.stop();
// Safepoint logging cares about cumulative per_thread_times and
// we'll capture most of the cost, but not the muxRelease() which
--- 2385,2413 ----
if (log_is_enabled(Info, safepoint, cleanup) ||
log_is_enabled(Info, monitorinflation)) {
timer.start();
}
! // Update n_in_circulation before om_in_use_count is updated by deflation.
counters->n_in_circulation += thread->om_in_use_count;
!
! int deflated_count = deflate_monitor_list(&thread->om_in_use_list, &thread->om_in_use_count, &free_head_p, &free_tail_p);
counters->n_in_use += thread->om_in_use_count;
!
! Thread::muxAcquire(&gListLock, "deflate_thread_local_monitors");
if (free_head_p != NULL) {
// Move the deflated ObjectMonitors back to the global free list.
guarantee(free_tail_p != NULL && deflated_count > 0, "invariant");
! assert(free_tail_p->_next_om == NULL, "must be NULL: _next_om="
! INTPTR_FORMAT, p2i(free_tail_p->_next_om));
// constant-time list splice - prepend scavenged segment to g_free_list
free_tail_p->_next_om = g_free_list;
g_free_list = free_head_p;
+ counters->n_scavenged += deflated_count;
+ counters->per_thread_scavenged += deflated_count;
}
timer.stop();
// Safepoint logging cares about cumulative per_thread_times and
// we'll capture most of the cost, but not the muxRelease() which
< prev index next >