1 /*
  2  * Copyright (c) 2000, 2021, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * 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.utilities.Observable;
 31 import sun.jvm.hotspot.utilities.Observer;
 32 
 33 public class Thread extends VMObject {
 34   private static long tlabFieldOffset;
 35 
 36   private static long lockStackCurrentOffset;
 37   private static long lockStackBaseOffset;
 38 
 39   private static CIntegerField suspendFlagsField;
 40 
 41   private static AddressField currentPendingMonitorField;
 42   private static AddressField currentWaitingMonitorField;
 43 
 44   private static JLongField allocatedBytesField;
 45 
 46   private static long oopPtrSize;
 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 typeThread = db.lookupType("Thread");
 58     Type typeJavaThread = db.lookupType("JavaThread");
 59     Type typeLockStack = db.lookupType("LockStack");
 60 
 61     suspendFlagsField = typeJavaThread.getCIntegerField("_suspend_flags");
 62 
 63     tlabFieldOffset    = typeThread.getField("_tlab").getOffset();
 64     currentPendingMonitorField = typeJavaThread.getAddressField("_current_pending_monitor");
 65     currentWaitingMonitorField = typeJavaThread.getAddressField("_current_waiting_monitor");
 66     allocatedBytesField = typeThread.getJLongField("_allocated_bytes");
 67 
 68     lockStackCurrentOffset = typeThread.getField("_lock_stack").getOffset() + typeLockStack.getField("_current").getOffset();
 69     lockStackBaseOffset = typeThread.getField("_lock_stack").getOffset() + typeLockStack.getField("_base").getOffset();
 70     oopPtrSize = VM.getVM().getAddressSize();
 71   }
 72 
 73   public Thread(Address addr) {
 74     super(addr);
 75   }
 76 
 77   public int suspendFlags() {
 78     return (int) suspendFlagsField.getValue(addr);
 79   }
 80 
 81   public ThreadLocalAllocBuffer tlab() {
 82     return new ThreadLocalAllocBuffer(addr.addOffsetTo(tlabFieldOffset));
 83   }
 84 
 85   public long allocatedBytes() {
 86     return allocatedBytesField.getValue(addr);
 87   }
 88 
 89   public boolean   isVMThread()                  { return false; }
 90   public boolean   isJavaThread()                { return false; }
 91   public boolean   isCompilerThread()            { return false; }
 92   public boolean   isCodeCacheSweeperThread()    { return false; }
 93   public boolean   isHiddenFromExternalView()    { return false; }
 94   public boolean   isJvmtiAgentThread()          { return false; }
 95   public boolean   isWatcherThread()             { return false; }
 96   public boolean   isServiceThread()             { return false; }
 97   public boolean   isMonitorDeflationThread()    { return false; }
 98 
 99   /** Memory operations */
100   public void oopsDo(AddressVisitor oopVisitor) {
101     // FIXME: Empty for now; will later traverse JNI handles and
102     // pending exception
103   }
104 
105   public ObjectMonitor getCurrentPendingMonitor() {
106     Address monitorAddr = currentPendingMonitorField.getValue(addr);
107     if (monitorAddr == null) {
108       return null;
109     }
110     return new ObjectMonitor(monitorAddr);
111   }
112 
113   public ObjectMonitor getCurrentWaitingMonitor() {
114     Address monitorAddr = currentWaitingMonitorField.getValue(addr);
115     if (monitorAddr == null) {
116       return null;
117     }
118     return new ObjectMonitor(monitorAddr);
119   }
120 
121   public boolean isLockOwned(OopHandle obj) {
122     Address current = addr.getAddressAt(lockStackCurrentOffset);
123     Address base = addr.getAddressAt(lockStackBaseOffset);
124     while (base.lessThan(current)) {
125         Address oop = base.getAddressAt(0);
126         if (oop.equals(obj)) {
127             return true;
128         }
129         base = base.addOffsetTo(oopPtrSize);
130     }
131     return false;
132   }
133 
134   public boolean isInStack(Address a) {
135     // In the Serviceability Agent we need access to the thread's
136     // stack pointer to be able to answer this question. Since it is
137     // only a debugging system at the moment we need access to the
138     // underlying thread, which is only present for Java threads; see
139     // JavaThread.java.
140     return false;
141   }
142 
143   /** Assistance for ObjectMonitor implementation */
144   Address threadObjectAddress() { return addr; }
145 }