- Loading...
...
*** THIS SUBSECTION NEEDS SUBSTANTIAL REWORK WITH v2.11 ***
ObjectMonitor::save_om_ptrenter() is used to safely save an ObjectMonitor* in an ObjectMonitorHandlecan change an idle monitor into a busy monitor. ObjectSynchronizer::deflate_monitor_using_JT() is used to asynchronously deflate an idle monitor. save_om_ptrenter() and deflate_monitor_using_JT() can interfere with each other. The thread calling save_om_ptrenter() (T-saveenter) is potentially racing with another JavaThread (T-deflate) so both threads have to check the results of the races.
T-save enter ObjectMonitor T-deflate
------------------------ +-----------------------+ ----------------------------------------
save_om_ptrenter() { | owner=NULL | deflate_monitor_using_JT() {
1> atomic inc ref_countcontentions | ref_countcontentions=0 | 1> cmpxchg(DEFLATER_MARKER, &owner, NULL)
+-----------------------+
T-save enter ObjectMonitor T-deflate
------------------------ +-----------------------+ --------------------------------------------
save_om_ptrenter() { | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
1> atomic inc ref_countcontentions | ref_countcontentions=0 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
+-----------------------+ :
1> prev = cmpxchg(-max_jint, &ref_countcontentions, 0)
T-save enter ObjectMonitor ObjectMonitor T-deflate
--------------------------------- +-------------------------+ --------------------------------------------
save_om_ptrenter() { | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
atomic inc ref_countcontentions | ref_countcontentions=-max_jint+1 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
1> if (owner == DEFLATER_MARKER && +-------------------------+ :
ref_countcontentions <= 0) { || prev = cmpxchg(-max_jint, &ref_countcontentions, 0)
restore obj header \/ 1> if (prev == 0 &&
atomic dec ref_count contentions +-------------------------+ owner == DEFLATER_MARKER) {
2> return false to force retry | owner=DEFLATER_MARKER | restore obj header
} | ref_countcontentions=-max_jint | 2> finish the deflation
+-------------------------+ }
...
T-save enter ObjectMonitor T-deflate
--------------------------------- +-------------------------+ --------------------------------------------
save_om_ptrenter() { | owner=DEFLATER_MARKER. | deflate_monitor_using_JT() {
atomic inc ref_count contentions | ref_countcontentions=1 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
1> if (owner == DEFLATER_MARKER && +-------------------------+ :
ref_countcontentions <= 0) { || prev = cmpxchg(-max_jint, &ref_countcontentions, 0)
} else { } \/ 1> if (prev == 0 &&
2> <continue savecontended om_ptrenter> in the +-------------------------+ owner == DEFLATER_MARKER) {
ObjectMonitorHandle | owner=NULL | } else {
| } else {
2> return true | ref_countcontentions=1 | cmpxchg(NULL, &owner, DEFLATER_MARKER)
+-------------------------+ 2> return
...
T-enter ObjectMonitor T-deflate
-------------------------------------------- +-------------------------+ --------------------------------------------
ObjectMonitor::enter() { | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
<ownerincrement iscontentions contended> | ref_countcontentions=1 | cmpxchg(DEFLATER_MARKER, &owner, NULL)
1> EnterI() { +-------------------------+ 1> :
if (owner == DEFLATER_MARKER && || 2> : <thread_stalls>
cmpxchg(Self, &owner, \/ :
DEFLATER_MARKER) +-------------------------+ :
== DEFLATER_MARKER) { | owner=Self/T-enter | :
// EnterI is done | ref_countcontentions=0 | : <thread_resumes>
return +-------------------------+ prev = cmpxchg(-max_jint, &ref_countcontentions, 0)
} || if (prev == 0 &&
} // enter() is donedecrement contentions \/ 3> owner == DEFLATER_MARKER) {
} // ~OMH: atomic dec ref_countenter() is done +-------------------------+ } else {
2> : <does app work> | owner=Self/T-enter|NULL | cmpxchg(NULL, &owner, DEFLATER_MARKER)
3> : | ref_countcontentions=-max_jint | atomic add max_jint to ref_countcontentions
exit() monitor +-------------------------+ 4> bailout on deflation
4> owner = NULL || }
\/
+-------------------------+
| owner=Self/T-enter|NULL |
| ref_countcontentions=0 |
+-------------------------+
NULL → DEFLATER_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 → DEFLATER_MARKER → Self/T-enter → NULL
so we really have A-B1-B2-A, but the A-B-A principal still holds.
T-enter finished doing app work and is about to exit the monitor (or it has already exited the monitor).
The fourth ObjectMonitor box is showing the fields at this point and the "4>" markers are showing where each thread is at for that ObjectMonitor box.
...