Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Add explanatory bullets after diagrams in "An Example of Object Header Interference" section.

...

    T-enter                                    object           T-deflate
    -----------------------------------------  +-------------+  -----------------------------------------
    dmw = header()                             | mark=om_ptr |  dmw = header()
    if (!dmw->is_marked() &&                   +-------------+  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)
    }                                                           }
    • 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-deflate Wins First Race

    T-enter                                    object            T-deflate
    -----------------------------------------  +-------------+   -----------------------------------------
    dmw = header()                             | mark=om_ptr |   dmw = header()
    if (!dmw->is_marked() &&                   +-------------+   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 (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)
    • The return value from cmpxchg() in each thread will be different.
    • Since T-deflate won the race, its 'dmw' variable contains the header/dmw from the ObjectMonitor.
    • Since T-enter lost the race, its 'dmw' variable contains the 'marked_dmw' set by T-deflate.
      • T-enter will unmark its 'dmw' variable
    • Both threads are poised to call cas_set_mark() at the same time.

T-enter T-enter Wins First Race

    T-enter                                    object            T-deflate
    -----------------------------------------  +-------------+   -----------------------------------------
    dmw = header()                             | mark=om_ptr |   dmw = header()
    if (!dmw->is_marked() &&                   +-------------+   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 == original dmw here                                  // dmw == marked_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)

Either Wins the Second Race

    • 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

    T-enter                                    object            T-deflate
    -----------------------------------------  +-------------+   -----------------------------------------
    dmw = header()                             | mark=dmw    |   dmw = header()
    if (!dmw->is_marked() &&                   +-------------+   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 == original dmw here                                  ...                                   // dmw == marked_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)
    • It does not matter whether T-enter or T-deflate won the cmpxchg() call so the comment does not say who won.
    • It does not matter whether T-enter or T-deflate won the cas_set_mark() call; in this scenario both were trying to restore the same value.
    • The object's mark field has changed from 'om_ptr' → 'dmw'.

Please notice that install_displaced_markword_in_object() does not do any retries on any code path. :

    • Instead the code adapts to being the loser in a cmpxchg() by unmarking its copy of the dmw.
    • In the second race, if a thread loses the cas_set_mark() race, there is

...

    • also no need to retry because the object's header has been restored by the other thread.

Hash Codes and Object Header Interference

...