author | pliden |
Thu, 17 Mar 2016 08:07:53 +0100 | |
changeset 37129 | af29e306e50b |
parent 35217 | ce4b5303a813 |
child 40892 | 330a02d935ad |
permissions | -rw-r--r-- |
1 | 1 |
/* |
37129
af29e306e50b
8151601: Cleanup locking of the Reference pending list
pliden
parents:
35217
diff
changeset
|
2 |
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. |
1 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. |
|
8 |
* |
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
13 |
* accompanied this code). |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License version |
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 |
* |
|
5547
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3261
diff
changeset
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3261
diff
changeset
|
20 |
* or visit www.oracle.com if you need additional information or have any |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3261
diff
changeset
|
21 |
* questions. |
1 | 22 |
* |
23 |
*/ |
|
24 |
||
25 |
package sun.jvm.hotspot.runtime; |
|
26 |
||
27 |
import java.util.*; |
|
28369 | 28 |
|
1 | 29 |
import sun.jvm.hotspot.debugger.*; |
30 |
import sun.jvm.hotspot.types.*; |
|
31 |
import sun.jvm.hotspot.runtime.solaris_sparc.SolarisSPARCJavaThreadPDAccess; |
|
32 |
import sun.jvm.hotspot.runtime.solaris_x86.SolarisX86JavaThreadPDAccess; |
|
33 |
import sun.jvm.hotspot.runtime.solaris_amd64.SolarisAMD64JavaThreadPDAccess; |
|
34 |
import sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess; |
|
35 |
import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess; |
|
36 |
import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess; |
|
37 |
import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess; |
|
31399 | 38 |
import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess; |
28369 | 39 |
import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess; |
1 | 40 |
import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess; |
10565 | 41 |
import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess; |
42 |
import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess; |
|
1 | 43 |
import sun.jvm.hotspot.utilities.*; |
44 |
||
45 |
public class Threads { |
|
46 |
private static JavaThreadFactory threadFactory; |
|
47 |
private static AddressField threadListField; |
|
16351 | 48 |
private static CIntegerField numOfThreadsField; |
1 | 49 |
private static VirtualConstructor virtualConstructor; |
50 |
private static JavaThreadPDAccess access; |
|
51 |
||
52 |
static { |
|
53 |
VM.registerVMInitializedObserver(new Observer() { |
|
54 |
public void update(Observable o, Object data) { |
|
55 |
initialize(VM.getVM().getTypeDataBase()); |
|
56 |
} |
|
57 |
}); |
|
58 |
} |
|
59 |
||
60 |
private static synchronized void initialize(TypeDataBase db) { |
|
61 |
Type type = db.lookupType("Threads"); |
|
62 |
||
63 |
threadListField = type.getAddressField("_thread_list"); |
|
16351 | 64 |
numOfThreadsField = type.getCIntegerField("_number_of_threads"); |
1 | 65 |
|
66 |
// Instantiate appropriate platform-specific JavaThreadFactory |
|
67 |
String os = VM.getVM().getOS(); |
|
68 |
String cpu = VM.getVM().getCPU(); |
|
69 |
||
70 |
access = null; |
|
71 |
// FIXME: find the platform specific PD class by reflection? |
|
72 |
if (os.equals("solaris")) { |
|
73 |
if (cpu.equals("sparc")) { |
|
74 |
access = new SolarisSPARCJavaThreadPDAccess(); |
|
75 |
} else if (cpu.equals("x86")) { |
|
76 |
access = new SolarisX86JavaThreadPDAccess(); |
|
77 |
} else if (cpu.equals("amd64")) { |
|
78 |
access = new SolarisAMD64JavaThreadPDAccess(); |
|
79 |
} |
|
80 |
} else if (os.equals("win32")) { |
|
81 |
if (cpu.equals("x86")) { |
|
82 |
access = new Win32X86JavaThreadPDAccess(); |
|
83 |
} else if (cpu.equals("amd64")) { |
|
84 |
access = new Win32AMD64JavaThreadPDAccess(); |
|
85 |
} |
|
86 |
} else if (os.equals("linux")) { |
|
87 |
if (cpu.equals("x86")) { |
|
88 |
access = new LinuxX86JavaThreadPDAccess(); |
|
89 |
} else if (cpu.equals("amd64")) { |
|
90 |
access = new LinuxAMD64JavaThreadPDAccess(); |
|
91 |
} else if (cpu.equals("sparc")) { |
|
92 |
access = new LinuxSPARCJavaThreadPDAccess(); |
|
28369 | 93 |
} else if (cpu.equals("ppc64")) { |
94 |
access = new LinuxPPC64JavaThreadPDAccess(); |
|
31399 | 95 |
} else if (cpu.equals("aarch64")) { |
96 |
access = new LinuxAARCH64JavaThreadPDAccess(); |
|
13529
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
97 |
} else { |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
98 |
try { |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
99 |
access = (JavaThreadPDAccess) |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
100 |
Class.forName("sun.jvm.hotspot.runtime.linux_" + |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
101 |
cpu.toLowerCase() + ".Linux" + cpu.toUpperCase() + |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
102 |
"JavaThreadPDAccess").newInstance(); |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
103 |
} catch (Exception e) { |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
104 |
throw new RuntimeException("OS/CPU combination " + os + "/" + cpu + |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
105 |
" not yet supported"); |
dc25e69fd16d
7154641: Servicability agent should work on platforms other than x86, sparc
bpittore
parents:
12728
diff
changeset
|
106 |
} |
1 | 107 |
} |
10565 | 108 |
} else if (os.equals("bsd")) { |
109 |
if (cpu.equals("x86")) { |
|
110 |
access = new BsdX86JavaThreadPDAccess(); |
|
12728
a8abd64eaa1b
7163117: Agent can't connect to process on Mac OSX
nloodin
parents:
10565
diff
changeset
|
111 |
} else if (cpu.equals("amd64") || cpu.equals("x86_64")) { |
10565 | 112 |
access = new BsdAMD64JavaThreadPDAccess(); |
113 |
} |
|
16351 | 114 |
} else if (os.equals("darwin")) { |
115 |
if (cpu.equals("amd64") || cpu.equals("x86_64")) { |
|
116 |
access = new BsdAMD64JavaThreadPDAccess(); |
|
117 |
} |
|
1 | 118 |
} |
119 |
||
120 |
if (access == null) { |
|
121 |
throw new RuntimeException("OS/CPU combination " + os + "/" + cpu + |
|
122 |
" not yet supported"); |
|
123 |
} |
|
124 |
||
125 |
virtualConstructor = new VirtualConstructor(db); |
|
126 |
// Add mappings for all known thread types |
|
127 |
virtualConstructor.addMapping("JavaThread", JavaThread.class); |
|
128 |
if (!VM.getVM().isCore()) { |
|
129 |
virtualConstructor.addMapping("CompilerThread", CompilerThread.class); |
|
27475 | 130 |
virtualConstructor.addMapping("CodeCacheSweeperThread", CodeCacheSweeperThread.class); |
1 | 131 |
} |
132 |
// for now, use JavaThread itself. fix it later with appropriate class if needed |
|
37129
af29e306e50b
8151601: Cleanup locking of the Reference pending list
pliden
parents:
35217
diff
changeset
|
133 |
virtualConstructor.addMapping("ReferencePendingListLockerThread", JavaThread.class); |
1 | 134 |
virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class); |
8110
c992c8d52344
6766644: Redefinition of compiled method fails with assertion "Can not load classes with the Compiler thread"
kamg
parents:
5547
diff
changeset
|
135 |
virtualConstructor.addMapping("ServiceThread", ServiceThread.class); |
1 | 136 |
} |
137 |
||
138 |
public Threads() { |
|
139 |
} |
|
140 |
||
141 |
/** NOTE: this returns objects of type JavaThread, CompilerThread, |
|
8110
c992c8d52344
6766644: Redefinition of compiled method fails with assertion "Can not load classes with the Compiler thread"
kamg
parents:
5547
diff
changeset
|
142 |
JvmtiAgentThread, and ServiceThread. |
1 | 143 |
The latter four are subclasses of the former. Most operations |
144 |
(fetching the top frame, etc.) are only allowed to be performed on |
|
145 |
a "pure" JavaThread. For this reason, {@link |
|
146 |
sun.jvm.hotspot.runtime.JavaThread#isJavaThread} has been |
|
147 |
changed from the definition in the VM (which returns true for |
|
148 |
all of these thread types) to return true for JavaThreads and |
|
149 |
false for the three subclasses. FIXME: should reconsider the |
|
150 |
inheritance hierarchy; see {@link |
|
151 |
sun.jvm.hotspot.runtime.JavaThread#isJavaThread}. */ |
|
152 |
public JavaThread first() { |
|
153 |
Address threadAddr = threadListField.getValue(); |
|
154 |
if (threadAddr == null) { |
|
155 |
return null; |
|
156 |
} |
|
157 |
||
158 |
return createJavaThreadWrapper(threadAddr); |
|
159 |
} |
|
160 |
||
16351 | 161 |
public int getNumberOfThreads() { |
162 |
return (int) numOfThreadsField.getValue(); |
|
163 |
} |
|
164 |
||
1 | 165 |
/** Routine for instantiating appropriately-typed wrapper for a |
166 |
JavaThread. Currently needs to be public for OopUtilities to |
|
167 |
access it. */ |
|
168 |
public JavaThread createJavaThreadWrapper(Address threadAddr) { |
|
169 |
try { |
|
170 |
JavaThread thread = (JavaThread)virtualConstructor.instantiateWrapperFor(threadAddr); |
|
171 |
thread.setThreadPDAccess(access); |
|
172 |
return thread; |
|
173 |
} catch (Exception e) { |
|
174 |
throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr + |
|
37129
af29e306e50b
8151601: Cleanup locking of the Reference pending list
pliden
parents:
35217
diff
changeset
|
175 |
" (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, ReferencePendingListLockerThread, or CodeCacheSweeperThread)", e); |
1 | 176 |
} |
177 |
} |
|
178 |
||
179 |
/** Memory operations */ |
|
180 |
public void oopsDo(AddressVisitor oopVisitor) { |
|
181 |
// FIXME: add more of VM functionality |
|
182 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
183 |
thread.oopsDo(oopVisitor); |
|
184 |
} |
|
185 |
} |
|
186 |
||
187 |
// refer to Threads::owning_thread_from_monitor_owner |
|
188 |
public JavaThread owningThreadFromMonitor(Address o) { |
|
189 |
if (o == null) return null; |
|
190 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
191 |
if (o.equals(thread.threadObjectAddress())) { |
|
192 |
return thread; |
|
193 |
} |
|
194 |
} |
|
195 |
||
196 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
2526
39a58a50be35
6699669: Hotspot server leaves synchronized block with monitor in bad state
xlu
parents:
1
diff
changeset
|
197 |
if (thread.isLockOwned(o)) |
39a58a50be35
6699669: Hotspot server leaves synchronized block with monitor in bad state
xlu
parents:
1
diff
changeset
|
198 |
return thread; |
1 | 199 |
} |
2526
39a58a50be35
6699669: Hotspot server leaves synchronized block with monitor in bad state
xlu
parents:
1
diff
changeset
|
200 |
return null; |
1 | 201 |
} |
202 |
||
203 |
public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) { |
|
204 |
return owningThreadFromMonitor(monitor.owner()); |
|
205 |
} |
|
206 |
||
207 |
// refer to Threads::get_pending_threads |
|
208 |
// Get list of Java threads that are waiting to enter the specified monitor. |
|
209 |
public List getPendingThreads(ObjectMonitor monitor) { |
|
210 |
List pendingThreads = new ArrayList(); |
|
211 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
27475 | 212 |
if (thread.isCompilerThread() || thread.isCodeCacheSweeperThread()) { |
1 | 213 |
continue; |
214 |
} |
|
215 |
ObjectMonitor pending = thread.getCurrentPendingMonitor(); |
|
216 |
if (monitor.equals(pending)) { |
|
217 |
pendingThreads.add(thread); |
|
218 |
} |
|
219 |
} |
|
220 |
return pendingThreads; |
|
221 |
} |
|
222 |
||
223 |
// Get list of Java threads that have called Object.wait on the specified monitor. |
|
224 |
public List getWaitingThreads(ObjectMonitor monitor) { |
|
225 |
List pendingThreads = new ArrayList(); |
|
226 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
227 |
ObjectMonitor waiting = thread.getCurrentWaitingMonitor(); |
|
228 |
if (monitor.equals(waiting)) { |
|
229 |
pendingThreads.add(thread); |
|
230 |
} |
|
231 |
} |
|
232 |
return pendingThreads; |
|
233 |
} |
|
234 |
||
235 |
// FIXME: add other accessors |
|
236 |
} |