Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Editorial pass on An Example of "Object Header Interference" section; primarily add "install_displaced_markword_in_object() {" to the diagrams.

...

ObjectMonitor::install_displaced_markword_in_object() is called from two places so we can have a race between a T-enter thread and a T-deflate thread:

Start of the Race

    T-enter                                   enter                                      object           T-deflate
    -------------------------------------------  +-------------+  --------------------------------------------
    dmw = header()                             install_displaced_markword_in_object() { | mark=om_ptr |  install_displaced_markword_in_object() {
    dmw = header()
    if (!dmw->is_marked() &&                                      +-------------+  dmw = header()
    if (!dmw->is_marked() &&
                                            if (!dmw->is_marked() &&
      dmw->hash() == 0) {                                                                                  dmw->hash() == 0) {
      create marked_dmw                                          dmw                    create marked_dmw
         dmw = cmpxchg(marked_dmw, &header, dmw)                                          dmw = cmpxchg(marked_dmw, &header, dmw)
    }                                                           } }
    • The data field (mark) is at its starting value.
    • 'dmw' and 'marked_dmw' are local copies in each thread.
    • T-enter and T-deflate are both calling install_displaced_markword_in_object() at the same time.
    • Both threads are poised to call cmpxchg() at the same time.

...

    T-enter                                      object            T-deflate
    -------------------------------------------  +-------------+   -------------------------------------------
    dmw = header()                            install_displaced_markword_in_object() {   | mark=om_ptr |  install_displaced_markword_in_object() {
     dmw = header()
    if (!dmw->is_marked() &&                                   +-------------+    dmw = header()
if (!dmw->is_marked() &&
        dmw->hash() == 0) {                                          dmw->hash() == 0) {
      create marked_dmw                                            create marked_dmw
      dmw = cmpxchg(marked_dmw, &header, dmw)                      dmw = cmpxchg(marked_dmw, &header, dmw)
    }                                                            }
    // dmw == marked_dmw here                                    // dmw == original dmw here
    if ( if (!dmw->is_marked())                                        if (dmw->is_marked())
      unmark dmw                                                   unmark dmw
    obj = object()                                               obj = object()
    &&
         dmw->hash() == 0) {                                           dmw->hash() == 0) {
       create marked_dmw                                             create marked_dmw
       dmw = cmpxchg(marked_dmw, &header, dmw)                       dmw = cmpxchg(marked_dmw, &header, dmw)
     }                                                             }
     // dmw == marked_dmw here                                     // dmw == original dmw here
     if (dmw->is_marked())                                         if (dmw->is_marked())
      unmark dmw                                                    unmark dmw
    obj = object()                                                obj = object()
    obj->cas_set_mark(dmw, this)                                                                  obj->cas_set_mark(dmw, this)

...

    T-enter                                      object            T-deflate
    -------------------------------------------  +-------------+   -------------------------------------------
    install_displaced_markword_in_object() {    | mark=om_ptr |  install_displaced_markword_in_object() {
    dmw = header()                    +-------------------
    dmw = header()                            
| mark=om_ptr |   dmw = header()
    if (!dmw->is_marked() &&                   +-------------+   if (!dmw->is_marked() &&
                dmw->hash() == 0) {                                                                                    dmw->hash() == 0) {
            create marked_dmw                                           dmw                                             create marked_dmw
            dmw = cmpxchg(marked_dmw, &header, dmw)                                            dmw = cmpxchg(marked_dmw, &header, dmw)
    }                                                            }                                                             }
    // dmw == original dmw here                                here                                     // dmw == marked_dmw here
    if (dmw->is_marked())                                                                                if (dmw->is_marked())
            unmark dmw                                                dmw                                                      unmark dmw
    obj = object()                                                                                              obj = object()
    obj->cas_set_mark(dmw, this)                                                                  obj->cas_set_mark(dmw, this)
    • This diagram is the same as "T-deflate Wins First Race" except we've swapped the post cmpxchg() comments.
    • Since T-enter won the race, its 'dmw' variable contains the header/dmw from the ObjectMonitor.
    • Since T-deflate lost the race, its 'dmw' variable contains the 'marked_dmw' set by T-enter.
      • T-deflate will unmark its 'dmw' variable.
    • Both threads are poised to call cas_set_mark() at the same time.

Either Wins the Second Race

    • at the same time.

Either Wins the Second Race

    T-enter                                      object            T-deflate
    -------------------------------------------  +-------------+   -------    T-enter                                    object            T-deflate
    ----------------------------------------- 
    install_displaced_markword_in_object() {   | mark=dmw    |  install_displaced_markword_in_object() {
     dmw = header()                   +-------------+   -----------------------------------------
     dmw = header()                            
| mark=dmw    |   dmw = header()
    if (!dmw->is_marked() &&                   +-------------+  marked() && if (!dmw->is_marked() &&
                dmw->hash() == 0) {                                                                                    dmw->hash() == 0) {
            create marked_dmw                                           dmw                                             create marked_dmw
            dmw = cmpxchg(marked_dmw, &header, dmw)                                            dmw = cmpxchg(marked_dmw, &header, dmw)
        }                                                                                                                        }
        // dmw == ...                                                                     // dmw == ...
    if (dmw->is_marked())                                                                                if (dmw->is_marked())
            unmark dmw                                               dmw                                                        unmark dmw
        obj = object()                                                                                              obj = object()
        obj->cas_set_mark(dmw, this)                                                                  obj->cas_set_mark(dmw, this)

...

    T-hash                     ObjectMonitor              T-deflate
    ------------------------  +-----------------------+  --------------------------------------------
    save_om_ptr() {           | header=dmw_no_hash | deflate_monitor_using_JT() {
      atomic inc ref_count    | owner=DEFLATER_MARKER |   cmpxchg(DEFLATER_MARKER, &owner, NULL)
   if (owner ==            | contentions=0      | if (waiters != 0 || ref_count != 0) {
          DEFLATER_MARKER && | ref_count=1 |   }
         contentions <= 0) {  +-----------------------+ 1> prev = cmpxchg(-max_jint, &contentions, 0)
      }                 ||             2> if (prev == 0 &&
   1> if (object no longer \/   owner == DEFLATER_MARKER &&
          has a monitor or +-----------------------+ ref_count == 0) {
          is a different | header=dmw_no_hash | } else {
        monitor) { | owner=DEFLATER_MARKER | cmpxchg(NULL, &owner, DEFLATER_MARKER)
        atomic dec ref_count | contentions=-max_jint | atomic add max_jint to contentions
        return false to | ref_count=1 | 3> bailout on deflation
      cause a retry +-----------------------+ }
      } ||
   2> save om_ptr in the \/
    ObjectMonitorHandle +-----------------------+
} | header=dmw_hash |
if save_om_ptr() { | owner=NULL |
if no hash | contentions=0 |
gen hash & merge | ref_count=1 |
hash = hash(header) +-----------------------+
}
3> atomic dec ref_count
return hash

...