diff agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children b9fba36710f2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.runtime.solaris_sparc.SolarisSPARCJavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.solaris_x86.SolarisX86JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.solaris_amd64.SolarisAMD64JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.win32_ia64.Win32IA64JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.linux_ia64.LinuxIA64JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess;
+import sun.jvm.hotspot.utilities.*;
+
+public class Threads {
+    private static JavaThreadFactory threadFactory;
+    private static AddressField      threadListField;
+    private static VirtualConstructor virtualConstructor;
+    private static JavaThreadPDAccess access;
+
+    static {
+        VM.registerVMInitializedObserver(new Observer() {
+            public void update(Observable o, Object data) {
+                initialize(VM.getVM().getTypeDataBase());
+            }
+        });
+    }
+
+    private static synchronized void initialize(TypeDataBase db) {
+        Type type = db.lookupType("Threads");
+
+        threadListField = type.getAddressField("_thread_list");
+
+        // Instantiate appropriate platform-specific JavaThreadFactory
+        String os  = VM.getVM().getOS();
+        String cpu = VM.getVM().getCPU();
+
+        access = null;
+        // FIXME: find the platform specific PD class by reflection?
+        if (os.equals("solaris")) {
+            if (cpu.equals("sparc")) {
+                access = new SolarisSPARCJavaThreadPDAccess();
+            } else if (cpu.equals("x86")) {
+                access = new SolarisX86JavaThreadPDAccess();
+            } else if (cpu.equals("amd64")) {
+                access = new SolarisAMD64JavaThreadPDAccess();
+            }
+        } else if (os.equals("win32")) {
+            if (cpu.equals("x86")) {
+                access =  new Win32X86JavaThreadPDAccess();
+            } else if (cpu.equals("amd64")) {
+                access =  new Win32AMD64JavaThreadPDAccess();
+            } else if (cpu.equals("ia64")) {
+                access =  new Win32IA64JavaThreadPDAccess();
+            }
+        } else if (os.equals("linux")) {
+            if (cpu.equals("x86")) {
+                access = new LinuxX86JavaThreadPDAccess();
+            } else if (cpu.equals("ia64")) {
+                access = new LinuxIA64JavaThreadPDAccess();
+            } else if (cpu.equals("amd64")) {
+                access = new LinuxAMD64JavaThreadPDAccess();
+            } else if (cpu.equals("sparc")) {
+                access = new LinuxSPARCJavaThreadPDAccess();
+            }
+
+        }
+
+        if (access == null) {
+            throw new RuntimeException("OS/CPU combination " + os + "/" + cpu +
+            " not yet supported");
+        }
+
+        virtualConstructor = new VirtualConstructor(db);
+        // Add mappings for all known thread types
+        virtualConstructor.addMapping("JavaThread", JavaThread.class);
+        if (!VM.getVM().isCore()) {
+            virtualConstructor.addMapping("CompilerThread", CompilerThread.class);
+        }
+        // for now, use JavaThread itself. fix it later with appropriate class if needed
+        virtualConstructor.addMapping("SurrogateLockerThread", JavaThread.class);
+        virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class);
+        virtualConstructor.addMapping("LowMemoryDetectorThread", LowMemoryDetectorThread.class);
+    }
+
+    public Threads() {
+    }
+
+    /** NOTE: this returns objects of type JavaThread, CompilerThread,
+      JvmtiAgentThread, and LowMemoryDetectorThread.
+      The latter four are subclasses of the former. Most operations
+      (fetching the top frame, etc.) are only allowed to be performed on
+      a "pure" JavaThread. For this reason, {@link
+      sun.jvm.hotspot.runtime.JavaThread#isJavaThread} has been
+      changed from the definition in the VM (which returns true for
+      all of these thread types) to return true for JavaThreads and
+      false for the three subclasses. FIXME: should reconsider the
+      inheritance hierarchy; see {@link
+      sun.jvm.hotspot.runtime.JavaThread#isJavaThread}. */
+    public JavaThread first() {
+        Address threadAddr = threadListField.getValue();
+        if (threadAddr == null) {
+            return null;
+        }
+
+        return createJavaThreadWrapper(threadAddr);
+    }
+
+    /** Routine for instantiating appropriately-typed wrapper for a
+      JavaThread. Currently needs to be public for OopUtilities to
+      access it. */
+    public JavaThread createJavaThreadWrapper(Address threadAddr) {
+        try {
+            JavaThread thread = (JavaThread)virtualConstructor.instantiateWrapperFor(threadAddr);
+            thread.setThreadPDAccess(access);
+            return thread;
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr +
+            " (expected type JavaThread, CompilerThread, LowMemoryDetectorThread, JvmtiAgentThread, or SurrogateLockerThread)", e);
+        }
+    }
+
+    /** Memory operations */
+    public void oopsDo(AddressVisitor oopVisitor) {
+        // FIXME: add more of VM functionality
+        for (JavaThread thread = first(); thread != null; thread = thread.next()) {
+            thread.oopsDo(oopVisitor);
+        }
+    }
+
+    // refer to Threads::owning_thread_from_monitor_owner
+    public JavaThread owningThreadFromMonitor(Address o) {
+        if (o == null) return null;
+        for (JavaThread thread = first(); thread != null; thread = thread.next()) {
+            if (o.equals(thread.threadObjectAddress())) {
+                return thread;
+            }
+        }
+
+        long leastDiff = 0;
+        boolean leastDiffInitialized = false;
+        JavaThread theOwner = null;
+        for (JavaThread thread = first(); thread != null; thread = thread.next()) {
+            Address addr = thread.highestLock();
+            if (addr == null || addr.lessThan(o)) continue;
+            long diff = addr.minus(o);
+            if (!leastDiffInitialized || diff < leastDiff) {
+                leastDiffInitialized = true;
+                leastDiff = diff;
+                theOwner = thread;
+            }
+        }
+        return theOwner;
+    }
+
+    public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) {
+        return owningThreadFromMonitor(monitor.owner());
+    }
+
+    // refer to Threads::get_pending_threads
+    // Get list of Java threads that are waiting to enter the specified monitor.
+    public List getPendingThreads(ObjectMonitor monitor) {
+        List pendingThreads = new ArrayList();
+        for (JavaThread thread = first(); thread != null; thread = thread.next()) {
+            if (thread.isCompilerThread()) {
+                continue;
+            }
+            ObjectMonitor pending = thread.getCurrentPendingMonitor();
+            if (monitor.equals(pending)) {
+                pendingThreads.add(thread);
+            }
+        }
+        return pendingThreads;
+    }
+
+    // Get list of Java threads that have called Object.wait on the specified monitor.
+    public List getWaitingThreads(ObjectMonitor monitor) {
+        List pendingThreads = new ArrayList();
+        for (JavaThread thread = first(); thread != null; thread = thread.next()) {
+            ObjectMonitor waiting = thread.getCurrentWaitingMonitor();
+            if (monitor.equals(waiting)) {
+                pendingThreads.add(thread);
+            }
+        }
+        return pendingThreads;
+    }
+
+    // FIXME: add other accessors
+}