annotate src/share/vm/runtime/objectMonitor.cpp @ 3979:4dfb2df418f2

6484982: G1: process references during evacuation pauses Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate. Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp
author johnc
date Thu, 22 Sep 2011 10:57:37 -0700
parents 1d1603768966
children f08d439fab8c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1 /*
2426
1d1603768966 7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents: 2177
diff changeset
2 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
4 *
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
7 * published by the Free Software Foundation.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
8 *
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
13 * accompanied this code).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
14 *
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
18 *
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
21 * questions.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
22 *
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
23 */
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
26 #include "classfile/vmSymbols.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
27 #include "memory/resourceArea.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
28 #include "oops/markOop.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
29 #include "oops/oop.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
30 #include "runtime/handles.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
31 #include "runtime/interfaceSupport.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
32 #include "runtime/mutexLocker.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
33 #include "runtime/objectMonitor.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
34 #include "runtime/objectMonitor.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
35 #include "runtime/osThread.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
36 #include "runtime/stubRoutines.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
37 #include "runtime/thread.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
38 #include "services/threadService.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
39 #include "utilities/dtrace.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
40 #include "utilities/preserveException.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
41 #ifdef TARGET_OS_FAMILY_linux
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
42 # include "os_linux.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
43 # include "thread_linux.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
44 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
45 #ifdef TARGET_OS_FAMILY_solaris
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
46 # include "os_solaris.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
47 # include "thread_solaris.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
48 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
49 #ifdef TARGET_OS_FAMILY_windows
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
50 # include "os_windows.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
51 # include "thread_windows.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
52 #endif
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
53
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
54 #if defined(__GNUC__) && !defined(IA64)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
55 // Need to inhibit inlining for older versions of GCC to avoid build-time failures
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
56 #define ATTR __attribute__((noinline))
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
57 #else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
58 #define ATTR
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
59 #endif
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
60
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
61
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
62 #ifdef DTRACE_ENABLED
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
63
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
64 // Only bother with this argument setup if dtrace is available
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
65 // TODO-FIXME: probes should not fire when caller is _blocked. assert() accordingly.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
66
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
67 HS_DTRACE_PROBE_DECL4(hotspot, monitor__notify,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
68 jlong, uintptr_t, char*, int);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
69 HS_DTRACE_PROBE_DECL4(hotspot, monitor__notifyAll,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
70 jlong, uintptr_t, char*, int);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
71 HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__enter,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
72 jlong, uintptr_t, char*, int);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
73 HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__entered,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
74 jlong, uintptr_t, char*, int);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
75 HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__exit,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
76 jlong, uintptr_t, char*, int);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
77
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
78 #define DTRACE_MONITOR_PROBE_COMMON(klassOop, thread) \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
79 char* bytes = NULL; \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
80 int len = 0; \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
81 jlong jtid = SharedRuntime::get_java_tid(thread); \
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
82 Symbol* klassname = ((oop)(klassOop))->klass()->klass_part()->name(); \
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
83 if (klassname != NULL) { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
84 bytes = (char*)klassname->bytes(); \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
85 len = klassname->utf8_length(); \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
86 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
87
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
88 #define DTRACE_MONITOR_WAIT_PROBE(monitor, klassOop, thread, millis) \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
89 { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
90 if (DTraceMonitorProbes) { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
91 DTRACE_MONITOR_PROBE_COMMON(klassOop, thread); \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
92 HS_DTRACE_PROBE5(hotspot, monitor__wait, jtid, \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
93 (monitor), bytes, len, (millis)); \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
94 } \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
95 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
96
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
97 #define DTRACE_MONITOR_PROBE(probe, monitor, klassOop, thread) \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
98 { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
99 if (DTraceMonitorProbes) { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
100 DTRACE_MONITOR_PROBE_COMMON(klassOop, thread); \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
101 HS_DTRACE_PROBE4(hotspot, monitor__##probe, jtid, \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
102 (uintptr_t)(monitor), bytes, len); \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
103 } \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
104 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
105
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
106 #else // ndef DTRACE_ENABLED
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
107
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
108 #define DTRACE_MONITOR_WAIT_PROBE(klassOop, thread, millis, mon) {;}
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
109 #define DTRACE_MONITOR_PROBE(probe, klassOop, thread, mon) {;}
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
110
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
111 #endif // ndef DTRACE_ENABLED
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
112
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
113 // Tunables ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
114 // The knob* variables are effectively final. Once set they should
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
115 // never be modified hence. Consider using __read_mostly with GCC.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
116
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
117 int ObjectMonitor::Knob_Verbose = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
118 int ObjectMonitor::Knob_SpinLimit = 5000 ; // derived by an external tool -
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
119 static int Knob_LogSpins = 0 ; // enable jvmstat tally for spins
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
120 static int Knob_HandOff = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
121 static int Knob_ReportSettings = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
122
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
123 static int Knob_SpinBase = 0 ; // Floor AKA SpinMin
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
124 static int Knob_SpinBackOff = 0 ; // spin-loop backoff
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
125 static int Knob_CASPenalty = -1 ; // Penalty for failed CAS
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
126 static int Knob_OXPenalty = -1 ; // Penalty for observed _owner change
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
127 static int Knob_SpinSetSucc = 1 ; // spinners set the _succ field
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
128 static int Knob_SpinEarly = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
129 static int Knob_SuccEnabled = 1 ; // futile wake throttling
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
130 static int Knob_SuccRestrict = 0 ; // Limit successors + spinners to at-most-one
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
131 static int Knob_MaxSpinners = -1 ; // Should be a function of # CPUs
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
132 static int Knob_Bonus = 100 ; // spin success bonus
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
133 static int Knob_BonusB = 100 ; // spin success bonus
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
134 static int Knob_Penalty = 200 ; // spin failure penalty
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
135 static int Knob_Poverty = 1000 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
136 static int Knob_SpinAfterFutile = 1 ; // Spin after returning from park()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
137 static int Knob_FixedSpin = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
138 static int Knob_OState = 3 ; // Spinner checks thread state of _owner
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
139 static int Knob_UsePause = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
140 static int Knob_ExitPolicy = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
141 static int Knob_PreSpin = 10 ; // 20-100 likely better
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
142 static int Knob_ResetEvent = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
143 static int BackOffMask = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
144
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
145 static int Knob_FastHSSEC = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
146 static int Knob_MoveNotifyee = 2 ; // notify() - disposition of notifyee
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
147 static int Knob_QMode = 0 ; // EntryList-cxq policy - queue discipline
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
148 static volatile int InitDone = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
149
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
150 #define TrySpin TrySpin_VaryDuration
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
151
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
152 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
153 // Theory of operations -- Monitors lists, thread residency, etc:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
154 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
155 // * A thread acquires ownership of a monitor by successfully
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
156 // CAS()ing the _owner field from null to non-null.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
157 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
158 // * Invariant: A thread appears on at most one monitor list --
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
159 // cxq, EntryList or WaitSet -- at any one time.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
160 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
161 // * Contending threads "push" themselves onto the cxq with CAS
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
162 // and then spin/park.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
163 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
164 // * After a contending thread eventually acquires the lock it must
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
165 // dequeue itself from either the EntryList or the cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
166 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
167 // * The exiting thread identifies and unparks an "heir presumptive"
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
168 // tentative successor thread on the EntryList. Critically, the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
169 // exiting thread doesn't unlink the successor thread from the EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
170 // After having been unparked, the wakee will recontend for ownership of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
171 // the monitor. The successor (wakee) will either acquire the lock or
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
172 // re-park itself.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
173 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
174 // Succession is provided for by a policy of competitive handoff.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
175 // The exiting thread does _not_ grant or pass ownership to the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
176 // successor thread. (This is also referred to as "handoff" succession").
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
177 // Instead the exiting thread releases ownership and possibly wakes
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
178 // a successor, so the successor can (re)compete for ownership of the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
179 // If the EntryList is empty but the cxq is populated the exiting
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
180 // thread will drain the cxq into the EntryList. It does so by
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
181 // by detaching the cxq (installing null with CAS) and folding
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
182 // the threads from the cxq into the EntryList. The EntryList is
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
183 // doubly linked, while the cxq is singly linked because of the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
184 // CAS-based "push" used to enqueue recently arrived threads (RATs).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
185 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
186 // * Concurrency invariants:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
187 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
188 // -- only the monitor owner may access or mutate the EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
189 // The mutex property of the monitor itself protects the EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
190 // from concurrent interference.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
191 // -- Only the monitor owner may detach the cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
192 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
193 // * The monitor entry list operations avoid locks, but strictly speaking
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
194 // they're not lock-free. Enter is lock-free, exit is not.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
195 // See http://j2se.east/~dice/PERSIST/040825-LockFreeQueues.html
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
196 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
197 // * The cxq can have multiple concurrent "pushers" but only one concurrent
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
198 // detaching thread. This mechanism is immune from the ABA corruption.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
199 // More precisely, the CAS-based "push" onto cxq is ABA-oblivious.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
200 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
201 // * Taken together, the cxq and the EntryList constitute or form a
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
202 // single logical queue of threads stalled trying to acquire the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
203 // We use two distinct lists to improve the odds of a constant-time
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
204 // dequeue operation after acquisition (in the ::enter() epilog) and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
205 // to reduce heat on the list ends. (c.f. Michael Scott's "2Q" algorithm).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
206 // A key desideratum is to minimize queue & monitor metadata manipulation
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
207 // that occurs while holding the monitor lock -- that is, we want to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
208 // minimize monitor lock holds times. Note that even a small amount of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
209 // fixed spinning will greatly reduce the # of enqueue-dequeue operations
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
210 // on EntryList|cxq. That is, spinning relieves contention on the "inner"
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
211 // locks and monitor metadata.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
212 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
213 // Cxq points to the the set of Recently Arrived Threads attempting entry.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
214 // Because we push threads onto _cxq with CAS, the RATs must take the form of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
215 // a singly-linked LIFO. We drain _cxq into EntryList at unlock-time when
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
216 // the unlocking thread notices that EntryList is null but _cxq is != null.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
217 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
218 // The EntryList is ordered by the prevailing queue discipline and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
219 // can be organized in any convenient fashion, such as a doubly-linked list or
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
220 // a circular doubly-linked list. Critically, we want insert and delete operations
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
221 // to operate in constant-time. If we need a priority queue then something akin
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
222 // to Solaris' sleepq would work nicely. Viz.,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
223 // http://agg.eng/ws/on10_nightly/source/usr/src/uts/common/os/sleepq.c.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
224 // Queue discipline is enforced at ::exit() time, when the unlocking thread
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
225 // drains the cxq into the EntryList, and orders or reorders the threads on the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
226 // EntryList accordingly.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
227 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
228 // Barring "lock barging", this mechanism provides fair cyclic ordering,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
229 // somewhat similar to an elevator-scan.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
230 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
231 // * The monitor synchronization subsystem avoids the use of native
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
232 // synchronization primitives except for the narrow platform-specific
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
233 // park-unpark abstraction. See the comments in os_solaris.cpp regarding
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
234 // the semantics of park-unpark. Put another way, this monitor implementation
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
235 // depends only on atomic operations and park-unpark. The monitor subsystem
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
236 // manages all RUNNING->BLOCKED and BLOCKED->READY transitions while the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
237 // underlying OS manages the READY<->RUN transitions.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
238 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
239 // * Waiting threads reside on the WaitSet list -- wait() puts
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
240 // the caller onto the WaitSet.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
241 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
242 // * notify() or notifyAll() simply transfers threads from the WaitSet to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
243 // either the EntryList or cxq. Subsequent exit() operations will
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
244 // unpark the notifyee. Unparking a notifee in notify() is inefficient -
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
245 // it's likely the notifyee would simply impale itself on the lock held
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
246 // by the notifier.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
247 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
248 // * An interesting alternative is to encode cxq as (List,LockByte) where
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
249 // the LockByte is 0 iff the monitor is owned. _owner is simply an auxiliary
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
250 // variable, like _recursions, in the scheme. The threads or Events that form
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
251 // the list would have to be aligned in 256-byte addresses. A thread would
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
252 // try to acquire the lock or enqueue itself with CAS, but exiting threads
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
253 // could use a 1-0 protocol and simply STB to set the LockByte to 0.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
254 // Note that is is *not* word-tearing, but it does presume that full-word
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
255 // CAS operations are coherent with intermix with STB operations. That's true
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
256 // on most common processors.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
257 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
258 // * See also http://blogs.sun.com/dave
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
259
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
260
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
261 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
262 // Enter support
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
263
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
264 bool ObjectMonitor::try_enter(Thread* THREAD) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
265 if (THREAD != _owner) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
266 if (THREAD->is_lock_owned ((address)_owner)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
267 assert(_recursions == 0, "internal state error");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
268 _owner = THREAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
269 _recursions = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
270 OwnerIsThread = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
271 return true;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
272 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
273 if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
274 return false;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
275 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
276 return true;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
277 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
278 _recursions++;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
279 return true;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
280 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
281 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
282
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
283 void ATTR ObjectMonitor::enter(TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
284 // The following code is ordered to check the most common cases first
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
285 // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
286 Thread * const Self = THREAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
287 void * cur ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
288
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
289 cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
290 if (cur == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
291 // Either ASSERT _recursions == 0 or explicitly set _recursions = 0.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
292 assert (_recursions == 0 , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
293 assert (_owner == Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
294 // CONSIDER: set or assert OwnerIsThread == 1
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
295 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
296 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
297
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
298 if (cur == Self) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
299 // TODO-FIXME: check for integer overflow! BUGID 6557169.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
300 _recursions ++ ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
301 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
302 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
303
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
304 if (Self->is_lock_owned ((address)cur)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
305 assert (_recursions == 0, "internal state error");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
306 _recursions = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
307 // Commute owner from a thread-specific on-stack BasicLockObject address to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
308 // a full-fledged "Thread *".
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
309 _owner = Self ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
310 OwnerIsThread = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
311 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
312 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
313
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
314 // We've encountered genuine contention.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
315 assert (Self->_Stalled == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
316 Self->_Stalled = intptr_t(this) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
317
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
318 // Try one round of spinning *before* enqueueing Self
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
319 // and before going through the awkward and expensive state
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
320 // transitions. The following spin is strictly optional ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
321 // Note that if we acquire the monitor from an initial spin
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
322 // we forgo posting JVMTI events and firing DTRACE probes.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
323 if (Knob_SpinEarly && TrySpin (Self) > 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
324 assert (_owner == Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
325 assert (_recursions == 0 , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
326 assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
327 Self->_Stalled = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
328 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
329 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
330
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
331 assert (_owner != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
332 assert (_succ != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
333 assert (Self->is_Java_thread() , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
334 JavaThread * jt = (JavaThread *) Self ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
335 assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
336 assert (jt->thread_state() != _thread_blocked , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
337 assert (this->object() != NULL , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
338 assert (_count >= 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
339
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
340 // Prevent deflation at STW-time. See deflate_idle_monitors() and is_busy().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
341 // Ensure the object-monitor relationship remains stable while there's contention.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
342 Atomic::inc_ptr(&_count);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
343
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
344 { // Change java thread status to indicate blocked on monitor enter.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
345 JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
346
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
347 DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
348 if (JvmtiExport::should_post_monitor_contended_enter()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
349 JvmtiExport::post_monitor_contended_enter(jt, this);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
350 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
351
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
352 OSThreadContendState osts(Self->osthread());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
353 ThreadBlockInVM tbivm(jt);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
354
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
355 Self->set_current_pending_monitor(this);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
356
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
357 // TODO-FIXME: change the following for(;;) loop to straight-line code.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
358 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
359 jt->set_suspend_equivalent();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
360 // cleared by handle_special_suspend_equivalent_condition()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
361 // or java_suspend_self()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
362
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
363 EnterI (THREAD) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
364
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
365 if (!ExitSuspendEquivalent(jt)) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
366
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
367 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
368 // We have acquired the contended monitor, but while we were
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
369 // waiting another thread suspended us. We don't want to enter
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
370 // the monitor while suspended because that would surprise the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
371 // thread that suspended us.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
372 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
373 _recursions = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
374 _succ = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
375 exit (Self) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
376
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
377 jt->java_suspend_self();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
378 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
379 Self->set_current_pending_monitor(NULL);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
380 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
381
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
382 Atomic::dec_ptr(&_count);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
383 assert (_count >= 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
384 Self->_Stalled = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
385
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
386 // Must either set _recursions = 0 or ASSERT _recursions == 0.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
387 assert (_recursions == 0 , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
388 assert (_owner == Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
389 assert (_succ != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
390 assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
391
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
392 // The thread -- now the owner -- is back in vm mode.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
393 // Report the glorious news via TI,DTrace and jvmstat.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
394 // The probe effect is non-trivial. All the reportage occurs
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
395 // while we hold the monitor, increasing the length of the critical
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
396 // section. Amdahl's parallel speedup law comes vividly into play.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
397 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
398 // Another option might be to aggregate the events (thread local or
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
399 // per-monitor aggregation) and defer reporting until a more opportune
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
400 // time -- such as next time some thread encounters contention but has
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
401 // yet to acquire the lock. While spinning that thread could
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
402 // spinning we could increment JVMStat counters, etc.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
403
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
404 DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
405 if (JvmtiExport::should_post_monitor_contended_entered()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
406 JvmtiExport::post_monitor_contended_entered(jt, this);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
407 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
408 if (ObjectMonitor::_sync_ContendedLockAttempts != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
409 ObjectMonitor::_sync_ContendedLockAttempts->inc() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
410 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
411 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
412
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
413
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
414 // Caveat: TryLock() is not necessarily serializing if it returns failure.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
415 // Callers must compensate as needed.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
416
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
417 int ObjectMonitor::TryLock (Thread * Self) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
418 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
419 void * own = _owner ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
420 if (own != NULL) return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
421 if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
422 // Either guarantee _recursions == 0 or set _recursions = 0.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
423 assert (_recursions == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
424 assert (_owner == Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
425 // CONSIDER: set or assert that OwnerIsThread == 1
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
426 return 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
427 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
428 // The lock had been free momentarily, but we lost the race to the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
429 // Interference -- the CAS failed.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
430 // We can either return -1 or retry.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
431 // Retry doesn't make as much sense because the lock was just acquired.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
432 if (true) return -1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
433 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
434 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
435
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
436 void ATTR ObjectMonitor::EnterI (TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
437 Thread * Self = THREAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
438 assert (Self->is_Java_thread(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
439 assert (((JavaThread *) Self)->thread_state() == _thread_blocked , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
440
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
441 // Try the lock - TATAS
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
442 if (TryLock (Self) > 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
443 assert (_succ != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
444 assert (_owner == Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
445 assert (_Responsible != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
446 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
447 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
448
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
449 DeferredInitialize () ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
450
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
451 // We try one round of spinning *before* enqueueing Self.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
452 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
453 // If the _owner is ready but OFFPROC we could use a YieldTo()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
454 // operation to donate the remainder of this thread's quantum
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
455 // to the owner. This has subtle but beneficial affinity
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
456 // effects.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
457
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
458 if (TrySpin (Self) > 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
459 assert (_owner == Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
460 assert (_succ != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
461 assert (_Responsible != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
462 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
463 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
464
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
465 // The Spin failed -- Enqueue and park the thread ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
466 assert (_succ != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
467 assert (_owner != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
468 assert (_Responsible != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
469
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
470 // Enqueue "Self" on ObjectMonitor's _cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
471 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
472 // Node acts as a proxy for Self.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
473 // As an aside, if were to ever rewrite the synchronization code mostly
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
474 // in Java, WaitNodes, ObjectMonitors, and Events would become 1st-class
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
475 // Java objects. This would avoid awkward lifecycle and liveness issues,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
476 // as well as eliminate a subset of ABA issues.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
477 // TODO: eliminate ObjectWaiter and enqueue either Threads or Events.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
478 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
479
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
480 ObjectWaiter node(Self) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
481 Self->_ParkEvent->reset() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
482 node._prev = (ObjectWaiter *) 0xBAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
483 node.TState = ObjectWaiter::TS_CXQ ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
484
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
485 // Push "Self" onto the front of the _cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
486 // Once on cxq/EntryList, Self stays on-queue until it acquires the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
487 // Note that spinning tends to reduce the rate at which threads
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
488 // enqueue and dequeue on EntryList|cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
489 ObjectWaiter * nxt ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
490 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
491 node._next = nxt = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
492 if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
493
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
494 // Interference - the CAS failed because _cxq changed. Just retry.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
495 // As an optional optimization we retry the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
496 if (TryLock (Self) > 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
497 assert (_succ != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
498 assert (_owner == Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
499 assert (_Responsible != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
500 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
501 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
502 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
503
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
504 // Check for cxq|EntryList edge transition to non-null. This indicates
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
505 // the onset of contention. While contention persists exiting threads
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
506 // will use a ST:MEMBAR:LD 1-1 exit protocol. When contention abates exit
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
507 // operations revert to the faster 1-0 mode. This enter operation may interleave
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
508 // (race) a concurrent 1-0 exit operation, resulting in stranding, so we
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
509 // arrange for one of the contending thread to use a timed park() operations
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
510 // to detect and recover from the race. (Stranding is form of progress failure
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
511 // where the monitor is unlocked but all the contending threads remain parked).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
512 // That is, at least one of the contended threads will periodically poll _owner.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
513 // One of the contending threads will become the designated "Responsible" thread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
514 // The Responsible thread uses a timed park instead of a normal indefinite park
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
515 // operation -- it periodically wakes and checks for and recovers from potential
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
516 // strandings admitted by 1-0 exit operations. We need at most one Responsible
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
517 // thread per-monitor at any given moment. Only threads on cxq|EntryList may
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
518 // be responsible for a monitor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
519 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
520 // Currently, one of the contended threads takes on the added role of "Responsible".
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
521 // A viable alternative would be to use a dedicated "stranding checker" thread
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
522 // that periodically iterated over all the threads (or active monitors) and unparked
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
523 // successors where there was risk of stranding. This would help eliminate the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
524 // timer scalability issues we see on some platforms as we'd only have one thread
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
525 // -- the checker -- parked on a timer.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
526
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
527 if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
528 // Try to assume the role of responsible thread for the monitor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
529 // CONSIDER: ST vs CAS vs { if (Responsible==null) Responsible=Self }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
530 Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
531 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
532
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
533 // The lock have been released while this thread was occupied queueing
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
534 // itself onto _cxq. To close the race and avoid "stranding" and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
535 // progress-liveness failure we must resample-retry _owner before parking.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
536 // Note the Dekker/Lamport duality: ST cxq; MEMBAR; LD Owner.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
537 // In this case the ST-MEMBAR is accomplished with CAS().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
538 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
539 // TODO: Defer all thread state transitions until park-time.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
540 // Since state transitions are heavy and inefficient we'd like
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
541 // to defer the state transitions until absolutely necessary,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
542 // and in doing so avoid some transitions ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
543
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
544 TEVENT (Inflated enter - Contention) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
545 int nWakeups = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
546 int RecheckInterval = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
547
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
548 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
549
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
550 if (TryLock (Self) > 0) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
551 assert (_owner != Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
552
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
553 if ((SyncFlags & 2) && _Responsible == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
554 Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
555 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
556
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
557 // park self
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
558 if (_Responsible == Self || (SyncFlags & 1)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
559 TEVENT (Inflated enter - park TIMED) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
560 Self->_ParkEvent->park ((jlong) RecheckInterval) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
561 // Increase the RecheckInterval, but clamp the value.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
562 RecheckInterval *= 8 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
563 if (RecheckInterval > 1000) RecheckInterval = 1000 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
564 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
565 TEVENT (Inflated enter - park UNTIMED) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
566 Self->_ParkEvent->park() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
567 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
568
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
569 if (TryLock(Self) > 0) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
570
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
571 // The lock is still contested.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
572 // Keep a tally of the # of futile wakeups.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
573 // Note that the counter is not protected by a lock or updated by atomics.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
574 // That is by design - we trade "lossy" counters which are exposed to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
575 // races during updates for a lower probe effect.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
576 TEVENT (Inflated enter - Futile wakeup) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
577 if (ObjectMonitor::_sync_FutileWakeups != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
578 ObjectMonitor::_sync_FutileWakeups->inc() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
579 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
580 ++ nWakeups ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
581
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
582 // Assuming this is not a spurious wakeup we'll normally find _succ == Self.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
583 // We can defer clearing _succ until after the spin completes
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
584 // TrySpin() must tolerate being called with _succ == Self.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
585 // Try yet another round of adaptive spinning.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
586 if ((Knob_SpinAfterFutile & 1) && TrySpin (Self) > 0) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
587
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
588 // We can find that we were unpark()ed and redesignated _succ while
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
589 // we were spinning. That's harmless. If we iterate and call park(),
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
590 // park() will consume the event and return immediately and we'll
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
591 // just spin again. This pattern can repeat, leaving _succ to simply
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
592 // spin on a CPU. Enable Knob_ResetEvent to clear pending unparks().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
593 // Alternately, we can sample fired() here, and if set, forgo spinning
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
594 // in the next iteration.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
595
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
596 if ((Knob_ResetEvent & 1) && Self->_ParkEvent->fired()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
597 Self->_ParkEvent->reset() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
598 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
599 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
600 if (_succ == Self) _succ = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
601
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
602 // Invariant: after clearing _succ a thread *must* retry _owner before parking.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
603 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
604 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
605
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
606 // Egress :
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
607 // Self has acquired the lock -- Unlink Self from the cxq or EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
608 // Normally we'll find Self on the EntryList .
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
609 // From the perspective of the lock owner (this thread), the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
610 // EntryList is stable and cxq is prepend-only.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
611 // The head of cxq is volatile but the interior is stable.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
612 // In addition, Self.TState is stable.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
613
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
614 assert (_owner == Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
615 assert (object() != NULL , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
616 // I'd like to write:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
617 // guarantee (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
618 // but as we're at a safepoint that's not safe.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
619
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
620 UnlinkAfterAcquire (Self, &node) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
621 if (_succ == Self) _succ = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
622
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
623 assert (_succ != Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
624 if (_Responsible == Self) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
625 _Responsible = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
626 // Dekker pivot-point.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
627 // Consider OrderAccess::storeload() here
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
628
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
629 // We may leave threads on cxq|EntryList without a designated
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
630 // "Responsible" thread. This is benign. When this thread subsequently
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
631 // exits the monitor it can "see" such preexisting "old" threads --
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
632 // threads that arrived on the cxq|EntryList before the fence, above --
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
633 // by LDing cxq|EntryList. Newly arrived threads -- that is, threads
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
634 // that arrive on cxq after the ST:MEMBAR, above -- will set Responsible
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
635 // non-null and elect a new "Responsible" timer thread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
636 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
637 // This thread executes:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
638 // ST Responsible=null; MEMBAR (in enter epilog - here)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
639 // LD cxq|EntryList (in subsequent exit)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
640 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
641 // Entering threads in the slow/contended path execute:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
642 // ST cxq=nonnull; MEMBAR; LD Responsible (in enter prolog)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
643 // The (ST cxq; MEMBAR) is accomplished with CAS().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
644 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
645 // The MEMBAR, above, prevents the LD of cxq|EntryList in the subsequent
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
646 // exit operation from floating above the ST Responsible=null.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
647 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
648 // In *practice* however, EnterI() is always followed by some atomic
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
649 // operation such as the decrement of _count in ::enter(). Those atomics
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
650 // obviate the need for the explicit MEMBAR, above.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
651 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
652
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
653 // We've acquired ownership with CAS().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
654 // CAS is serializing -- it has MEMBAR/FENCE-equivalent semantics.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
655 // But since the CAS() this thread may have also stored into _succ,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
656 // EntryList, cxq or Responsible. These meta-data updates must be
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
657 // visible __before this thread subsequently drops the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
658 // Consider what could occur if we didn't enforce this constraint --
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
659 // STs to monitor meta-data and user-data could reorder with (become
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
660 // visible after) the ST in exit that drops ownership of the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
661 // Some other thread could then acquire the lock, but observe inconsistent
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
662 // or old monitor meta-data and heap data. That violates the JMM.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
663 // To that end, the 1-0 exit() operation must have at least STST|LDST
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
664 // "release" barrier semantics. Specifically, there must be at least a
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
665 // STST|LDST barrier in exit() before the ST of null into _owner that drops
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
666 // the lock. The barrier ensures that changes to monitor meta-data and data
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
667 // protected by the lock will be visible before we release the lock, and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
668 // therefore before some other thread (CPU) has a chance to acquire the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
669 // See also: http://gee.cs.oswego.edu/dl/jmm/cookbook.html.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
670 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
671 // Critically, any prior STs to _succ or EntryList must be visible before
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
672 // the ST of null into _owner in the *subsequent* (following) corresponding
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
673 // monitorexit. Recall too, that in 1-0 mode monitorexit does not necessarily
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
674 // execute a serializing instruction.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
675
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
676 if (SyncFlags & 8) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
677 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
678 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
679 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
680 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
681
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
682 // ReenterI() is a specialized inline form of the latter half of the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
683 // contended slow-path from EnterI(). We use ReenterI() only for
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
684 // monitor reentry in wait().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
685 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
686 // In the future we should reconcile EnterI() and ReenterI(), adding
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
687 // Knob_Reset and Knob_SpinAfterFutile support and restructuring the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
688 // loop accordingly.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
689
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
690 void ATTR ObjectMonitor::ReenterI (Thread * Self, ObjectWaiter * SelfNode) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
691 assert (Self != NULL , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
692 assert (SelfNode != NULL , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
693 assert (SelfNode->_thread == Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
694 assert (_waiters > 0 , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
695 assert (((oop)(object()))->mark() == markOopDesc::encode(this) , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
696 assert (((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
697 JavaThread * jt = (JavaThread *) Self ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
698
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
699 int nWakeups = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
700 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
701 ObjectWaiter::TStates v = SelfNode->TState ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
702 guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
703 assert (_owner != Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
704
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
705 if (TryLock (Self) > 0) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
706 if (TrySpin (Self) > 0) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
707
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
708 TEVENT (Wait Reentry - parking) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
709
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
710 // State transition wrappers around park() ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
711 // ReenterI() wisely defers state transitions until
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
712 // it's clear we must park the thread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
713 {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
714 OSThreadContendState osts(Self->osthread());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
715 ThreadBlockInVM tbivm(jt);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
716
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
717 // cleared by handle_special_suspend_equivalent_condition()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
718 // or java_suspend_self()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
719 jt->set_suspend_equivalent();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
720 if (SyncFlags & 1) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
721 Self->_ParkEvent->park ((jlong)1000) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
722 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
723 Self->_ParkEvent->park () ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
724 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
725
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
726 // were we externally suspended while we were waiting?
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
727 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
728 if (!ExitSuspendEquivalent (jt)) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
729 if (_succ == Self) { _succ = NULL; OrderAccess::fence(); }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
730 jt->java_suspend_self();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
731 jt->set_suspend_equivalent();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
732 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
733 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
734
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
735 // Try again, but just so we distinguish between futile wakeups and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
736 // successful wakeups. The following test isn't algorithmically
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
737 // necessary, but it helps us maintain sensible statistics.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
738 if (TryLock(Self) > 0) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
739
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
740 // The lock is still contested.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
741 // Keep a tally of the # of futile wakeups.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
742 // Note that the counter is not protected by a lock or updated by atomics.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
743 // That is by design - we trade "lossy" counters which are exposed to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
744 // races during updates for a lower probe effect.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
745 TEVENT (Wait Reentry - futile wakeup) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
746 ++ nWakeups ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
747
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
748 // Assuming this is not a spurious wakeup we'll normally
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
749 // find that _succ == Self.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
750 if (_succ == Self) _succ = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
751
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
752 // Invariant: after clearing _succ a contending thread
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
753 // *must* retry _owner before parking.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
754 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
755
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
756 if (ObjectMonitor::_sync_FutileWakeups != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
757 ObjectMonitor::_sync_FutileWakeups->inc() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
758 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
759 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
760
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
761 // Self has acquired the lock -- Unlink Self from the cxq or EntryList .
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
762 // Normally we'll find Self on the EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
763 // Unlinking from the EntryList is constant-time and atomic-free.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
764 // From the perspective of the lock owner (this thread), the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
765 // EntryList is stable and cxq is prepend-only.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
766 // The head of cxq is volatile but the interior is stable.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
767 // In addition, Self.TState is stable.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
768
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
769 assert (_owner == Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
770 assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
771 UnlinkAfterAcquire (Self, SelfNode) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
772 if (_succ == Self) _succ = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
773 assert (_succ != Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
774 SelfNode->TState = ObjectWaiter::TS_RUN ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
775 OrderAccess::fence() ; // see comments at the end of EnterI()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
776 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
777
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
778 // after the thread acquires the lock in ::enter(). Equally, we could defer
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
779 // unlinking the thread until ::exit()-time.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
780
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
781 void ObjectMonitor::UnlinkAfterAcquire (Thread * Self, ObjectWaiter * SelfNode)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
782 {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
783 assert (_owner == Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
784 assert (SelfNode->_thread == Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
785
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
786 if (SelfNode->TState == ObjectWaiter::TS_ENTER) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
787 // Normal case: remove Self from the DLL EntryList .
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
788 // This is a constant-time operation.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
789 ObjectWaiter * nxt = SelfNode->_next ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
790 ObjectWaiter * prv = SelfNode->_prev ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
791 if (nxt != NULL) nxt->_prev = prv ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
792 if (prv != NULL) prv->_next = nxt ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
793 if (SelfNode == _EntryList ) _EntryList = nxt ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
794 assert (nxt == NULL || nxt->TState == ObjectWaiter::TS_ENTER, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
795 assert (prv == NULL || prv->TState == ObjectWaiter::TS_ENTER, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
796 TEVENT (Unlink from EntryList) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
797 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
798 guarantee (SelfNode->TState == ObjectWaiter::TS_CXQ, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
799 // Inopportune interleaving -- Self is still on the cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
800 // This usually means the enqueue of self raced an exiting thread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
801 // Normally we'll find Self near the front of the cxq, so
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
802 // dequeueing is typically fast. If needbe we can accelerate
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
803 // this with some MCS/CHL-like bidirectional list hints and advisory
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
804 // back-links so dequeueing from the interior will normally operate
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
805 // in constant-time.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
806 // Dequeue Self from either the head (with CAS) or from the interior
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
807 // with a linear-time scan and normal non-atomic memory operations.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
808 // CONSIDER: if Self is on the cxq then simply drain cxq into EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
809 // and then unlink Self from EntryList. We have to drain eventually,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
810 // so it might as well be now.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
811
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
812 ObjectWaiter * v = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
813 assert (v != NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
814 if (v != SelfNode || Atomic::cmpxchg_ptr (SelfNode->_next, &_cxq, v) != v) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
815 // The CAS above can fail from interference IFF a "RAT" arrived.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
816 // In that case Self must be in the interior and can no longer be
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
817 // at the head of cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
818 if (v == SelfNode) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
819 assert (_cxq != v, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
820 v = _cxq ; // CAS above failed - start scan at head of list
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
821 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
822 ObjectWaiter * p ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
823 ObjectWaiter * q = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
824 for (p = v ; p != NULL && p != SelfNode; p = p->_next) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
825 q = p ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
826 assert (p->TState == ObjectWaiter::TS_CXQ, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
827 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
828 assert (v != SelfNode, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
829 assert (p == SelfNode, "Node not found on cxq") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
830 assert (p != _cxq, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
831 assert (q != NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
832 assert (q->_next == p, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
833 q->_next = p->_next ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
834 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
835 TEVENT (Unlink from cxq) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
836 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
837
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
838 // Diagnostic hygiene ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
839 SelfNode->_prev = (ObjectWaiter *) 0xBAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
840 SelfNode->_next = (ObjectWaiter *) 0xBAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
841 SelfNode->TState = ObjectWaiter::TS_RUN ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
842 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
843
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
844 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
845 // Exit support
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
846 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
847 // exit()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
848 // ~~~~~~
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
849 // Note that the collector can't reclaim the objectMonitor or deflate
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
850 // the object out from underneath the thread calling ::exit() as the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
851 // thread calling ::exit() never transitions to a stable state.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
852 // This inhibits GC, which in turn inhibits asynchronous (and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
853 // inopportune) reclamation of "this".
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
854 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
855 // We'd like to assert that: (THREAD->thread_state() != _thread_blocked) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
856 // There's one exception to the claim above, however. EnterI() can call
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
857 // exit() to drop a lock if the acquirer has been externally suspended.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
858 // In that case exit() is called with _thread_state as _thread_blocked,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
859 // but the monitor's _count field is > 0, which inhibits reclamation.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
860 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
861 // 1-0 exit
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
862 // ~~~~~~~~
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
863 // ::exit() uses a canonical 1-1 idiom with a MEMBAR although some of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
864 // the fast-path operators have been optimized so the common ::exit()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
865 // operation is 1-0. See i486.ad fast_unlock(), for instance.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
866 // The code emitted by fast_unlock() elides the usual MEMBAR. This
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
867 // greatly improves latency -- MEMBAR and CAS having considerable local
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
868 // latency on modern processors -- but at the cost of "stranding". Absent the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
869 // MEMBAR, a thread in fast_unlock() can race a thread in the slow
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
870 // ::enter() path, resulting in the entering thread being stranding
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
871 // and a progress-liveness failure. Stranding is extremely rare.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
872 // We use timers (timed park operations) & periodic polling to detect
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
873 // and recover from stranding. Potentially stranded threads periodically
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
874 // wake up and poll the lock. See the usage of the _Responsible variable.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
875 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
876 // The CAS() in enter provides for safety and exclusion, while the CAS or
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
877 // MEMBAR in exit provides for progress and avoids stranding. 1-0 locking
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
878 // eliminates the CAS/MEMBAR from the exist path, but it admits stranding.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
879 // We detect and recover from stranding with timers.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
880 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
881 // If a thread transiently strands it'll park until (a) another
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
882 // thread acquires the lock and then drops the lock, at which time the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
883 // exiting thread will notice and unpark the stranded thread, or, (b)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
884 // the timer expires. If the lock is high traffic then the stranding latency
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
885 // will be low due to (a). If the lock is low traffic then the odds of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
886 // stranding are lower, although the worst-case stranding latency
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
887 // is longer. Critically, we don't want to put excessive load in the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
888 // platform's timer subsystem. We want to minimize both the timer injection
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
889 // rate (timers created/sec) as well as the number of timers active at
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
890 // any one time. (more precisely, we want to minimize timer-seconds, which is
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
891 // the integral of the # of active timers at any instant over time).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
892 // Both impinge on OS scalability. Given that, at most one thread parked on
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
893 // a monitor will use a timer.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
894
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
895 void ATTR ObjectMonitor::exit(TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
896 Thread * Self = THREAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
897 if (THREAD != _owner) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
898 if (THREAD->is_lock_owned((address) _owner)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
899 // Transmute _owner from a BasicLock pointer to a Thread address.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
900 // We don't need to hold _mutex for this transition.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
901 // Non-null to Non-null is safe as long as all readers can
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
902 // tolerate either flavor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
903 assert (_recursions == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
904 _owner = THREAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
905 _recursions = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
906 OwnerIsThread = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
907 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
908 // NOTE: we need to handle unbalanced monitor enter/exit
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
909 // in native code by throwing an exception.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
910 // TODO: Throw an IllegalMonitorStateException ?
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
911 TEVENT (Exit - Throw IMSX) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
912 assert(false, "Non-balanced monitor enter/exit!");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
913 if (false) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
914 THROW(vmSymbols::java_lang_IllegalMonitorStateException());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
915 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
916 return;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
917 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
918 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
919
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
920 if (_recursions != 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
921 _recursions--; // this is simple recursive enter
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
922 TEVENT (Inflated exit - recursive) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
923 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
924 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
925
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
926 // Invariant: after setting Responsible=null an thread must execute
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
927 // a MEMBAR or other serializing instruction before fetching EntryList|cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
928 if ((SyncFlags & 4) == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
929 _Responsible = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
930 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
931
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
932 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
933 assert (THREAD == _owner, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
934
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
935
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
936 if (Knob_ExitPolicy == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
937 // release semantics: prior loads and stores from within the critical section
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
938 // must not float (reorder) past the following store that drops the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
939 // On SPARC that requires MEMBAR #loadstore|#storestore.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
940 // But of course in TSO #loadstore|#storestore is not required.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
941 // I'd like to write one of the following:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
942 // A. OrderAccess::release() ; _owner = NULL
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
943 // B. OrderAccess::loadstore(); OrderAccess::storestore(); _owner = NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
944 // Unfortunately OrderAccess::release() and OrderAccess::loadstore() both
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
945 // store into a _dummy variable. That store is not needed, but can result
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
946 // in massive wasteful coherency traffic on classic SMP systems.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
947 // Instead, I use release_store(), which is implemented as just a simple
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
948 // ST on x64, x86 and SPARC.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
949 OrderAccess::release_store_ptr (&_owner, NULL) ; // drop the lock
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
950 OrderAccess::storeload() ; // See if we need to wake a successor
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
951 if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
952 TEVENT (Inflated exit - simple egress) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
953 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
954 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
955 TEVENT (Inflated exit - complex egress) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
956
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
957 // Normally the exiting thread is responsible for ensuring succession,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
958 // but if other successors are ready or other entering threads are spinning
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
959 // then this thread can simply store NULL into _owner and exit without
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
960 // waking a successor. The existence of spinners or ready successors
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
961 // guarantees proper succession (liveness). Responsibility passes to the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
962 // ready or running successors. The exiting thread delegates the duty.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
963 // More precisely, if a successor already exists this thread is absolved
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
964 // of the responsibility of waking (unparking) one.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
965 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
966 // The _succ variable is critical to reducing futile wakeup frequency.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
967 // _succ identifies the "heir presumptive" thread that has been made
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
968 // ready (unparked) but that has not yet run. We need only one such
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
969 // successor thread to guarantee progress.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
970 // See http://www.usenix.org/events/jvm01/full_papers/dice/dice.pdf
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
971 // section 3.3 "Futile Wakeup Throttling" for details.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
972 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
973 // Note that spinners in Enter() also set _succ non-null.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
974 // In the current implementation spinners opportunistically set
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
975 // _succ so that exiting threads might avoid waking a successor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
976 // Another less appealing alternative would be for the exiting thread
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
977 // to drop the lock and then spin briefly to see if a spinner managed
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
978 // to acquire the lock. If so, the exiting thread could exit
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
979 // immediately without waking a successor, otherwise the exiting
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
980 // thread would need to dequeue and wake a successor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
981 // (Note that we'd need to make the post-drop spin short, but no
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
982 // shorter than the worst-case round-trip cache-line migration time.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
983 // The dropped lock needs to become visible to the spinner, and then
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
984 // the acquisition of the lock by the spinner must become visible to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
985 // the exiting thread).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
986 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
987
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
988 // It appears that an heir-presumptive (successor) must be made ready.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
989 // Only the current lock owner can manipulate the EntryList or
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
990 // drain _cxq, so we need to reacquire the lock. If we fail
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
991 // to reacquire the lock the responsibility for ensuring succession
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
992 // falls to the new owner.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
993 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
994 if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
995 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
996 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
997 TEVENT (Exit - Reacquired) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
998 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
999 if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1000 OrderAccess::release_store_ptr (&_owner, NULL) ; // drop the lock
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1001 OrderAccess::storeload() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1002 // Ratify the previously observed values.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1003 if (_cxq == NULL || _succ != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1004 TEVENT (Inflated exit - simple egress) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1005 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1006 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1007
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1008 // inopportune interleaving -- the exiting thread (this thread)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1009 // in the fast-exit path raced an entering thread in the slow-enter
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1010 // path.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1011 // We have two choices:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1012 // A. Try to reacquire the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1013 // If the CAS() fails return immediately, otherwise
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1014 // we either restart/rerun the exit operation, or simply
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1015 // fall-through into the code below which wakes a successor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1016 // B. If the elements forming the EntryList|cxq are TSM
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1017 // we could simply unpark() the lead thread and return
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1018 // without having set _succ.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1019 if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1020 TEVENT (Inflated exit - reacquired succeeded) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1021 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1022 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1023 TEVENT (Inflated exit - reacquired failed) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1024 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1025 TEVENT (Inflated exit - complex egress) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1026 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1027 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1028
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1029 guarantee (_owner == THREAD, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1030
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1031 ObjectWaiter * w = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1032 int QMode = Knob_QMode ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1033
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1034 if (QMode == 2 && _cxq != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1035 // QMode == 2 : cxq has precedence over EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1036 // Try to directly wake a successor from the cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1037 // If successful, the successor will need to unlink itself from cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1038 w = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1039 assert (w != NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1040 assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1041 ExitEpilog (Self, w) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1042 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1043 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1044
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1045 if (QMode == 3 && _cxq != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1046 // Aggressively drain cxq into EntryList at the first opportunity.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1047 // This policy ensure that recently-run threads live at the head of EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1048 // Drain _cxq into EntryList - bulk transfer.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1049 // First, detach _cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1050 // The following loop is tantamount to: w = swap (&cxq, NULL)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1051 w = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1052 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1053 assert (w != NULL, "Invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1054 ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1055 if (u == w) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1056 w = u ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1057 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1058 assert (w != NULL , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1059
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1060 ObjectWaiter * q = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1061 ObjectWaiter * p ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1062 for (p = w ; p != NULL ; p = p->_next) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1063 guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1064 p->TState = ObjectWaiter::TS_ENTER ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1065 p->_prev = q ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1066 q = p ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1067 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1068
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1069 // Append the RATs to the EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1070 // TODO: organize EntryList as a CDLL so we can locate the tail in constant-time.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1071 ObjectWaiter * Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1072 for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1073 if (Tail == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1074 _EntryList = w ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1075 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1076 Tail->_next = w ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1077 w->_prev = Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1078 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1079
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1080 // Fall thru into code that tries to wake a successor from EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1081 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1082
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1083 if (QMode == 4 && _cxq != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1084 // Aggressively drain cxq into EntryList at the first opportunity.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1085 // This policy ensure that recently-run threads live at the head of EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1086
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1087 // Drain _cxq into EntryList - bulk transfer.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1088 // First, detach _cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1089 // The following loop is tantamount to: w = swap (&cxq, NULL)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1090 w = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1091 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1092 assert (w != NULL, "Invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1093 ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1094 if (u == w) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1095 w = u ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1096 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1097 assert (w != NULL , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1098
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1099 ObjectWaiter * q = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1100 ObjectWaiter * p ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1101 for (p = w ; p != NULL ; p = p->_next) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1102 guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1103 p->TState = ObjectWaiter::TS_ENTER ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1104 p->_prev = q ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1105 q = p ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1106 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1107
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1108 // Prepend the RATs to the EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1109 if (_EntryList != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1110 q->_next = _EntryList ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1111 _EntryList->_prev = q ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1112 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1113 _EntryList = w ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1114
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1115 // Fall thru into code that tries to wake a successor from EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1116 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1117
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1118 w = _EntryList ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1119 if (w != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1120 // I'd like to write: guarantee (w->_thread != Self).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1121 // But in practice an exiting thread may find itself on the EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1122 // Lets say thread T1 calls O.wait(). Wait() enqueues T1 on O's waitset and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1123 // then calls exit(). Exit release the lock by setting O._owner to NULL.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1124 // Lets say T1 then stalls. T2 acquires O and calls O.notify(). The
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1125 // notify() operation moves T1 from O's waitset to O's EntryList. T2 then
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1126 // release the lock "O". T2 resumes immediately after the ST of null into
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1127 // _owner, above. T2 notices that the EntryList is populated, so it
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1128 // reacquires the lock and then finds itself on the EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1129 // Given all that, we have to tolerate the circumstance where "w" is
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1130 // associated with Self.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1131 assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1132 ExitEpilog (Self, w) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1133 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1134 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1135
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1136 // If we find that both _cxq and EntryList are null then just
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1137 // re-run the exit protocol from the top.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1138 w = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1139 if (w == NULL) continue ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1140
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1141 // Drain _cxq into EntryList - bulk transfer.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1142 // First, detach _cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1143 // The following loop is tantamount to: w = swap (&cxq, NULL)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1144 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1145 assert (w != NULL, "Invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1146 ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1147 if (u == w) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1148 w = u ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1149 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1150 TEVENT (Inflated exit - drain cxq into EntryList) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1151
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1152 assert (w != NULL , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1153 assert (_EntryList == NULL , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1154
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1155 // Convert the LIFO SLL anchored by _cxq into a DLL.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1156 // The list reorganization step operates in O(LENGTH(w)) time.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1157 // It's critical that this step operate quickly as
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1158 // "Self" still holds the outer-lock, restricting parallelism
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1159 // and effectively lengthening the critical section.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1160 // Invariant: s chases t chases u.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1161 // TODO-FIXME: consider changing EntryList from a DLL to a CDLL so
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1162 // we have faster access to the tail.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1163
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1164 if (QMode == 1) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1165 // QMode == 1 : drain cxq to EntryList, reversing order
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1166 // We also reverse the order of the list.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1167 ObjectWaiter * s = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1168 ObjectWaiter * t = w ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1169 ObjectWaiter * u = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1170 while (t != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1171 guarantee (t->TState == ObjectWaiter::TS_CXQ, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1172 t->TState = ObjectWaiter::TS_ENTER ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1173 u = t->_next ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1174 t->_prev = u ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1175 t->_next = s ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1176 s = t;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1177 t = u ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1178 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1179 _EntryList = s ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1180 assert (s != NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1181 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1182 // QMode == 0 or QMode == 2
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1183 _EntryList = w ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1184 ObjectWaiter * q = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1185 ObjectWaiter * p ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1186 for (p = w ; p != NULL ; p = p->_next) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1187 guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1188 p->TState = ObjectWaiter::TS_ENTER ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1189 p->_prev = q ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1190 q = p ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1191 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1192 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1193
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1194 // In 1-0 mode we need: ST EntryList; MEMBAR #storestore; ST _owner = NULL
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1195 // The MEMBAR is satisfied by the release_store() operation in ExitEpilog().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1196
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1197 // See if we can abdicate to a spinner instead of waking a thread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1198 // A primary goal of the implementation is to reduce the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1199 // context-switch rate.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1200 if (_succ != NULL) continue;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1201
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1202 w = _EntryList ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1203 if (w != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1204 guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1205 ExitEpilog (Self, w) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1206 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1207 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1208 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1209 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1210
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1211 // ExitSuspendEquivalent:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1212 // A faster alternate to handle_special_suspend_equivalent_condition()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1213 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1214 // handle_special_suspend_equivalent_condition() unconditionally
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1215 // acquires the SR_lock. On some platforms uncontended MutexLocker()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1216 // operations have high latency. Note that in ::enter() we call HSSEC
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1217 // while holding the monitor, so we effectively lengthen the critical sections.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1218 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1219 // There are a number of possible solutions:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1220 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1221 // A. To ameliorate the problem we might also defer state transitions
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1222 // to as late as possible -- just prior to parking.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1223 // Given that, we'd call HSSEC after having returned from park(),
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1224 // but before attempting to acquire the monitor. This is only a
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1225 // partial solution. It avoids calling HSSEC while holding the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1226 // monitor (good), but it still increases successor reacquisition latency --
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1227 // the interval between unparking a successor and the time the successor
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1228 // resumes and retries the lock. See ReenterI(), which defers state transitions.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1229 // If we use this technique we can also avoid EnterI()-exit() loop
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1230 // in ::enter() where we iteratively drop the lock and then attempt
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1231 // to reacquire it after suspending.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1232 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1233 // B. In the future we might fold all the suspend bits into a
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1234 // composite per-thread suspend flag and then update it with CAS().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1235 // Alternately, a Dekker-like mechanism with multiple variables
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1236 // would suffice:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1237 // ST Self->_suspend_equivalent = false
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1238 // MEMBAR
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1239 // LD Self_>_suspend_flags
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1240 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1241
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1242
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1243 bool ObjectMonitor::ExitSuspendEquivalent (JavaThread * jSelf) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1244 int Mode = Knob_FastHSSEC ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1245 if (Mode && !jSelf->is_external_suspend()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1246 assert (jSelf->is_suspend_equivalent(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1247 jSelf->clear_suspend_equivalent() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1248 if (2 == Mode) OrderAccess::storeload() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1249 if (!jSelf->is_external_suspend()) return false ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1250 // We raced a suspension -- fall thru into the slow path
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1251 TEVENT (ExitSuspendEquivalent - raced) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1252 jSelf->set_suspend_equivalent() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1253 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1254 return jSelf->handle_special_suspend_equivalent_condition() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1255 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1256
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1257
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1258 void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1259 assert (_owner == Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1260
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1261 // Exit protocol:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1262 // 1. ST _succ = wakee
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1263 // 2. membar #loadstore|#storestore;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1264 // 2. ST _owner = NULL
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1265 // 3. unpark(wakee)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1266
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1267 _succ = Knob_SuccEnabled ? Wakee->_thread : NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1268 ParkEvent * Trigger = Wakee->_event ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1269
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1270 // Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1271 // The thread associated with Wakee may have grabbed the lock and "Wakee" may be
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1272 // out-of-scope (non-extant).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1273 Wakee = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1274
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1275 // Drop the lock
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1276 OrderAccess::release_store_ptr (&_owner, NULL) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1277 OrderAccess::fence() ; // ST _owner vs LD in unpark()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1278
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1279 if (SafepointSynchronize::do_call_back()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1280 TEVENT (unpark before SAFEPOINT) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1281 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1282
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1283 DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1284 Trigger->unpark() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1285
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1286 // Maintain stats and report events to JVMTI
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1287 if (ObjectMonitor::_sync_Parks != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1288 ObjectMonitor::_sync_Parks->inc() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1289 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1290 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1291
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1292
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1293 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1294 // Class Loader deadlock handling.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1295 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1296 // complete_exit exits a lock returning recursion count
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1297 // complete_exit/reenter operate as a wait without waiting
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1298 // complete_exit requires an inflated monitor
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1299 // The _owner field is not always the Thread addr even with an
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1300 // inflated monitor, e.g. the monitor can be inflated by a non-owning
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1301 // thread due to contention.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1302 intptr_t ObjectMonitor::complete_exit(TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1303 Thread * const Self = THREAD;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1304 assert(Self->is_Java_thread(), "Must be Java thread!");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1305 JavaThread *jt = (JavaThread *)THREAD;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1306
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1307 DeferredInitialize();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1308
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1309 if (THREAD != _owner) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1310 if (THREAD->is_lock_owned ((address)_owner)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1311 assert(_recursions == 0, "internal state error");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1312 _owner = THREAD ; /* Convert from basiclock addr to Thread addr */
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1313 _recursions = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1314 OwnerIsThread = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1315 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1316 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1317
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1318 guarantee(Self == _owner, "complete_exit not owner");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1319 intptr_t save = _recursions; // record the old recursion count
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1320 _recursions = 0; // set the recursion level to be 0
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1321 exit (Self) ; // exit the monitor
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1322 guarantee (_owner != Self, "invariant");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1323 return save;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1324 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1325
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1326 // reenter() enters a lock and sets recursion count
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1327 // complete_exit/reenter operate as a wait without waiting
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1328 void ObjectMonitor::reenter(intptr_t recursions, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1329 Thread * const Self = THREAD;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1330 assert(Self->is_Java_thread(), "Must be Java thread!");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1331 JavaThread *jt = (JavaThread *)THREAD;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1332
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1333 guarantee(_owner != Self, "reenter already owner");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1334 enter (THREAD); // enter the monitor
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1335 guarantee (_recursions == 0, "reenter recursion");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1336 _recursions = recursions;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1337 return;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1338 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1339
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1340
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1341 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1342 // A macro is used below because there may already be a pending
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1343 // exception which should not abort the execution of the routines
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1344 // which use this (which is why we don't put this into check_slow and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1345 // call it with a CHECK argument).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1346
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1347 #define CHECK_OWNER() \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1348 do { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1349 if (THREAD != _owner) { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1350 if (THREAD->is_lock_owned((address) _owner)) { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1351 _owner = THREAD ; /* Convert from basiclock addr to Thread addr */ \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1352 _recursions = 0; \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1353 OwnerIsThread = 1 ; \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1354 } else { \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1355 TEVENT (Throw IMSX) ; \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1356 THROW(vmSymbols::java_lang_IllegalMonitorStateException()); \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1357 } \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1358 } \
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1359 } while (false)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1360
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1361 // check_slow() is a misnomer. It's called to simply to throw an IMSX exception.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1362 // TODO-FIXME: remove check_slow() -- it's likely dead.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1363
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1364 void ObjectMonitor::check_slow(TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1365 TEVENT (check_slow - throw IMSX) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1366 assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1367 THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1368 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1369
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1370 static int Adjust (volatile int * adr, int dx) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1371 int v ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1372 for (v = *adr ; Atomic::cmpxchg (v + dx, adr, v) != v; v = *adr) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1373 return v ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1374 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1375 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1376 // Wait/Notify/NotifyAll
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1377 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1378 // Note: a subset of changes to ObjectMonitor::wait()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1379 // will need to be replicated in complete_exit above
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1380 void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1381 Thread * const Self = THREAD ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1382 assert(Self->is_Java_thread(), "Must be Java thread!");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1383 JavaThread *jt = (JavaThread *)THREAD;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1384
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1385 DeferredInitialize () ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1386
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1387 // Throw IMSX or IEX.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1388 CHECK_OWNER();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1389
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1390 // check for a pending interrupt
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1391 if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1392 // post monitor waited event. Note that this is past-tense, we are done waiting.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1393 if (JvmtiExport::should_post_monitor_waited()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1394 // Note: 'false' parameter is passed here because the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1395 // wait was not timed out due to thread interrupt.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1396 JvmtiExport::post_monitor_waited(jt, this, false);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1397 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1398 TEVENT (Wait - Throw IEX) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1399 THROW(vmSymbols::java_lang_InterruptedException());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1400 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1401 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1402 TEVENT (Wait) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1403
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1404 assert (Self->_Stalled == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1405 Self->_Stalled = intptr_t(this) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1406 jt->set_current_waiting_monitor(this);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1407
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1408 // create a node to be put into the queue
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1409 // Critically, after we reset() the event but prior to park(), we must check
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1410 // for a pending interrupt.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1411 ObjectWaiter node(Self);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1412 node.TState = ObjectWaiter::TS_WAIT ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1413 Self->_ParkEvent->reset() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1414 OrderAccess::fence(); // ST into Event; membar ; LD interrupted-flag
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1415
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1416 // Enter the waiting queue, which is a circular doubly linked list in this case
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1417 // but it could be a priority queue or any data structure.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1418 // _WaitSetLock protects the wait queue. Normally the wait queue is accessed only
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1419 // by the the owner of the monitor *except* in the case where park()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1420 // returns because of a timeout of interrupt. Contention is exceptionally rare
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1421 // so we use a simple spin-lock instead of a heavier-weight blocking lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1422
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1423 Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1424 AddWaiter (&node) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1425 Thread::SpinRelease (&_WaitSetLock) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1426
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1427 if ((SyncFlags & 4) == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1428 _Responsible = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1429 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1430 intptr_t save = _recursions; // record the old recursion count
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1431 _waiters++; // increment the number of waiters
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1432 _recursions = 0; // set the recursion level to be 1
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1433 exit (Self) ; // exit the monitor
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1434 guarantee (_owner != Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1435
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1436 // As soon as the ObjectMonitor's ownership is dropped in the exit()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1437 // call above, another thread can enter() the ObjectMonitor, do the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1438 // notify(), and exit() the ObjectMonitor. If the other thread's
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1439 // exit() call chooses this thread as the successor and the unpark()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1440 // call happens to occur while this thread is posting a
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1441 // MONITOR_CONTENDED_EXIT event, then we run the risk of the event
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1442 // handler using RawMonitors and consuming the unpark().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1443 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1444 // To avoid the problem, we re-post the event. This does no harm
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1445 // even if the original unpark() was not consumed because we are the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1446 // chosen successor for this monitor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1447 if (node._notified != 0 && _succ == Self) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1448 node._event->unpark();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1449 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1450
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1451 // The thread is on the WaitSet list - now park() it.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1452 // On MP systems it's conceivable that a brief spin before we park
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1453 // could be profitable.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1454 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1455 // TODO-FIXME: change the following logic to a loop of the form
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1456 // while (!timeout && !interrupted && _notified == 0) park()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1457
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1458 int ret = OS_OK ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1459 int WasNotified = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1460 { // State transition wrappers
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1461 OSThread* osthread = Self->osthread();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1462 OSThreadWaitState osts(osthread, true);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1463 {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1464 ThreadBlockInVM tbivm(jt);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1465 // Thread is in thread_blocked state and oop access is unsafe.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1466 jt->set_suspend_equivalent();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1467
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1468 if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1469 // Intentionally empty
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1470 } else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1471 if (node._notified == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1472 if (millis <= 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1473 Self->_ParkEvent->park () ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1474 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1475 ret = Self->_ParkEvent->park (millis) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1476 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1477 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1478
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1479 // were we externally suspended while we were waiting?
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1480 if (ExitSuspendEquivalent (jt)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1481 // TODO-FIXME: add -- if succ == Self then succ = null.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1482 jt->java_suspend_self();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1483 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1484
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1485 } // Exit thread safepoint: transition _thread_blocked -> _thread_in_vm
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1486
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1487
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1488 // Node may be on the WaitSet, the EntryList (or cxq), or in transition
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1489 // from the WaitSet to the EntryList.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1490 // See if we need to remove Node from the WaitSet.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1491 // We use double-checked locking to avoid grabbing _WaitSetLock
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1492 // if the thread is not on the wait queue.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1493 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1494 // Note that we don't need a fence before the fetch of TState.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1495 // In the worst case we'll fetch a old-stale value of TS_WAIT previously
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1496 // written by the is thread. (perhaps the fetch might even be satisfied
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1497 // by a look-aside into the processor's own store buffer, although given
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1498 // the length of the code path between the prior ST and this load that's
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1499 // highly unlikely). If the following LD fetches a stale TS_WAIT value
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1500 // then we'll acquire the lock and then re-fetch a fresh TState value.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1501 // That is, we fail toward safety.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1502
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1503 if (node.TState == ObjectWaiter::TS_WAIT) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1504 Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1505 if (node.TState == ObjectWaiter::TS_WAIT) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1506 DequeueSpecificWaiter (&node) ; // unlink from WaitSet
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1507 assert(node._notified == 0, "invariant");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1508 node.TState = ObjectWaiter::TS_RUN ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1509 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1510 Thread::SpinRelease (&_WaitSetLock) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1511 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1512
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1513 // The thread is now either on off-list (TS_RUN),
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1514 // on the EntryList (TS_ENTER), or on the cxq (TS_CXQ).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1515 // The Node's TState variable is stable from the perspective of this thread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1516 // No other threads will asynchronously modify TState.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1517 guarantee (node.TState != ObjectWaiter::TS_WAIT, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1518 OrderAccess::loadload() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1519 if (_succ == Self) _succ = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1520 WasNotified = node._notified ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1521
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1522 // Reentry phase -- reacquire the monitor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1523 // re-enter contended monitor after object.wait().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1524 // retain OBJECT_WAIT state until re-enter successfully completes
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1525 // Thread state is thread_in_vm and oop access is again safe,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1526 // although the raw address of the object may have changed.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1527 // (Don't cache naked oops over safepoints, of course).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1528
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1529 // post monitor waited event. Note that this is past-tense, we are done waiting.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1530 if (JvmtiExport::should_post_monitor_waited()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1531 JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1532 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1533 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1534
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1535 assert (Self->_Stalled != 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1536 Self->_Stalled = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1537
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1538 assert (_owner != Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1539 ObjectWaiter::TStates v = node.TState ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1540 if (v == ObjectWaiter::TS_RUN) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1541 enter (Self) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1542 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1543 guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1544 ReenterI (Self, &node) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1545 node.wait_reenter_end(this);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1546 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1547
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1548 // Self has reacquired the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1549 // Lifecycle - the node representing Self must not appear on any queues.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1550 // Node is about to go out-of-scope, but even if it were immortal we wouldn't
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1551 // want residual elements associated with this thread left on any lists.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1552 guarantee (node.TState == ObjectWaiter::TS_RUN, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1553 assert (_owner == Self, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1554 assert (_succ != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1555 } // OSThreadWaitState()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1556
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1557 jt->set_current_waiting_monitor(NULL);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1558
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1559 guarantee (_recursions == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1560 _recursions = save; // restore the old recursion count
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1561 _waiters--; // decrement the number of waiters
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1562
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1563 // Verify a few postconditions
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1564 assert (_owner == Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1565 assert (_succ != Self , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1566 assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1567
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1568 if (SyncFlags & 32) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1569 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1570 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1571
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1572 // check if the notification happened
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1573 if (!WasNotified) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1574 // no, it could be timeout or Thread.interrupt() or both
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1575 // check for interrupt event, otherwise it is timeout
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1576 if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1577 TEVENT (Wait - throw IEX from epilog) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1578 THROW(vmSymbols::java_lang_InterruptedException());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1579 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1580 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1581
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1582 // NOTE: Spurious wake up will be consider as timeout.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1583 // Monitor notify has precedence over thread interrupt.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1584 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1585
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1586
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1587 // Consider:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1588 // If the lock is cool (cxq == null && succ == null) and we're on an MP system
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1589 // then instead of transferring a thread from the WaitSet to the EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1590 // we might just dequeue a thread from the WaitSet and directly unpark() it.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1591
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1592 void ObjectMonitor::notify(TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1593 CHECK_OWNER();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1594 if (_WaitSet == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1595 TEVENT (Empty-Notify) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1596 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1597 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1598 DTRACE_MONITOR_PROBE(notify, this, object(), THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1599
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1600 int Policy = Knob_MoveNotifyee ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1601
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1602 Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notify") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1603 ObjectWaiter * iterator = DequeueWaiter() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1604 if (iterator != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1605 TEVENT (Notify1 - Transfer) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1606 guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1607 guarantee (iterator->_notified == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1608 if (Policy != 4) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1609 iterator->TState = ObjectWaiter::TS_ENTER ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1610 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1611 iterator->_notified = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1612
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1613 ObjectWaiter * List = _EntryList ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1614 if (List != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1615 assert (List->_prev == NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1616 assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1617 assert (List != iterator, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1618 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1619
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1620 if (Policy == 0) { // prepend to EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1621 if (List == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1622 iterator->_next = iterator->_prev = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1623 _EntryList = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1624 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1625 List->_prev = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1626 iterator->_next = List ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1627 iterator->_prev = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1628 _EntryList = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1629 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1630 } else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1631 if (Policy == 1) { // append to EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1632 if (List == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1633 iterator->_next = iterator->_prev = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1634 _EntryList = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1635 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1636 // CONSIDER: finding the tail currently requires a linear-time walk of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1637 // the EntryList. We can make tail access constant-time by converting to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1638 // a CDLL instead of using our current DLL.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1639 ObjectWaiter * Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1640 for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1641 assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1642 Tail->_next = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1643 iterator->_prev = Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1644 iterator->_next = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1645 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1646 } else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1647 if (Policy == 2) { // prepend to cxq
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1648 // prepend to cxq
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1649 if (List == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1650 iterator->_next = iterator->_prev = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1651 _EntryList = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1652 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1653 iterator->TState = ObjectWaiter::TS_CXQ ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1654 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1655 ObjectWaiter * Front = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1656 iterator->_next = Front ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1657 if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1658 break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1659 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1660 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1661 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1662 } else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1663 if (Policy == 3) { // append to cxq
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1664 iterator->TState = ObjectWaiter::TS_CXQ ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1665 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1666 ObjectWaiter * Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1667 Tail = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1668 if (Tail == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1669 iterator->_next = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1670 if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1671 break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1672 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1673 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1674 while (Tail->_next != NULL) Tail = Tail->_next ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1675 Tail->_next = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1676 iterator->_prev = Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1677 iterator->_next = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1678 break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1679 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1680 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1681 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1682 ParkEvent * ev = iterator->_event ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1683 iterator->TState = ObjectWaiter::TS_RUN ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1684 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1685 ev->unpark() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1686 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1687
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1688 if (Policy < 4) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1689 iterator->wait_reenter_begin(this);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1690 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1691
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1692 // _WaitSetLock protects the wait queue, not the EntryList. We could
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1693 // move the add-to-EntryList operation, above, outside the critical section
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1694 // protected by _WaitSetLock. In practice that's not useful. With the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1695 // exception of wait() timeouts and interrupts the monitor owner
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1696 // is the only thread that grabs _WaitSetLock. There's almost no contention
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1697 // on _WaitSetLock so it's not profitable to reduce the length of the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1698 // critical section.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1699 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1700
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1701 Thread::SpinRelease (&_WaitSetLock) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1702
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1703 if (iterator != NULL && ObjectMonitor::_sync_Notifications != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1704 ObjectMonitor::_sync_Notifications->inc() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1705 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1706 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1707
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1708
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1709 void ObjectMonitor::notifyAll(TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1710 CHECK_OWNER();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1711 ObjectWaiter* iterator;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1712 if (_WaitSet == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1713 TEVENT (Empty-NotifyAll) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1714 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1715 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1716 DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1717
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1718 int Policy = Knob_MoveNotifyee ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1719 int Tally = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1720 Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notifyall") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1721
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1722 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1723 iterator = DequeueWaiter () ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1724 if (iterator == NULL) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1725 TEVENT (NotifyAll - Transfer1) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1726 ++Tally ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1727
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1728 // Disposition - what might we do with iterator ?
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1729 // a. add it directly to the EntryList - either tail or head.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1730 // b. push it onto the front of the _cxq.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1731 // For now we use (a).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1732
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1733 guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1734 guarantee (iterator->_notified == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1735 iterator->_notified = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1736 if (Policy != 4) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1737 iterator->TState = ObjectWaiter::TS_ENTER ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1738 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1739
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1740 ObjectWaiter * List = _EntryList ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1741 if (List != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1742 assert (List->_prev == NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1743 assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1744 assert (List != iterator, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1745 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1746
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1747 if (Policy == 0) { // prepend to EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1748 if (List == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1749 iterator->_next = iterator->_prev = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1750 _EntryList = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1751 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1752 List->_prev = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1753 iterator->_next = List ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1754 iterator->_prev = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1755 _EntryList = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1756 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1757 } else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1758 if (Policy == 1) { // append to EntryList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1759 if (List == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1760 iterator->_next = iterator->_prev = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1761 _EntryList = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1762 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1763 // CONSIDER: finding the tail currently requires a linear-time walk of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1764 // the EntryList. We can make tail access constant-time by converting to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1765 // a CDLL instead of using our current DLL.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1766 ObjectWaiter * Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1767 for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1768 assert (Tail != NULL && Tail->_next == NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1769 Tail->_next = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1770 iterator->_prev = Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1771 iterator->_next = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1772 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1773 } else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1774 if (Policy == 2) { // prepend to cxq
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1775 // prepend to cxq
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1776 iterator->TState = ObjectWaiter::TS_CXQ ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1777 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1778 ObjectWaiter * Front = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1779 iterator->_next = Front ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1780 if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1781 break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1782 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1783 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1784 } else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1785 if (Policy == 3) { // append to cxq
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1786 iterator->TState = ObjectWaiter::TS_CXQ ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1787 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1788 ObjectWaiter * Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1789 Tail = _cxq ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1790 if (Tail == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1791 iterator->_next = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1792 if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1793 break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1794 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1795 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1796 while (Tail->_next != NULL) Tail = Tail->_next ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1797 Tail->_next = iterator ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1798 iterator->_prev = Tail ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1799 iterator->_next = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1800 break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1801 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1802 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1803 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1804 ParkEvent * ev = iterator->_event ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1805 iterator->TState = ObjectWaiter::TS_RUN ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1806 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1807 ev->unpark() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1808 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1809
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1810 if (Policy < 4) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1811 iterator->wait_reenter_begin(this);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1812 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1813
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1814 // _WaitSetLock protects the wait queue, not the EntryList. We could
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1815 // move the add-to-EntryList operation, above, outside the critical section
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1816 // protected by _WaitSetLock. In practice that's not useful. With the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1817 // exception of wait() timeouts and interrupts the monitor owner
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1818 // is the only thread that grabs _WaitSetLock. There's almost no contention
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1819 // on _WaitSetLock so it's not profitable to reduce the length of the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1820 // critical section.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1821 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1822
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1823 Thread::SpinRelease (&_WaitSetLock) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1824
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1825 if (Tally != 0 && ObjectMonitor::_sync_Notifications != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1826 ObjectMonitor::_sync_Notifications->inc(Tally) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1827 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1828 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1829
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1830 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1831 // Adaptive Spinning Support
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1832 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1833 // Adaptive spin-then-block - rational spinning
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1834 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1835 // Note that we spin "globally" on _owner with a classic SMP-polite TATAS
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1836 // algorithm. On high order SMP systems it would be better to start with
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1837 // a brief global spin and then revert to spinning locally. In the spirit of MCS/CLH,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1838 // a contending thread could enqueue itself on the cxq and then spin locally
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1839 // on a thread-specific variable such as its ParkEvent._Event flag.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1840 // That's left as an exercise for the reader. Note that global spinning is
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1841 // not problematic on Niagara, as the L2$ serves the interconnect and has both
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1842 // low latency and massive bandwidth.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1843 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1844 // Broadly, we can fix the spin frequency -- that is, the % of contended lock
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1845 // acquisition attempts where we opt to spin -- at 100% and vary the spin count
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1846 // (duration) or we can fix the count at approximately the duration of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1847 // a context switch and vary the frequency. Of course we could also
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1848 // vary both satisfying K == Frequency * Duration, where K is adaptive by monitor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1849 // See http://j2se.east/~dice/PERSIST/040824-AdaptiveSpinning.html.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1850 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1851 // This implementation varies the duration "D", where D varies with
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1852 // the success rate of recent spin attempts. (D is capped at approximately
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1853 // length of a round-trip context switch). The success rate for recent
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1854 // spin attempts is a good predictor of the success rate of future spin
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1855 // attempts. The mechanism adapts automatically to varying critical
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1856 // section length (lock modality), system load and degree of parallelism.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1857 // D is maintained per-monitor in _SpinDuration and is initialized
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1858 // optimistically. Spin frequency is fixed at 100%.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1859 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1860 // Note that _SpinDuration is volatile, but we update it without locks
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1861 // or atomics. The code is designed so that _SpinDuration stays within
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1862 // a reasonable range even in the presence of races. The arithmetic
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1863 // operations on _SpinDuration are closed over the domain of legal values,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1864 // so at worst a race will install and older but still legal value.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1865 // At the very worst this introduces some apparent non-determinism.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1866 // We might spin when we shouldn't or vice-versa, but since the spin
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1867 // count are relatively short, even in the worst case, the effect is harmless.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1868 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1869 // Care must be taken that a low "D" value does not become an
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1870 // an absorbing state. Transient spinning failures -- when spinning
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1871 // is overall profitable -- should not cause the system to converge
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1872 // on low "D" values. We want spinning to be stable and predictable
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1873 // and fairly responsive to change and at the same time we don't want
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1874 // it to oscillate, become metastable, be "too" non-deterministic,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1875 // or converge on or enter undesirable stable absorbing states.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1876 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1877 // We implement a feedback-based control system -- using past behavior
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1878 // to predict future behavior. We face two issues: (a) if the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1879 // input signal is random then the spin predictor won't provide optimal
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1880 // results, and (b) if the signal frequency is too high then the control
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1881 // system, which has some natural response lag, will "chase" the signal.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1882 // (b) can arise from multimodal lock hold times. Transient preemption
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1883 // can also result in apparent bimodal lock hold times.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1884 // Although sub-optimal, neither condition is particularly harmful, as
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1885 // in the worst-case we'll spin when we shouldn't or vice-versa.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1886 // The maximum spin duration is rather short so the failure modes aren't bad.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1887 // To be conservative, I've tuned the gain in system to bias toward
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1888 // _not spinning. Relatedly, the system can sometimes enter a mode where it
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1889 // "rings" or oscillates between spinning and not spinning. This happens
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1890 // when spinning is just on the cusp of profitability, however, so the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1891 // situation is not dire. The state is benign -- there's no need to add
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1892 // hysteresis control to damp the transition rate between spinning and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1893 // not spinning.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1894 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1895
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1896 intptr_t ObjectMonitor::SpinCallbackArgument = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1897 int (*ObjectMonitor::SpinCallbackFunction)(intptr_t, int) = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1898
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1899 // Spinning: Fixed frequency (100%), vary duration
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1900
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1901
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1902 int ObjectMonitor::TrySpin_VaryDuration (Thread * Self) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1903
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1904 // Dumb, brutal spin. Good for comparative measurements against adaptive spinning.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1905 int ctr = Knob_FixedSpin ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1906 if (ctr != 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1907 while (--ctr >= 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1908 if (TryLock (Self) > 0) return 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1909 SpinPause () ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1910 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1911 return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1912 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1913
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1914 for (ctr = Knob_PreSpin + 1; --ctr >= 0 ; ) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1915 if (TryLock(Self) > 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1916 // Increase _SpinDuration ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1917 // Note that we don't clamp SpinDuration precisely at SpinLimit.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1918 // Raising _SpurDuration to the poverty line is key.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1919 int x = _SpinDuration ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1920 if (x < Knob_SpinLimit) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1921 if (x < Knob_Poverty) x = Knob_Poverty ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1922 _SpinDuration = x + Knob_BonusB ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1923 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1924 return 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1925 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1926 SpinPause () ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1927 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1928
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1929 // Admission control - verify preconditions for spinning
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1930 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1931 // We always spin a little bit, just to prevent _SpinDuration == 0 from
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1932 // becoming an absorbing state. Put another way, we spin briefly to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1933 // sample, just in case the system load, parallelism, contention, or lock
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1934 // modality changed.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1935 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1936 // Consider the following alternative:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1937 // Periodically set _SpinDuration = _SpinLimit and try a long/full
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1938 // spin attempt. "Periodically" might mean after a tally of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1939 // the # of failed spin attempts (or iterations) reaches some threshold.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1940 // This takes us into the realm of 1-out-of-N spinning, where we
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1941 // hold the duration constant but vary the frequency.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1942
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1943 ctr = _SpinDuration ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1944 if (ctr < Knob_SpinBase) ctr = Knob_SpinBase ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1945 if (ctr <= 0) return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1946
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1947 if (Knob_SuccRestrict && _succ != NULL) return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1948 if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1949 TEVENT (Spin abort - notrunnable [TOP]);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1950 return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1951 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1952
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1953 int MaxSpin = Knob_MaxSpinners ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1954 if (MaxSpin >= 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1955 if (_Spinner > MaxSpin) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1956 TEVENT (Spin abort -- too many spinners) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1957 return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1958 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1959 // Slighty racy, but benign ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1960 Adjust (&_Spinner, 1) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1961 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1962
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1963 // We're good to spin ... spin ingress.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1964 // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1965 // when preparing to LD...CAS _owner, etc and the CAS is likely
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1966 // to succeed.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1967 int hits = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1968 int msk = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1969 int caspty = Knob_CASPenalty ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1970 int oxpty = Knob_OXPenalty ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1971 int sss = Knob_SpinSetSucc ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1972 if (sss && _succ == NULL ) _succ = Self ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1973 Thread * prv = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1974
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1975 // There are three ways to exit the following loop:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1976 // 1. A successful spin where this thread has acquired the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1977 // 2. Spin failure with prejudice
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1978 // 3. Spin failure without prejudice
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1979
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1980 while (--ctr >= 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1981
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1982 // Periodic polling -- Check for pending GC
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1983 // Threads may spin while they're unsafe.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1984 // We don't want spinning threads to delay the JVM from reaching
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1985 // a stop-the-world safepoint or to steal cycles from GC.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1986 // If we detect a pending safepoint we abort in order that
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1987 // (a) this thread, if unsafe, doesn't delay the safepoint, and (b)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1988 // this thread, if safe, doesn't steal cycles from GC.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1989 // This is in keeping with the "no loitering in runtime" rule.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1990 // We periodically check to see if there's a safepoint pending.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1991 if ((ctr & 0xFF) == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1992 if (SafepointSynchronize::do_call_back()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1993 TEVENT (Spin: safepoint) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1994 goto Abort ; // abrupt spin egress
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1995 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1996 if (Knob_UsePause & 1) SpinPause () ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1997
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1998 int (*scb)(intptr_t,int) = SpinCallbackFunction ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
1999 if (hits > 50 && scb != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2000 int abend = (*scb)(SpinCallbackArgument, 0) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2001 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2002 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2003
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2004 if (Knob_UsePause & 2) SpinPause() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2005
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2006 // Exponential back-off ... Stay off the bus to reduce coherency traffic.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2007 // This is useful on classic SMP systems, but is of less utility on
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2008 // N1-style CMT platforms.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2009 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2010 // Trade-off: lock acquisition latency vs coherency bandwidth.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2011 // Lock hold times are typically short. A histogram
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2012 // of successful spin attempts shows that we usually acquire
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2013 // the lock early in the spin. That suggests we want to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2014 // sample _owner frequently in the early phase of the spin,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2015 // but then back-off and sample less frequently as the spin
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2016 // progresses. The back-off makes a good citizen on SMP big
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2017 // SMP systems. Oversampling _owner can consume excessive
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2018 // coherency bandwidth. Relatedly, if we _oversample _owner we
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2019 // can inadvertently interfere with the the ST m->owner=null.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2020 // executed by the lock owner.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2021 if (ctr & msk) continue ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2022 ++hits ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2023 if ((hits & 0xF) == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2024 // The 0xF, above, corresponds to the exponent.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2025 // Consider: (msk+1)|msk
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2026 msk = ((msk << 2)|3) & BackOffMask ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2027 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2028
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2029 // Probe _owner with TATAS
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2030 // If this thread observes the monitor transition or flicker
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2031 // from locked to unlocked to locked, then the odds that this
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2032 // thread will acquire the lock in this spin attempt go down
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2033 // considerably. The same argument applies if the CAS fails
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2034 // or if we observe _owner change from one non-null value to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2035 // another non-null value. In such cases we might abort
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2036 // the spin without prejudice or apply a "penalty" to the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2037 // spin count-down variable "ctr", reducing it by 100, say.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2038
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2039 Thread * ox = (Thread *) _owner ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2040 if (ox == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2041 ox = (Thread *) Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2042 if (ox == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2043 // The CAS succeeded -- this thread acquired ownership
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2044 // Take care of some bookkeeping to exit spin state.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2045 if (sss && _succ == Self) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2046 _succ = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2047 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2048 if (MaxSpin > 0) Adjust (&_Spinner, -1) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2049
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2050 // Increase _SpinDuration :
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2051 // The spin was successful (profitable) so we tend toward
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2052 // longer spin attempts in the future.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2053 // CONSIDER: factor "ctr" into the _SpinDuration adjustment.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2054 // If we acquired the lock early in the spin cycle it
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2055 // makes sense to increase _SpinDuration proportionally.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2056 // Note that we don't clamp SpinDuration precisely at SpinLimit.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2057 int x = _SpinDuration ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2058 if (x < Knob_SpinLimit) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2059 if (x < Knob_Poverty) x = Knob_Poverty ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2060 _SpinDuration = x + Knob_Bonus ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2061 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2062 return 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2063 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2064
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2065 // The CAS failed ... we can take any of the following actions:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2066 // * penalize: ctr -= Knob_CASPenalty
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2067 // * exit spin with prejudice -- goto Abort;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2068 // * exit spin without prejudice.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2069 // * Since CAS is high-latency, retry again immediately.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2070 prv = ox ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2071 TEVENT (Spin: cas failed) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2072 if (caspty == -2) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2073 if (caspty == -1) goto Abort ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2074 ctr -= caspty ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2075 continue ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2076 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2077
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2078 // Did lock ownership change hands ?
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2079 if (ox != prv && prv != NULL ) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2080 TEVENT (spin: Owner changed)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2081 if (oxpty == -2) break ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2082 if (oxpty == -1) goto Abort ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2083 ctr -= oxpty ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2084 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2085 prv = ox ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2086
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2087 // Abort the spin if the owner is not executing.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2088 // The owner must be executing in order to drop the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2089 // Spinning while the owner is OFFPROC is idiocy.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2090 // Consider: ctr -= RunnablePenalty ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2091 if (Knob_OState && NotRunnable (Self, ox)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2092 TEVENT (Spin abort - notrunnable);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2093 goto Abort ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2094 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2095 if (sss && _succ == NULL ) _succ = Self ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2096 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2097
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2098 // Spin failed with prejudice -- reduce _SpinDuration.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2099 // TODO: Use an AIMD-like policy to adjust _SpinDuration.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2100 // AIMD is globally stable.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2101 TEVENT (Spin failure) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2102 {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2103 int x = _SpinDuration ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2104 if (x > 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2105 // Consider an AIMD scheme like: x -= (x >> 3) + 100
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2106 // This is globally sample and tends to damp the response.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2107 x -= Knob_Penalty ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2108 if (x < 0) x = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2109 _SpinDuration = x ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2110 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2111 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2112
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2113 Abort:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2114 if (MaxSpin >= 0) Adjust (&_Spinner, -1) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2115 if (sss && _succ == Self) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2116 _succ = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2117 // Invariant: after setting succ=null a contending thread
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2118 // must recheck-retry _owner before parking. This usually happens
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2119 // in the normal usage of TrySpin(), but it's safest
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2120 // to make TrySpin() as foolproof as possible.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2121 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2122 if (TryLock(Self) > 0) return 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2123 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2124 return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2125 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2126
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2127 // NotRunnable() -- informed spinning
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2128 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2129 // Don't bother spinning if the owner is not eligible to drop the lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2130 // Peek at the owner's schedctl.sc_state and Thread._thread_values and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2131 // spin only if the owner thread is _thread_in_Java or _thread_in_vm.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2132 // The thread must be runnable in order to drop the lock in timely fashion.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2133 // If the _owner is not runnable then spinning will not likely be
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2134 // successful (profitable).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2135 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2136 // Beware -- the thread referenced by _owner could have died
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2137 // so a simply fetch from _owner->_thread_state might trap.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2138 // Instead, we use SafeFetchXX() to safely LD _owner->_thread_state.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2139 // Because of the lifecycle issues the schedctl and _thread_state values
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2140 // observed by NotRunnable() might be garbage. NotRunnable must
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2141 // tolerate this and consider the observed _thread_state value
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2142 // as advisory.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2143 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2144 // Beware too, that _owner is sometimes a BasicLock address and sometimes
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2145 // a thread pointer. We differentiate the two cases with OwnerIsThread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2146 // Alternately, we might tag the type (thread pointer vs basiclock pointer)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2147 // with the LSB of _owner. Another option would be to probablistically probe
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2148 // the putative _owner->TypeTag value.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2149 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2150 // Checking _thread_state isn't perfect. Even if the thread is
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2151 // in_java it might be blocked on a page-fault or have been preempted
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2152 // and sitting on a ready/dispatch queue. _thread state in conjunction
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2153 // with schedctl.sc_state gives us a good picture of what the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2154 // thread is doing, however.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2155 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2156 // TODO: check schedctl.sc_state.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2157 // We'll need to use SafeFetch32() to read from the schedctl block.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2158 // See RFE #5004247 and http://sac.sfbay.sun.com/Archives/CaseLog/arc/PSARC/2005/351/
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2159 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2160 // The return value from NotRunnable() is *advisory* -- the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2161 // result is based on sampling and is not necessarily coherent.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2162 // The caller must tolerate false-negative and false-positive errors.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2163 // Spinning, in general, is probabilistic anyway.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2164
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2165
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2166 int ObjectMonitor::NotRunnable (Thread * Self, Thread * ox) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2167 // Check either OwnerIsThread or ox->TypeTag == 2BAD.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2168 if (!OwnerIsThread) return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2169
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2170 if (ox == NULL) return 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2171
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2172 // Avoid transitive spinning ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2173 // Say T1 spins or blocks trying to acquire L. T1._Stalled is set to L.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2174 // Immediately after T1 acquires L it's possible that T2, also
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2175 // spinning on L, will see L.Owner=T1 and T1._Stalled=L.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2176 // This occurs transiently after T1 acquired L but before
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2177 // T1 managed to clear T1.Stalled. T2 does not need to abort
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2178 // its spin in this circumstance.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2179 intptr_t BlockedOn = SafeFetchN ((intptr_t *) &ox->_Stalled, intptr_t(1)) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2180
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2181 if (BlockedOn == 1) return 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2182 if (BlockedOn != 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2183 return BlockedOn != intptr_t(this) && _owner == ox ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2184 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2185
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2186 assert (sizeof(((JavaThread *)ox)->_thread_state == sizeof(int)), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2187 int jst = SafeFetch32 ((int *) &((JavaThread *) ox)->_thread_state, -1) ; ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2188 // consider also: jst != _thread_in_Java -- but that's overspecific.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2189 return jst == _thread_blocked || jst == _thread_in_native ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2190 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2191
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2192
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2193 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2194 // WaitSet management ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2195
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2196 ObjectWaiter::ObjectWaiter(Thread* thread) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2197 _next = NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2198 _prev = NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2199 _notified = 0;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2200 TState = TS_RUN ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2201 _thread = thread;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2202 _event = thread->_ParkEvent ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2203 _active = false;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2204 assert (_event != NULL, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2205 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2206
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2207 void ObjectWaiter::wait_reenter_begin(ObjectMonitor *mon) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2208 JavaThread *jt = (JavaThread *)this->_thread;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2209 _active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2210 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2211
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2212 void ObjectWaiter::wait_reenter_end(ObjectMonitor *mon) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2213 JavaThread *jt = (JavaThread *)this->_thread;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2214 JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2215 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2216
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2217 inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2218 assert(node != NULL, "should not dequeue NULL node");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2219 assert(node->_prev == NULL, "node already in list");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2220 assert(node->_next == NULL, "node already in list");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2221 // put node at end of queue (circular doubly linked list)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2222 if (_WaitSet == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2223 _WaitSet = node;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2224 node->_prev = node;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2225 node->_next = node;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2226 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2227 ObjectWaiter* head = _WaitSet ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2228 ObjectWaiter* tail = head->_prev;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2229 assert(tail->_next == head, "invariant check");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2230 tail->_next = node;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2231 head->_prev = node;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2232 node->_next = head;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2233 node->_prev = tail;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2234 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2235 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2236
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2237 inline ObjectWaiter* ObjectMonitor::DequeueWaiter() {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2238 // dequeue the very first waiter
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2239 ObjectWaiter* waiter = _WaitSet;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2240 if (waiter) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2241 DequeueSpecificWaiter(waiter);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2242 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2243 return waiter;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2244 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2245
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2246 inline void ObjectMonitor::DequeueSpecificWaiter(ObjectWaiter* node) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2247 assert(node != NULL, "should not dequeue NULL node");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2248 assert(node->_prev != NULL, "node already removed from list");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2249 assert(node->_next != NULL, "node already removed from list");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2250 // when the waiter has woken up because of interrupt,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2251 // timeout or other spurious wake-up, dequeue the
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2252 // waiter from waiting list
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2253 ObjectWaiter* next = node->_next;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2254 if (next == node) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2255 assert(node->_prev == node, "invariant check");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2256 _WaitSet = NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2257 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2258 ObjectWaiter* prev = node->_prev;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2259 assert(prev->_next == node, "invariant check");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2260 assert(next->_prev == node, "invariant check");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2261 next->_prev = prev;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2262 prev->_next = next;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2263 if (_WaitSet == node) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2264 _WaitSet = next;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2265 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2266 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2267 node->_next = NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2268 node->_prev = NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2269 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2270
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2271 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2272 // PerfData support
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2273 PerfCounter * ObjectMonitor::_sync_ContendedLockAttempts = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2274 PerfCounter * ObjectMonitor::_sync_FutileWakeups = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2275 PerfCounter * ObjectMonitor::_sync_Parks = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2276 PerfCounter * ObjectMonitor::_sync_EmptyNotifications = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2277 PerfCounter * ObjectMonitor::_sync_Notifications = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2278 PerfCounter * ObjectMonitor::_sync_PrivateA = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2279 PerfCounter * ObjectMonitor::_sync_PrivateB = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2280 PerfCounter * ObjectMonitor::_sync_SlowExit = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2281 PerfCounter * ObjectMonitor::_sync_SlowEnter = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2282 PerfCounter * ObjectMonitor::_sync_SlowNotify = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2283 PerfCounter * ObjectMonitor::_sync_SlowNotifyAll = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2284 PerfCounter * ObjectMonitor::_sync_FailedSpins = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2285 PerfCounter * ObjectMonitor::_sync_SuccessfulSpins = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2286 PerfCounter * ObjectMonitor::_sync_MonInCirculation = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2287 PerfCounter * ObjectMonitor::_sync_MonScavenged = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2288 PerfCounter * ObjectMonitor::_sync_Inflations = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2289 PerfCounter * ObjectMonitor::_sync_Deflations = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2290 PerfLongVariable * ObjectMonitor::_sync_MonExtant = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2291
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2292 // One-shot global initialization for the sync subsystem.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2293 // We could also defer initialization and initialize on-demand
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2294 // the first time we call inflate(). Initialization would
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2295 // be protected - like so many things - by the MonitorCache_lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2296
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2297 void ObjectMonitor::Initialize () {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2298 static int InitializationCompleted = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2299 assert (InitializationCompleted == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2300 InitializationCompleted = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2301 if (UsePerfData) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2302 EXCEPTION_MARK ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2303 #define NEWPERFCOUNTER(n) {n = PerfDataManager::create_counter(SUN_RT, #n, PerfData::U_Events,CHECK); }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2304 #define NEWPERFVARIABLE(n) {n = PerfDataManager::create_variable(SUN_RT, #n, PerfData::U_Events,CHECK); }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2305 NEWPERFCOUNTER(_sync_Inflations) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2306 NEWPERFCOUNTER(_sync_Deflations) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2307 NEWPERFCOUNTER(_sync_ContendedLockAttempts) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2308 NEWPERFCOUNTER(_sync_FutileWakeups) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2309 NEWPERFCOUNTER(_sync_Parks) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2310 NEWPERFCOUNTER(_sync_EmptyNotifications) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2311 NEWPERFCOUNTER(_sync_Notifications) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2312 NEWPERFCOUNTER(_sync_SlowEnter) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2313 NEWPERFCOUNTER(_sync_SlowExit) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2314 NEWPERFCOUNTER(_sync_SlowNotify) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2315 NEWPERFCOUNTER(_sync_SlowNotifyAll) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2316 NEWPERFCOUNTER(_sync_FailedSpins) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2317 NEWPERFCOUNTER(_sync_SuccessfulSpins) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2318 NEWPERFCOUNTER(_sync_PrivateA) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2319 NEWPERFCOUNTER(_sync_PrivateB) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2320 NEWPERFCOUNTER(_sync_MonInCirculation) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2321 NEWPERFCOUNTER(_sync_MonScavenged) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2322 NEWPERFVARIABLE(_sync_MonExtant) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2323 #undef NEWPERFCOUNTER
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2324 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2325 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2326
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2327
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2328 // Compile-time asserts
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2329 // When possible, it's better to catch errors deterministically at
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2330 // compile-time than at runtime. The down-side to using compile-time
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2331 // asserts is that error message -- often something about negative array
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2332 // indices -- is opaque.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2333
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2334 #define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @" INTPTR_FORMAT "\n", (intptr_t)tag); }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2335
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2336 void ObjectMonitor::ctAsserts() {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2337 CTASSERT(offset_of (ObjectMonitor, _header) == 0);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2338 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2339
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2340
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2341 static char * kvGet (char * kvList, const char * Key) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2342 if (kvList == NULL) return NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2343 size_t n = strlen (Key) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2344 char * Search ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2345 for (Search = kvList ; *Search ; Search += strlen(Search) + 1) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2346 if (strncmp (Search, Key, n) == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2347 if (Search[n] == '=') return Search + n + 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2348 if (Search[n] == 0) return (char *) "1" ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2349 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2350 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2351 return NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2352 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2353
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2354 static int kvGetInt (char * kvList, const char * Key, int Default) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2355 char * v = kvGet (kvList, Key) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2356 int rslt = v ? ::strtol (v, NULL, 0) : Default ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2357 if (Knob_ReportSettings && v != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2358 ::printf (" SyncKnob: %s %d(%d)\n", Key, rslt, Default) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2359 ::fflush (stdout) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2360 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2361 return rslt ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2362 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2363
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2364 void ObjectMonitor::DeferredInitialize () {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2365 if (InitDone > 0) return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2366 if (Atomic::cmpxchg (-1, &InitDone, 0) != 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2367 while (InitDone != 1) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2368 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2369 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2370
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2371 // One-shot global initialization ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2372 // The initialization is idempotent, so we don't need locks.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2373 // In the future consider doing this via os::init_2().
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2374 // SyncKnobs consist of <Key>=<Value> pairs in the style
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2375 // of environment variables. Start by converting ':' to NUL.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2376
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2377 if (SyncKnobs == NULL) SyncKnobs = "" ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2378
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2379 size_t sz = strlen (SyncKnobs) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2380 char * knobs = (char *) malloc (sz + 2) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2381 if (knobs == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2382 vm_exit_out_of_memory (sz + 2, "Parse SyncKnobs") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2383 guarantee (0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2384 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2385 strcpy (knobs, SyncKnobs) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2386 knobs[sz+1] = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2387 for (char * p = knobs ; *p ; p++) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2388 if (*p == ':') *p = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2389 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2390
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2391 #define SETKNOB(x) { Knob_##x = kvGetInt (knobs, #x, Knob_##x); }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2392 SETKNOB(ReportSettings) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2393 SETKNOB(Verbose) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2394 SETKNOB(FixedSpin) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2395 SETKNOB(SpinLimit) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2396 SETKNOB(SpinBase) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2397 SETKNOB(SpinBackOff);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2398 SETKNOB(CASPenalty) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2399 SETKNOB(OXPenalty) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2400 SETKNOB(LogSpins) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2401 SETKNOB(SpinSetSucc) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2402 SETKNOB(SuccEnabled) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2403 SETKNOB(SuccRestrict) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2404 SETKNOB(Penalty) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2405 SETKNOB(Bonus) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2406 SETKNOB(BonusB) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2407 SETKNOB(Poverty) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2408 SETKNOB(SpinAfterFutile) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2409 SETKNOB(UsePause) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2410 SETKNOB(SpinEarly) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2411 SETKNOB(OState) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2412 SETKNOB(MaxSpinners) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2413 SETKNOB(PreSpin) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2414 SETKNOB(ExitPolicy) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2415 SETKNOB(QMode);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2416 SETKNOB(ResetEvent) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2417 SETKNOB(MoveNotifyee) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2418 SETKNOB(FastHSSEC) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2419 #undef SETKNOB
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2420
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2421 if (os::is_MP()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2422 BackOffMask = (1 << Knob_SpinBackOff) - 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2423 if (Knob_ReportSettings) ::printf ("BackOffMask=%X\n", BackOffMask) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2424 // CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2425 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2426 Knob_SpinLimit = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2427 Knob_SpinBase = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2428 Knob_PreSpin = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2429 Knob_FixedSpin = -1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2430 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2431
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2432 if (Knob_LogSpins == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2433 ObjectMonitor::_sync_FailedSpins = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2434 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2435
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2436 free (knobs) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2437 OrderAccess::fence() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2438 InitDone = 1 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2439 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2440
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2441 #ifndef PRODUCT
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2442 void ObjectMonitor::verify() {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2443 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2444
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2445 void ObjectMonitor::print() {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2446 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents:
diff changeset
2447 #endif