annotate src/share/vm/runtime/objectMonitor.cpp @ 6972:bd7a7ce2e264

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