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 
  31 public class Thread extends VMObject {
  32   private static long tlabFieldOffset;
  33 
  34   private static CIntegerField suspendFlagsField;
  35   // Thread::SuspendFlags enum constants
  36   private static int EXTERNAL_SUSPEND;
  37   private static int EXT_SUSPENDED;
  38   private static int HAS_ASYNC_EXCEPTION;
  39 
  40   private static AddressField activeHandlesField;
  41   private static AddressField highestLockField;
  42   private static AddressField currentPendingMonitorField;
  43   private static AddressField currentWaitingMonitorField;
  44 
  45   static {
  46     VM.registerVMInitializedObserver(new Observer() {
  47         public void update(Observable o, Object data) {
  48           initialize(VM.getVM().getTypeDataBase());
  49         }
  50       });
  51   }
  52 
  53   private static synchronized void initialize(TypeDataBase db) {
  54     Type type = db.lookupType("Thread");
  55 
  56     suspendFlagsField = type.getCIntegerField("_suspend_flags");
  57     EXTERNAL_SUSPEND = db.lookupIntConstant("Thread::_external_suspend").intValue();
  58     EXT_SUSPENDED = db.lookupIntConstant("Thread::_ext_suspended").intValue();
  59     HAS_ASYNC_EXCEPTION = db.lookupIntConstant("Thread::_has_async_exception").intValue();
  60 
  61     tlabFieldOffset    = type.getField("_tlab").getOffset();
  62     activeHandlesField = type.getAddressField("_active_handles");
  63     highestLockField   = type.getAddressField("_highest_lock");
  64     currentPendingMonitorField = type.getAddressField("_current_pending_monitor");
  65     currentWaitingMonitorField = type.getAddressField("_current_waiting_monitor");
  66   }
  67 
  68   public Thread(Address addr) {
  69     super(addr);
  70   }
  71 
  72   public int suspendFlags() {
  73     return (int) suspendFlagsField.getValue(addr);
  74   }
  75 
  76   public boolean isExternalSuspend() {
  77     return (suspendFlags() & EXTERNAL_SUSPEND) != 0;
  78   }
  79 
  80   public boolean isExtSuspended() {
  81     return (suspendFlags() & EXT_SUSPENDED) != 0;
  82   }
  83 
  84   public boolean isBeingExtSuspended() {
  85     return isExtSuspended() || isExternalSuspend();
  86   }
  87 
  88   // historical usage: checked for VM or external suspension
  89   public boolean isAnySuspended() {
  90     return isExtSuspended();
  91   }
  92 
  93   public boolean hasAsyncException() {
  94     return (suspendFlags() & HAS_ASYNC_EXCEPTION) != 0;
  95   }
  96   
  97   public ThreadLocalAllocBuffer tlab() {
  98     return new ThreadLocalAllocBuffer(addr.addOffsetTo(tlabFieldOffset));
  99   }
 100 
 101   public JNIHandleBlock activeHandles() {
 102     Address a = activeHandlesField.getAddress(addr);
 103     if (a == null) {
 104       return null;
 105     }
 106     return new JNIHandleBlock(a);
 107   }
 108 
 109   public boolean   isVMThread()                { return false; }
 110   public boolean   isJavaThread()              { return false; }
 111   public boolean   isCompilerThread()          { return false; }
 112   public boolean   isHiddenFromExternalView()  { return false; } 
 113   public boolean   isJvmtiAgentThread()        { return false; }
 114   public boolean   isWatcherThread()           { return false; }
 115   public boolean   isConcurrentMarkSweepThread() { return false; }
 116   public boolean   isLowMemoryDetectorThread() { return false; }
 117 
 118   /** Memory operations */
 119   public void oopsDo(AddressVisitor oopVisitor) {
 120     // FIXME: Empty for now; will later traverse JNI handles and
 121     // pending exception
 122   }
 123 
 124   public Address highestLock() {
 125     return highestLockField.getValue(addr);
 126   }
 127 
 128   public ObjectMonitor getCurrentPendingMonitor() {
 129     Address monitorAddr = currentPendingMonitorField.getValue(addr);
 130     if (monitorAddr == null) {
 131       return null;
 132     }
 133     return new ObjectMonitor(monitorAddr);
 134   }
 135 
 136   public ObjectMonitor getCurrentWaitingMonitor() {
 137     Address monitorAddr = currentWaitingMonitorField.getValue(addr);
 138     if (monitorAddr == null) {
 139       return null;
 140     }
 141     return new ObjectMonitor(monitorAddr);
 142   }
 143 
 144   public boolean isLockOwned(Address lock) {
 145     if (isInStack(lock)) return true;
 146     return false;
 147   }
 148 
 149   public boolean isInStack(Address a) {
 150     // In the Serviceability Agent we need access to the thread's
 151     // stack pointer to be able to answer this question. Since it is
 152     // only a debugging system at the moment we need access to the
 153     // underlying thread, which is only present for Java threads; see
 154     // JavaThread.java.
 155     return false;
 156   }
 157 
 158   /** Assistance for ObjectMonitor implementation */
 159   Address threadObjectAddress() { return addr; }
 160 }