Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Clarify when bailing out on deflation has to undo work.

...

                      ObjectMonitor              T-deflate
    T-enter           +-----------------------+  ----------------------------------------
    ----------------  | owner=DEFLATER_MARKER |  cmpxchg(DEFLATER_MARKER, &owner, NULL)
    owner contended   | count=1               |  :
    atomic inc count  +-----------------------+  prev = cmpxchg(-max_jint, &count, 0)
    if (count > 0)                               if (prev != 0 ||
      do contended                                   owner != DEFLATER_MARKER)
      enter work                                 bailout on deflation (nothing to undo)
    • This diagram starts after "Racing Threads".
    • T-enter and T-deflate both observe a count 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 and bails out on deflating the ObjectMonitor.
    • In this example, T-deflate never reaches the DEFLATER_MARKER check and it has nothing to undo.

T-enter Wins By A-B-A

                                                ObjectMonitor                T-deflate
    T-enter           +-------------------------+  ----------------------------------------
    ------------------------------------------ | owner=DEFLATER_MARKER |  cmpxchg(DEFLATER_MARKER, &owner, NULL)
    owner contended   | count=1                |  : <thread_stalls>
    atomic inc count  +-------------------------+  :
    if (count > 0)                               || :
      EnterI()                               \/ :
      cmpxchg(Self, &owner, DEFLATER_MARKER)  +-------------------------+ :
atomic dec count | owner=Self/T-enter | : <thread_resumes>
} | count=0 | prev = cmpxchg(-max_jint, &count, 0)
// finished with enter +-------------------------+ if (prev != 0 ||)
: <does app work> || bailout on owner != DEFLATER_MARKERdeflation (nothing to undo)
exit() monitor \/ else if bailout on deflationowner != DEFLATER_MARKER) {
owner = NULL +-------------------------+ atomic add max_jint to count
| owner=Self/T-enter|NULL | bailout on deflation
| count=-max_jint0 | }
+-------------------------+
    • This diagram starts after "Racing Threads".
    • T-enter observes a count field > 0.
    • 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 count 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.
    • T-deflate resumes, sets the count field to -max_jint, 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 count to -max_jint by atomically adding max_jint to count which will restore count to its proper value.
    • The third ObjectMonitor box is showing the fields at this point.
    • 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.

...