< prev index next >
src/hotspot/share/runtime/synchronizer.cpp
Print this page
rev 55489 : Checkpoint latest preliminary review patches for full OpenJDK review; merge with 8222295.patch.
rev 55490 : imported patch dcubed.monitor_deflate_conc.v2.01
rev 55491 : imported patch dcubed.monitor_deflate_conc.v2.02
rev 55492 : imported patch dcubed.monitor_deflate_conc.v2.03
rev 55493 : imported patch dcubed.monitor_deflate_conc.v2.04
rev 55494 : imported patch dcubed.monitor_deflate_conc.v2.05
*** 253,262 ****
--- 253,272 ----
if (owner == NULL && Atomic::replace_if_null(Self, &(m->_owner))) {
assert(m->_recursions == 0, "invariant");
return true;
}
+
+ if (AsyncDeflateIdleMonitors &&
+ Atomic::cmpxchg(Self, &m->_owner, DEFLATER_MARKER) == DEFLATER_MARKER) {
+ // The deflation protocol finished the first part (setting owner),
+ // but it failed the second part (making ref_count negative) and
+ // bailed. Or the ObjectMonitor was async deflated and reused.
+ // Acquired the monitor.
+ assert(m->_recursions == 0, "invariant");
+ return true;
+ }
}
break;
}
// Note that we could inflate in quick_enter.
*** 1019,1028 ****
--- 1029,1045 ----
return monitor_usage > MonitorUsedDeflationThreshold;
}
return false;
}
+ // Returns true if MonitorBound is set (> 0) and if the specified
+ // cnt is > MonitorBound. Otherwise returns false.
+ static bool is_MonitorBound_exceeded(const int cnt) {
+ const int mx = MonitorBound;
+ return mx > 0 && cnt > mx;
+ }
+
bool ObjectSynchronizer::is_async_deflation_needed() {
if (!AsyncDeflateIdleMonitors) {
return false;
}
if (is_async_deflation_requested()) {
*** 1037,1046 ****
--- 1054,1067 ----
// than AsyncDeflationInterval (unless is_async_deflation_requested)
// in order to not swamp the ServiceThread.
_last_async_deflation_time_ns = os::javaTimeNanos();
return true;
}
+ if (is_MonitorBound_exceeded(gMonitorPopulation - gMonitorFreeCount)) {
+ // Not enough ObjectMonitors on the global free list.
+ return true;
+ }
return false;
}
bool ObjectSynchronizer::is_safepoint_deflation_needed() {
if (!AsyncDeflateIdleMonitors) {
*** 1109,1118 ****
--- 1130,1142 ----
// to the objectmonitor.
// Constraining monitor pool growth via MonitorBound ...
//
+ // If MonitorBound is not set (<= 0), MonitorBound checks are disabled.
+ //
+ // When safepoint deflation is being used (!AsyncDeflateIdleMonitors):
// The monitor pool is grow-only. We scavenge at STW safepoint-time, but the
// the rate of scavenging is driven primarily by GC. As such, we can find
// an inordinate number of monitors in circulation.
// To avoid that scenario we can artificially induce a STW safepoint
// if the pool appears to be growing past some reasonable bound.
*** 1122,1133 ****
--- 1146,1175 ----
// we could just loop. In addition, if MonitorBound is set to a low value
// we'll incur more safepoints, which are harmful to performance.
// See also: GuaranteedSafepointInterval
//
// The current implementation uses asynchronous VM operations.
+ //
+ // When safepoint deflation is being used and MonitorBound is set, the
+ // boundry applies to (gMonitorPopulation - gMonitorFreeCount), i.e.,
+ // if there are not enough ObjectMonitors on the global free list, then
+ // a safepoint deflation is induced. Picking a good MonitorBound value
+ // is non-trivial.
+ //
+ // When async deflation is being used:
+ // The monitor pool is still grow-only. Async deflation is requested
+ // by a safepoint's cleanup phase or by the ServiceThread at periodic
+ // intervals when is_async_deflation_needed() returns true. In
+ // addition to other policies that are checked, if there are not
+ // enough ObjectMonitors on the global free list, then
+ // is_async_deflation_needed() will return true. The ServiceThread
+ // calls deflate_global_idle_monitors_using_JT() and also sets the
+ // per-thread omShouldDeflateIdleMonitors flag as needed.
static void InduceScavenge(Thread * Self, const char * Whence) {
+ assert(!AsyncDeflateIdleMonitors, "is not used by async deflation");
+
// Induce STW safepoint to trim monitors
// Ultimately, this results in a call to deflate_idle_monitors() in the near future.
// More precisely, trigger an asynchronous STW safepoint as the number
// of active monitors passes the specified threshold.
// TODO: assert thread state is reasonable
*** 1155,1167 ****
if (jt->omShouldDeflateIdleMonitors && jt->omInUseCount > 0 &&
cause != inflate_cause_vm_internal) {
// Deflate any per-thread idle monitors for this JavaThread if
// this is not an internal inflation; internal inflations can
// occur in places where it is not safe to pause for a safepoint.
! // Clean up your own mess. (Gibbs Rule 45) Otherwise, skip this
// deflation. deflate_global_idle_monitors_using_JT() is called
! // by the ServiceThread.
debug_only(jt->check_for_valid_safepoint_state(false);)
ObjectSynchronizer::deflate_per_thread_idle_monitors_using_JT();
}
}
--- 1197,1210 ----
if (jt->omShouldDeflateIdleMonitors && jt->omInUseCount > 0 &&
cause != inflate_cause_vm_internal) {
// Deflate any per-thread idle monitors for this JavaThread if
// this is not an internal inflation; internal inflations can
// occur in places where it is not safe to pause for a safepoint.
! // 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 omShouldDeflateIdleMonitors.
debug_only(jt->check_for_valid_safepoint_state(false);)
ObjectSynchronizer::deflate_per_thread_idle_monitors_using_JT();
}
}
*** 1201,1214 ****
gMonitorFreeCount--;
ObjectMonitor * take = gFreeList;
gFreeList = take->FreeNext;
guarantee(take->object() == NULL, "invariant");
if (AsyncDeflateIdleMonitors) {
! // Clear any values we allowed to linger during async deflation.
take->_header = NULL;
- take->set_owner(NULL);
-
if (take->ref_count() < 0) {
// Add back max_jint to restore the ref_count field to its
// proper value.
Atomic::add(max_jint, &take->_ref_count);
--- 1244,1259 ----
gMonitorFreeCount--;
ObjectMonitor * take = gFreeList;
gFreeList = take->FreeNext;
guarantee(take->object() == NULL, "invariant");
if (AsyncDeflateIdleMonitors) {
! // We allowed 3 field values to linger during async deflation.
! // We clear header and restore ref_count here, but we leave
! // owner == DEFLATER_MARKER so the simple C2 ObjectMonitor
! // enter optimization can no longer race with async deflation
! // and reuse.
take->_header = NULL;
if (take->ref_count() < 0) {
// Add back max_jint to restore the ref_count field to its
// proper value.
Atomic::add(max_jint, &take->_ref_count);
*** 1222,1233 ****
}
Thread::muxRelease(&gListLock);
Self->omFreeProvision += 1 + (Self->omFreeProvision/2);
if (Self->omFreeProvision > MAXPRIVATE) Self->omFreeProvision = MAXPRIVATE;
! const int mx = MonitorBound;
! if (mx > 0 && (gMonitorPopulation-gMonitorFreeCount) > mx) {
// We can't safely induce a STW safepoint from omAlloc() as our thread
// state may not be appropriate for such activities and callers may hold
// naked oops, so instead we defer the action.
InduceScavenge(Self, "omAlloc");
}
--- 1267,1279 ----
}
Thread::muxRelease(&gListLock);
Self->omFreeProvision += 1 + (Self->omFreeProvision/2);
if (Self->omFreeProvision > MAXPRIVATE) Self->omFreeProvision = MAXPRIVATE;
! if (!AsyncDeflateIdleMonitors &&
! is_MonitorBound_exceeded(gMonitorPopulation - gMonitorFreeCount)) {
! // Not enough ObjectMonitors on the global free list.
// We can't safely induce a STW safepoint from omAlloc() as our thread
// state may not be appropriate for such activities and callers may hold
// naked oops, so instead we defer the action.
InduceScavenge(Self, "omAlloc");
}
*** 1671,1680 ****
--- 1717,1729 ----
object = h_obj(); // Refresh object.
}
// prepare m for installation - set monitor to initial state
m->Recycle();
m->set_header(mark);
+ // If we leave _owner == DEFLATER_MARKER here, then the simple C2
+ // ObjectMonitor enter optimization can no longer race with async
+ // deflation and reuse.
m->set_object(object);
m->_Responsible = NULL;
m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // consider: keep metastats by type/class
omh_p->set_om_ptr(m);
*** 1713,1722 ****
--- 1762,1772 ----
}
// We maintain a list of in-use monitors for each thread.
//
+ // For safepoint based deflation:
// deflate_thread_local_monitors() scans a single thread's in-use list, while
// deflate_idle_monitors() scans only a global list of in-use monitors which
// is populated only as a thread dies (see omFlush()).
//
// These operations are called at all safepoints, immediately after mutators
*** 1731,1740 ****
--- 1781,1795 ----
//
// Perversely, the heap size -- and thus the STW safepoint rate --
// typically drives the scavenge rate. Large heaps can mean infrequent GC,
// which in turn can mean large(r) numbers of ObjectMonitors in circulation.
// This is an unfortunate aspect of this design.
+ //
+ // For async deflation:
+ // If a special deflation request is made, then the safepoint based
+ // deflation mechanism is used. Otherwise, an async deflation request
+ // is registered with the ServiceThread and it is notified.
void ObjectSynchronizer::do_safepoint_work(DeflateMonitorCounters* _counters) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
// The per-thread in-use lists are handled in
*** 1769,1779 ****
guarantee(mark->monitor() == mid, "should match: monitor()=" INTPTR_FORMAT
", mid=" INTPTR_FORMAT, p2i(mark->monitor()), p2i(mid));
const markOop dmw = mid->header();
guarantee(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
! if (mid->is_busy()) {
deflated = false;
} else {
// Deflate the monitor if it is no longer being used
// It's idle - scavenge and return to the global free list
// plain old deflation ...
--- 1824,1836 ----
guarantee(mark->monitor() == mid, "should match: monitor()=" INTPTR_FORMAT
", mid=" INTPTR_FORMAT, p2i(mark->monitor()), p2i(mid));
const markOop dmw = mid->header();
guarantee(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
! if (mid->is_busy() || mid->ref_count() != 0) {
! // Easy checks are first - the ObjectMonitor is busy or ObjectMonitor*
! // is in use so no deflation.
deflated = false;
} else {
// Deflate the monitor if it is no longer being used
// It's idle - scavenge and return to the global free list
// plain old deflation ...
*** 1785,1794 ****
--- 1842,1857 ----
p2i(mark), obj->klass()->external_name());
}
// Restore the header back to obj
obj->release_set_mark(dmw);
+ if (AsyncDeflateIdleMonitors) {
+ // clear() expects the owner field to be NULL and we won't race
+ // with the simple C2 ObjectMonitor enter optimization since
+ // we're at a safepoint.
+ mid->set_owner(NULL);
+ }
mid->clear();
assert(mid->object() == NULL, "invariant: object=" INTPTR_FORMAT,
p2i(mid->object()));
assert(mid->is_free(), "invariant");
*** 1855,1865 ****
if (Atomic::cmpxchg(-max_jint, &mid->_ref_count, (jint)0) == 0) {
// Make ref_count negative to force any contending threads or
// ObjectMonitor* using threads to retry. This is the second
// part of the async deflation dance.
! if (mid->_owner == DEFLATER_MARKER) {
// If owner is still DEFLATER_MARKER, then we have successfully
// signaled any contending threads to retry. If it is not, then we
// have lost the race to an entering thread and the ObjectMonitor
// is now busy. This is the third and final part of the async
// deflation dance.
--- 1918,1928 ----
if (Atomic::cmpxchg(-max_jint, &mid->_ref_count, (jint)0) == 0) {
// Make ref_count negative to force any contending threads or
// ObjectMonitor* using threads to retry. This is the second
// part of the async deflation dance.
! if (mid->owner_is_DEFLATER_MARKER()) {
// If owner is still DEFLATER_MARKER, then we have successfully
// signaled any contending threads to retry. If it is not, then we
// have lost the race to an entering thread and the ObjectMonitor
// is now busy. This is the third and final part of the async
// deflation dance.
*** 2518,2529 ****
// Check a free monitor entry; log any errors.
void ObjectSynchronizer::chk_free_entry(JavaThread * jt, ObjectMonitor * n,
outputStream * out, int *error_cnt_p) {
stringStream ss;
! if ((!AsyncDeflateIdleMonitors && n->is_busy()) ||
! (AsyncDeflateIdleMonitors && n->is_busy_async())) {
if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
": free per-thread monitor must not be busy: %s", p2i(jt),
p2i(n), n->is_busy_to_string(&ss));
} else {
--- 2581,2591 ----
// Check a free monitor entry; log any errors.
void ObjectSynchronizer::chk_free_entry(JavaThread * jt, ObjectMonitor * n,
outputStream * out, int *error_cnt_p) {
stringStream ss;
! if (n->is_busy()) {
if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
": free per-thread monitor must not be busy: %s", p2i(jt),
p2i(n), n->is_busy_to_string(&ss));
} else {
< prev index next >