- Loading...
...
ObjectMonitor::install_displaced_markword_in_object() is the new piece of code that handles all the racy situations with restoring an object's header asynchronously. The function is called from a couple of places (deflation and object monitor entry) and can also race with installation of a hash for the object. The restoration protocol for the object's header uses the mark bit along with the hash() value staying at zero to indicate that the object's header
is being restored. Only one of the three possible racing scenarios can win and the losing scenarios all adapt to the winning scenario's object header value.
...
Various code paths have been updated to recognize an owner field equal to DEFLATER_MARKER or a negative count contentions field and those code paths will retry their operation. This is the shortest "Key Part" description, but don't be fooled. See "Gory Details" below.
...
For example, when ObjectMonitor::enter() detects genuine contention via the owner field, it atomically increments the count contentions field to indicate that the ObjectMonitor is busy. The thread calling enter() (T-enter) is potentially racing with an Async Monitor Deflation by another JavaThread (T-deflate) so both threads have to check the result of the race.
...
ObjectMonitor T-deflate
T-enter +-----------------------+ ----------------------------------------
---------------- | owner=NULL | cmpxchg(DEFLATER_MARKER, &owner, NULL) deflate_monitor_using_JT() {
| countcontentions=0 0 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
+-----------------------+
...
ObjectMonitor T-deflate
T-enter +-----------------------+ --------------------------------------------
---------------- ------ | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
owner contended | contentions=0 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
owneratomic contended | count=0 | :
atomic inc count inc contentions +-----------------------+ :
prev = cmpxchg(-max_jint, &countcontentions, 0)
ObjectMonitor T-deflate
T-enter enter +-----------------------+ --------------------------------------------
---------------------- | owner------- | owner=DEFLATER_MARKER | cmpxchg(DEFLATER_MARKER, &owner, NULL)deflate_monitor_using_JT() {
owner contended contended | countcontentions=-max_jint jint | : cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc contentions count +-----------------------+ :
if (contentions <= 0 && owner prev = cmpxchg(-max_jint, &countcontentions, 0)
if (count <= 0 && owner == DEFLATER_MARKER) { if (prev == 0 &&
== DEFLATER_MARKER) { restore header owner == DEFLATER_MARKER) {
restore header retry enter restore object header
retry enter } finish the deflation
} }
ObjectMonitor T-deflate
T-enter +-----------------------+ --------------------------------------------
---------------------- | owner=DEFLATER_MARKER | cmpxchg(DEFLATER_MARKER, &owner, NULL)deflate_monitor_using_JT() {
owner contended contended | countcontentions=1 1 | : cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc count contentions +-----------------------+ :
if (contentions > 0) prev = cmpxchg(-max_jint, &countcontentions, 0)
if (count > 0) do contended if (prev != 0 ||
do contended enter work owner != DEFLATER_MARKER)
enter work bailout on deflation (nothing to undo)
...
ObjectMonitor T-deflate
T-enter +-------------------------+ ------------------------------------------
------------------------------------------ | owner=DEFLATER_MARKER | cmpxchg(DEFLATER_MARKER, &owner, NULL)deflate_monitor_using_JT() {
owner contended | count=1 contentions=1 | | : <thread_stalls> cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc count contentions +-------------------------+ 2> : <thread_stalls>
if (countcontentions > 0) || :
EnterI() \/ :
cmpxchg(Self, &owner, DEFLATER_MARKER) +-------------------------+ :
atomic dec countcontentions | owner=Self/T-enter | : <thread_resumes>
2> } | countcontentions=0 | | prev = cmpxchg(-max_jint, &count, 0): <thread_resumes>
// finished with enter +-------------------------+ if (prev !== cmpxchg(-max_jint, &contentions, 0)
3> : <does app work> || bailoutif on deflation (nothingprev to!= undo0)
exit() monitor \/ \/ bailout elseon ifdeflation owner(nothing != DEFLATER_MARKER) {to undo)
owner = NULL +-------------------------+ else if atomicowner add!= maxDEFLATER_jint to countMARKER) {
| owner=Self/T-enter|NULL | bailout on deflation atomic add max_jint to contentions
| countcontentions=0 | 3> bailout on | }deflation
+-------------------------+ }
If the T-enter thread has managed to enter but not exit the monitor during the T-deflate stall, then our owner field A-B-A transition is:
NULL → DEFLATE_MARKER → Self/T-enter
so we really have A1-B-A2, but the A-B-A principal still holds.
...