...
- Setting a NULL owner field to DEFLATER_MARKER with cmpxchg() forces any contending thread through the slow path. A racing thread would be trying to set the owner field.
- Making a zero contentions field a large negative value with cmpxchg() forces racing threads to retry. A racing thread would have set the owner field (after we stored DEFLATER_MARKER) and would be trying to increment the contentions field.
- If the owner field is still equal to DEFLATER_MARKER, then we have won all the races and can deflate the monitor.
...
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.
...
ObjectMonitor T-deflate
T-enter +-------------------------+ ------------------------------------------
------------------------------------------ | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
owner contended | contentions=1 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc contentions +-------------------------+ 2>1> : <thread_stalls>
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 deflation (nothing to undo)
owner = NULL +-------------------------+ else if owner != DEFLATER_MARKER) {
| owner=Self/T-enter|NULL | atomic add max_jint to contentions
| contentions=0 | 3> bailout on deflation
+-------------------------+ }
- This diagram starts after "Racing Threads".
- T-enter observes a contentions field > 0incremented 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 we have to 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 pointand 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.
...