...
ObjectMonitor T-deflate
T-enter +-----------------------+ --------------------------------------------
---------------------- | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
owner contended | contentions=1 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc contentions +-----------------------+ :
if (contentions > 0) prev = cmpxchg(-max_jint, &contentions, 0)
do contended if (prev !== 0 ||&&
enter work owner !== DEFLATER_MARKER) {
} else {
bailout on deflation (nothing to undo cmpxchg(NULL, &owner, DEFLATER_MARKER)
- This diagram starts after "Racing Threads".
- T-enter and T-deflate both observe a contentions field > 0.
- T-enter has won the race and it proceeds with the normal contended enter work.
- T-deflate detects that it has lost the race (prev != 0) and bails out on deflating the ObjectMonitor.In this example, :
- Before bailing out T-deflate
never reaches the - tries to restore the owner field to NULL if it is still DEFLATER_MARKER
check and it has nothing to undo.
T-enter Wins By A-B-A
ObjectMonitor T-deflate
T-enter +-------------------------+ ------------------------------------------
------------------------------------------ | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
owner contended | contentions=1 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc contentions +-------------------------+ 1> :
1> if (contentions > 0) || 2> : <thread_stalls>
EnterI() \/ :
cmpxchg(Self, &owner, DEFLATER_MARKER) +-------------------------+ :
atomic dec contentions | owner=Self/T-enter | :
2> } | contentions=0 | : <thread_resumes>
// finished with enter +-------------------------+ prev = cmpxchg(-max_jint, &contentions, 0)
3> : <does app work> || if (prev !== 0) &&
exit() monitor \/ bailout on deflationowner (nothing to undo)== DEFLATER_MARKER) {
owner = NULL +-------------------------+ } else if owner != {
| owner=Self/T-enter|NULL | cmpxchg(NULL, &owner, DEFLATER_MARKER) {
| owner=Self/T-enter|NULL |contentions=0 | atomic add max_jint to contentions
atomic add max_jint to contentions
+-------------------------+ 3> bailout on deflation
| contentions=0 | 3> bailout on deflation
+-------------------------+ }
- This diagram starts after "Racing Threads".
- T-enter incremented contentions to 1.
- The first ObjectMonitor box is showing the fields at this point and the "1>" markers are showing where each thread is at for that ObjectMonitor box.
- T-deflate stalls after setting the owner field to DEFLATER_MARKER.
- T-enter has won the race and calls EnterI() to do the contended enter work.
- EnterI() observes owner == DEFLATER_MARKER and uses cmpxchg() to set the owner field to Self/T-enter.
- T-enter decrements the contentions field because it is no longer contending for the monitor; it owns the monitor.
- The second ObjectMonitor box is showing the fields at this point and the "2>" markers are showing where each thread is at for that ObjectMonitor box.
- T-deflate resumes, sets the contentions field to -max_jint (not shown), and passes the first part of the bailout expression because "prev == 0".
- T-deflate observes that "owner != DEFLATE_MARKER" and bails out on deflation.:
- Depending on when T-deflate resumes after the stall, it will see "owner == T-enter" or "owner == NULL".
- Both of those values will cause deflation to bailout , but in this case so we have to conditionally undo work:
- restore the owner field to NULL if it is still DEFLATER_MARKER (it's not DEFLATER_MARKER)
- undo setting contentions to -max_jint by atomically adding max_jint to contentions which will restore contentions to its proper value.
- The third ObjectMonitor box is showing the fields at this point and the "3>" markers are showing where each thread is at for that ObjectMonitor box.
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.
- If the T-enter thread has managed to enter and exit the monitor during the T-deflate stall, then our owner field A-B-A transition is:
NULL → DEFLATE_MARKER → Self/T-enter → NULL
so we really have A-B1-B2-A, but the A-B-A principal still holds.
...