annotate src/share/vm/runtime/objectMonitor.cpp @ 10292:acac2b03a07f

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