author | xlu |
Mon, 06 Apr 2009 15:47:39 -0700 | |
changeset 2526 | 39a58a50be35 |
parent 1 | 489c9b5090e2 |
child 3261 | c7d5aae8d3f7 |
permissions | -rw-r--r-- |
1 | 1 |
/* |
2 |
* Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. |
|
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 |
* |
|
19 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 |
* have any questions. |
|
22 |
* |
|
23 |
*/ |
|
24 |
||
25 |
package sun.jvm.hotspot.runtime; |
|
26 |
||
27 |
import java.util.*; |
|
28 |
import sun.jvm.hotspot.debugger.*; |
|
29 |
import sun.jvm.hotspot.types.*; |
|
30 |
import sun.jvm.hotspot.runtime.solaris_sparc.SolarisSPARCJavaThreadPDAccess; |
|
31 |
import sun.jvm.hotspot.runtime.solaris_x86.SolarisX86JavaThreadPDAccess; |
|
32 |
import sun.jvm.hotspot.runtime.solaris_amd64.SolarisAMD64JavaThreadPDAccess; |
|
33 |
import sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess; |
|
34 |
import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess; |
|
35 |
import sun.jvm.hotspot.runtime.win32_ia64.Win32IA64JavaThreadPDAccess; |
|
36 |
import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess; |
|
37 |
import sun.jvm.hotspot.runtime.linux_ia64.LinuxIA64JavaThreadPDAccess; |
|
38 |
import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess; |
|
39 |
import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess; |
|
40 |
import sun.jvm.hotspot.utilities.*; |
|
41 |
||
42 |
public class Threads { |
|
43 |
private static JavaThreadFactory threadFactory; |
|
44 |
private static AddressField threadListField; |
|
45 |
private static VirtualConstructor virtualConstructor; |
|
46 |
private static JavaThreadPDAccess access; |
|
47 |
||
48 |
static { |
|
49 |
VM.registerVMInitializedObserver(new Observer() { |
|
50 |
public void update(Observable o, Object data) { |
|
51 |
initialize(VM.getVM().getTypeDataBase()); |
|
52 |
} |
|
53 |
}); |
|
54 |
} |
|
55 |
||
56 |
private static synchronized void initialize(TypeDataBase db) { |
|
57 |
Type type = db.lookupType("Threads"); |
|
58 |
||
59 |
threadListField = type.getAddressField("_thread_list"); |
|
60 |
||
61 |
// Instantiate appropriate platform-specific JavaThreadFactory |
|
62 |
String os = VM.getVM().getOS(); |
|
63 |
String cpu = VM.getVM().getCPU(); |
|
64 |
||
65 |
access = null; |
|
66 |
// FIXME: find the platform specific PD class by reflection? |
|
67 |
if (os.equals("solaris")) { |
|
68 |
if (cpu.equals("sparc")) { |
|
69 |
access = new SolarisSPARCJavaThreadPDAccess(); |
|
70 |
} else if (cpu.equals("x86")) { |
|
71 |
access = new SolarisX86JavaThreadPDAccess(); |
|
72 |
} else if (cpu.equals("amd64")) { |
|
73 |
access = new SolarisAMD64JavaThreadPDAccess(); |
|
74 |
} |
|
75 |
} else if (os.equals("win32")) { |
|
76 |
if (cpu.equals("x86")) { |
|
77 |
access = new Win32X86JavaThreadPDAccess(); |
|
78 |
} else if (cpu.equals("amd64")) { |
|
79 |
access = new Win32AMD64JavaThreadPDAccess(); |
|
80 |
} else if (cpu.equals("ia64")) { |
|
81 |
access = new Win32IA64JavaThreadPDAccess(); |
|
82 |
} |
|
83 |
} else if (os.equals("linux")) { |
|
84 |
if (cpu.equals("x86")) { |
|
85 |
access = new LinuxX86JavaThreadPDAccess(); |
|
86 |
} else if (cpu.equals("ia64")) { |
|
87 |
access = new LinuxIA64JavaThreadPDAccess(); |
|
88 |
} else if (cpu.equals("amd64")) { |
|
89 |
access = new LinuxAMD64JavaThreadPDAccess(); |
|
90 |
} else if (cpu.equals("sparc")) { |
|
91 |
access = new LinuxSPARCJavaThreadPDAccess(); |
|
92 |
} |
|
93 |
||
94 |
} |
|
95 |
||
96 |
if (access == null) { |
|
97 |
throw new RuntimeException("OS/CPU combination " + os + "/" + cpu + |
|
98 |
" not yet supported"); |
|
99 |
} |
|
100 |
||
101 |
virtualConstructor = new VirtualConstructor(db); |
|
102 |
// Add mappings for all known thread types |
|
103 |
virtualConstructor.addMapping("JavaThread", JavaThread.class); |
|
104 |
if (!VM.getVM().isCore()) { |
|
105 |
virtualConstructor.addMapping("CompilerThread", CompilerThread.class); |
|
106 |
} |
|
107 |
// for now, use JavaThread itself. fix it later with appropriate class if needed |
|
108 |
virtualConstructor.addMapping("SurrogateLockerThread", JavaThread.class); |
|
109 |
virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class); |
|
110 |
virtualConstructor.addMapping("LowMemoryDetectorThread", LowMemoryDetectorThread.class); |
|
111 |
} |
|
112 |
||
113 |
public Threads() { |
|
114 |
} |
|
115 |
||
116 |
/** NOTE: this returns objects of type JavaThread, CompilerThread, |
|
117 |
JvmtiAgentThread, and LowMemoryDetectorThread. |
|
118 |
The latter four are subclasses of the former. Most operations |
|
119 |
(fetching the top frame, etc.) are only allowed to be performed on |
|
120 |
a "pure" JavaThread. For this reason, {@link |
|
121 |
sun.jvm.hotspot.runtime.JavaThread#isJavaThread} has been |
|
122 |
changed from the definition in the VM (which returns true for |
|
123 |
all of these thread types) to return true for JavaThreads and |
|
124 |
false for the three subclasses. FIXME: should reconsider the |
|
125 |
inheritance hierarchy; see {@link |
|
126 |
sun.jvm.hotspot.runtime.JavaThread#isJavaThread}. */ |
|
127 |
public JavaThread first() { |
|
128 |
Address threadAddr = threadListField.getValue(); |
|
129 |
if (threadAddr == null) { |
|
130 |
return null; |
|
131 |
} |
|
132 |
||
133 |
return createJavaThreadWrapper(threadAddr); |
|
134 |
} |
|
135 |
||
136 |
/** Routine for instantiating appropriately-typed wrapper for a |
|
137 |
JavaThread. Currently needs to be public for OopUtilities to |
|
138 |
access it. */ |
|
139 |
public JavaThread createJavaThreadWrapper(Address threadAddr) { |
|
140 |
try { |
|
141 |
JavaThread thread = (JavaThread)virtualConstructor.instantiateWrapperFor(threadAddr); |
|
142 |
thread.setThreadPDAccess(access); |
|
143 |
return thread; |
|
144 |
} catch (Exception e) { |
|
145 |
throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr + |
|
146 |
" (expected type JavaThread, CompilerThread, LowMemoryDetectorThread, JvmtiAgentThread, or SurrogateLockerThread)", e); |
|
147 |
} |
|
148 |
} |
|
149 |
||
150 |
/** Memory operations */ |
|
151 |
public void oopsDo(AddressVisitor oopVisitor) { |
|
152 |
// FIXME: add more of VM functionality |
|
153 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
154 |
thread.oopsDo(oopVisitor); |
|
155 |
} |
|
156 |
} |
|
157 |
||
158 |
// refer to Threads::owning_thread_from_monitor_owner |
|
159 |
public JavaThread owningThreadFromMonitor(Address o) { |
|
160 |
if (o == null) return null; |
|
161 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
162 |
if (o.equals(thread.threadObjectAddress())) { |
|
163 |
return thread; |
|
164 |
} |
|
165 |
} |
|
166 |
||
167 |
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
|
168 |
if (thread.isLockOwned(o)) |
39a58a50be35
6699669: Hotspot server leaves synchronized block with monitor in bad state
xlu
parents:
1
diff
changeset
|
169 |
return thread; |
1 | 170 |
} |
2526
39a58a50be35
6699669: Hotspot server leaves synchronized block with monitor in bad state
xlu
parents:
1
diff
changeset
|
171 |
return null; |
1 | 172 |
} |
173 |
||
174 |
public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) { |
|
175 |
return owningThreadFromMonitor(monitor.owner()); |
|
176 |
} |
|
177 |
||
178 |
// refer to Threads::get_pending_threads |
|
179 |
// Get list of Java threads that are waiting to enter the specified monitor. |
|
180 |
public List getPendingThreads(ObjectMonitor monitor) { |
|
181 |
List pendingThreads = new ArrayList(); |
|
182 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
183 |
if (thread.isCompilerThread()) { |
|
184 |
continue; |
|
185 |
} |
|
186 |
ObjectMonitor pending = thread.getCurrentPendingMonitor(); |
|
187 |
if (monitor.equals(pending)) { |
|
188 |
pendingThreads.add(thread); |
|
189 |
} |
|
190 |
} |
|
191 |
return pendingThreads; |
|
192 |
} |
|
193 |
||
194 |
// Get list of Java threads that have called Object.wait on the specified monitor. |
|
195 |
public List getWaitingThreads(ObjectMonitor monitor) { |
|
196 |
List pendingThreads = new ArrayList(); |
|
197 |
for (JavaThread thread = first(); thread != null; thread = thread.next()) { |
|
198 |
ObjectMonitor waiting = thread.getCurrentWaitingMonitor(); |
|
199 |
if (monitor.equals(waiting)) { |
|
200 |
pendingThreads.add(thread); |
|
201 |
} |
|
202 |
} |
|
203 |
return pendingThreads; |
|
204 |
} |
|
205 |
||
206 |
// FIXME: add other accessors |
|
207 |
} |