Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Change T-deflate diagrams in "T-enter Wins" and "T-enter Wins By A-B-A" subsections to show the same code from "T-deflate Wins" as an untaken branch; this matches the style of later diagrams.

...

                            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.

...