- Loading...
...
Once we know it is safe to deflate the monitor (which is mostly field resetting and monitor list management), we have to restore
the object's header. That's another racy operation that is described below in "Restoring the Header With Interference Detection".
...
ObjectMonitor T-deflate
T-enter +-----------------------+ --------------------------------------------
----------------------------- | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
owner contended | contentions=-max_jint | cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc contentions +-----------------------+ :
if (contentions <= 0 && owner prev = cmpxchg(-max_jint, &contentions, 0)
== DEFLATER_MARKER) { if (prev == 0 &&
restore obj header owner == DEFLATER_MARKER) {
retry enter restore objectobj header
} finish the deflation
}
...
T-hash ObjectMonitor T-deflate
------------------------ +-----------------------+ --------------------------------------------
save_om_ptr() { | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
atomic inc ref_count | contentions=-max_jint | cmpxchg(DEFLATER_MARKER, &owner, NULL)
1> if (owner == | ref_count=1 | if (waiters != 0 || ref_count != 0) {
DEFLATER_MARKER && +-----------------------+ }
contentions <= 0) { || prev = cmpxchg(-max_jint, &contentions, 0)
atomic dec ref_count restore obj header \/ 1> if (prev == 0 &&
2> return false toatomic dec ref_count +-----------------------+ owner == DEFLATER_MARKER &&
2> return cause a retry false to | owner=DEFLATER_MARKER | ref_count == 0) {
} cause a retry | contentions=-max_jint | restore obj header
} | ref_count=0 | 2> finish the deflation
+-----------------------+ }
...
T-hash ObjectMonitor T-deflate
------------------------ +-----------------------+ --------------------------------------------
save_om_ptr() { | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
atomic inc ref_count | contentions=-max_jint | cmpxchg(DEFLATER_MARKER, &owner, NULL)
1> if (owner == | ref_count=1 | if (waiters != 0 || ref_count != 0) {
DEFLATER_MARKER && +-----------------------+ }
contentions <= 0) { || prev = cmpxchg(-max_jint, &contentions, 0)
atomicrestore obj header dec ref_count \/ 1> if (prev == 0 &&
2> return false toatomic dec ref_count +-----------------------+ owner == DEFLATER_MARKER &&
2> return false to cause a retry | owner=NULL | ref_count == 0) {
} cause a retry | contentions=0 | } else {
} | ref_count=0 | cmpxchg(NULL, &owner, DEFLATER_MARKER)
+-----------------------+ atomic add max_jint to contentions
2> bailout on deflation
}
Note: The addition of "restore obj header" to save_om_ptr() created a bug where the ObjectMonitor can be disconnected from the object without the ObjectMonitor being deflated. This leads to a situation where the ObjectMonitor is still on the in-use list and thinks it is owned by the object, but the object does not agree. This bug exists in the "CR1/v2.01/4-for-jdk13" version of the code that is currently out for review. The bug occurs rarely in extensive testing. I have a fix and I'm in the process of testing it.
Please note that in Carsten's original prototype, there was another race in ObjectSynchronizer::FastHashCode() when the object's monitor had to be inflated. The setting of the hashcode in the ObjectMonitor's header/dmw could race with T-deflate. That race is resolved in this version by the use of an ObjectMonitorHandle in the call to ObjectSynchronizer::inflate(). The ObjectMonitor* returned by ObjectMonitorHandle.om_ptr() has a non-zero ref_count so no additional races with T-deflate are possible.
...