thread.h revision 668512afd0d9b3772a0abc589208b729ee16bc61
10e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro// Copyright 2011 Google Inc. All Rights Reserved.
20e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
30e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#ifndef ART_SRC_THREAD_H_
40e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#define ART_SRC_THREAD_H_
50e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
6b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <pthread.h>
7a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
8a09576416788b916095739e43a16917e7948f3a4Elliott Hughes#include <iosfwd>
9b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <list>
10b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
111f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "dex_file.h"
12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "globals.h"
1369f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes#include "jni_internal.h"
14578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "logging.h"
15578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "macros.h"
16b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom#include "mem_map.h"
17578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "offsets.h"
18b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapironamespace art {
200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
2169f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughesclass Array;
2237f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughesclass Class;
231f87008b165d26541d832ff805250afdc89c253dBrian Carlstromclass ClassLinker;
24edcc09c737b00462881f147602656739d029571eElliott Hughesclass ClassLoader;
25a40f9bc48afe3a9d38be2fa298fece13ed82ba28Brian Carlstromclass Method;
260e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Object;
27b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass Runtime;
280e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread;
29b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList;
30e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughesclass Throwable;
3155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liaoclass StackTraceElement;
3255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liaotemplate<class T> class ObjectArray;
334417536522fd2a9d8215d8672331984769c9520bShih-wei Liaotemplate<class T> class PrimitiveArray;
344417536522fd2a9d8215d8672331984769c9520bShih-wei Liaotypedef PrimitiveArray<int32_t> IntArray;
350e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
360e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Mutex {
370e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  virtual ~Mutex() {}
390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
40b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock();
410e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
42b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool TryLock();
430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
44b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock();
450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  const char* GetName() { return name_; }
470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Thread* GetOwner() { return owner_; }
490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
50b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Mutex* Create(const char* name);
51b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
5279082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  // TODO: only needed because we lack a condition variable abstraction.
5379082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  pthread_mutex_t* GetImpl() { return &lock_impl_; }
540e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
550e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
5618c0753c1659629021b4becdaa3f6ea81aecce35Elliott Hughes  explicit Mutex(const char* name) : name_(name), owner_(NULL) {}
5718c0753c1659629021b4becdaa3f6ea81aecce35Elliott Hughes
5879082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  void SetOwner(Thread* thread) { owner_ = thread; }
5979082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes
600e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  const char* name_;
610e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
620e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Thread* owner_;
630e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
64b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pthread_mutex_t lock_impl_;
65b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
660e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Mutex);
670e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
680e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
690e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass MutexLock {
700e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
710e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  explicit MutexLock(Mutex *mu) : mu_(mu) {
720e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    mu_->Lock();
730e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
740e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  ~MutexLock() { mu_->Unlock(); }
750e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
760e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Mutex* const mu_;
770e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(MutexLock);
780e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
790e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
80408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers// Stack allocated indirect reference table, allocated within the bridge frame
81408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers// between managed and native code.
82408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogersclass StackIndirectReferenceTable {
83b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public:
84408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Number of references contained within this SIRT
85b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t NumberOfReferences() {
86b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return number_of_references_;
87b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
89408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Link to previous SIRT or NULL
90408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  StackIndirectReferenceTable* Link() {
91b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return link_;
92b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
93b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
94408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Object** References() {
95408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return references_;
96a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  }
97a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
98408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Offset of length within SIRT, used by generated code
99b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t NumberOfReferencesOffset() {
100408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return OFFSETOF_MEMBER(StackIndirectReferenceTable, number_of_references_);
101b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
102b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
103408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Offset of link within SIRT, used by generated code
104b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t LinkOffset() {
105408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return OFFSETOF_MEMBER(StackIndirectReferenceTable, link_);
106b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
107b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
108b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private:
109408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  StackIndirectReferenceTable() {}
110b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
111b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t number_of_references_;
112408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  StackIndirectReferenceTable* link_;
113b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
114a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  // Fake array, really allocated and filled in by jni_compiler.
115408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Object* references_[0];
116a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
117408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  DISALLOW_COPY_AND_ASSIGN(StackIndirectReferenceTable);
118b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
119b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1206de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogersstruct NativeToManagedRecord {
1216de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  NativeToManagedRecord* link;
1226de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void* last_top_of_managed_stack;
1236de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers};
1246de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
1251a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao// Iterator over managed frames up to the first native-to-managed transition
1261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaoclass Frame {
1279b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao public:
1281a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame() : sp_(NULL) {}
1291a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1300cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Method* GetMethod() const {
131a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    return (sp_ != NULL) ? *sp_ : NULL;
1321a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
1331a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1341a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  bool HasNext() const {
1351a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return NextMethod() != NULL;
1361a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
1371a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1381a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  void Next();
1391a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
14055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao  uintptr_t GetPC() const;
1411a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1420cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Method** GetSP() const {
1431a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return sp_;
1441a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
1451a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1461a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  // TODO: this is here for testing, remove when we have exception unit tests
1471a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  // that use the real stack
1480cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  void SetSP(Method** sp) {
1491a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    sp_ = sp;
1501a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
1511a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1521a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao private:
1530cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Method* NextMethod() const;
1541a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1551a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  friend class Thread;
1561a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1570cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Method** sp_;
1581a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao};
1591a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
1600e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread {
1610e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
162b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  enum State {
163b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kUnknown = -1,
164b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kNew,
165b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kRunnable,
166b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kBlocked,
167b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kWaiting,
168b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTimedWaiting,
169b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kNative,
170b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTerminated,
171b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
172b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
173c143c55718342519db5398e41dda31422cf16c79buzbee
17461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const size_t kDefaultStackSize = 64 * KB;
17561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
176c143c55718342519db5398e41dda31422cf16c79buzbee  // Runtime support function pointers
177c143c55718342519db5398e41dda31422cf16c79buzbee  void* (*pMemcpy)(void*, const void*, size_t);
1785433072f589b61413e042eddf76e8190a048f71dbuzbee  uint64_t (*pShlLong)(uint64_t, uint32_t);
1795433072f589b61413e042eddf76e8190a048f71dbuzbee  uint64_t (*pShrLong)(uint64_t, uint32_t);
1805433072f589b61413e042eddf76e8190a048f71dbuzbee  uint64_t (*pUshrLong)(uint64_t, uint32_t);
181c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pI2f)(int);
182c143c55718342519db5398e41dda31422cf16c79buzbee  int (*pF2iz)(float);
183c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pD2f)(double);
184c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pF2d)(float);
185c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pI2d)(int);
186c143c55718342519db5398e41dda31422cf16c79buzbee  int (*pD2iz)(double);
187c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pL2f)(long);
188c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pL2d)(long);
1891b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  long long (*pF2l)(float);
1901b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  long long (*pD2l)(double);
191c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFadd)(float, float);
192c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFsub)(float, float);
193c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFdiv)(float, float);
194c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFmul)(float, float);
195c143c55718342519db5398e41dda31422cf16c79buzbee  float (*pFmodf)(float, float);
196c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pDadd)(double, double);
197c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pDsub)(double, double);
198c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pDdiv)(double, double);
199c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pDmul)(double, double);
200c143c55718342519db5398e41dda31422cf16c79buzbee  double (*pFmod)(double, double);
201c143c55718342519db5398e41dda31422cf16c79buzbee  int (*pIdivmod)(int, int);
202c143c55718342519db5398e41dda31422cf16c79buzbee  int (*pIdiv)(int, int);
203439c4fa0db980fb19e4a585723a64a3461e4c278buzbee  long long (*pLmul)(long long, long long);
204c143c55718342519db5398e41dda31422cf16c79buzbee  long long (*pLdivmod)(long long, long long);
205dfd3d70e58c37b5d56eded3a4469082d8bb26ee0buzbee  Array* (*pAllocFromCode)(uint32_t, Method*, int32_t);
2061f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom  Object* (*pAllocObjectFromCode)(uint32_t, Method*);
207e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  uint32_t (*pGet32Static)(uint32_t, const Method*);
208e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  void (*pSet32Static)(uint32_t, const Method*, uint32_t);
209e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  uint64_t (*pGet64Static)(uint32_t, const Method*);
210e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  void (*pSet64Static)(uint32_t, const Method*, uint64_t);
211e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  Object* (*pGetObjStatic)(uint32_t, const Method*);
212e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee  void (*pSetObjStatic)(uint32_t, const Method*, Object*);
2131b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  bool (*pCanPutArrayElementFromCode)(const Class*, const Class*);
2141b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  int (*pInstanceofNonTrivialFromCode) (const Class*, const Class*);
2151b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  Method* (*pFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, struct DvmDex*);
2161b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  bool (*pUnlockObjectFromCode)(Thread*, Object*);
2171b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  void (*pLockObjectFromCode)(Thread*, Object*);
2181b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  void (*pThrowException)(Thread*, Throwable*);
2191b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  void (*pHandleFillArrayDataFromCode)(Array*, const uint16_t*);
2201b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee  Class* (*pInitializeTypeFromCode)(uint32_t, Method*);
221561227c80077bbb4147f778043f1a836af6b9248buzbee  void (*pResolveMethodFromCode)(Method*, uint32_t);
222c143c55718342519db5398e41dda31422cf16c79buzbee
2239b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao  class StackVisitor {
2249b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao   public:
2250cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    virtual ~StackVisitor() {}
2269b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao    virtual bool VisitFrame(const Frame& frame) = 0;
2279b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao  };
2289b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao
22961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread.
230b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom  static Thread* Create(const Runtime* runtime);
23161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
23261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread from the calling thread.
233515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  static Thread* Attach(const Runtime* runtime);
234b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
235b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Thread* Current() {
236d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    void* thread = pthread_getspecific(Thread::pthread_key_self_);
237d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    return reinterpret_cast<Thread*>(thread);
2380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
2390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
240a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  void Dump(std::ostream& os) const;
241a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
2420cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  State GetState() const {
2430cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    return state_;
2440cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2450cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
2460cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  State SetState(State new_state) {
2470cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    State old_state = state_;
2480cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    state_ = new_state;
2490cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    return old_state;
2500cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2510cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
2520cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  bool CanAccessDirectReferences() const {
2530cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    return state_ == kRunnable;
2540cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2550cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
256b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  uint32_t GetId() const {
257b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return id_;
258b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
259b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
260d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  pid_t GetTid() const {
261d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes    return tid_;
262d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  }
263e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes
264e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes  pthread_t GetImpl() const {
265e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes    return handle_;
2660e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
2670e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
2680cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  // Returns the Method* for the current method.
2690cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  // This is used by the JNI implementation for logging and diagnostic purposes.
2700cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  const Method* GetCurrentMethod() const {
2710cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    return top_of_managed_stack_.GetMethod();
2720cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2730cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
2740e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  bool IsExceptionPending() const {
275b20a554613609dc372073d2ebd9fbc3925a429f5Elliott Hughes    return exception_ != NULL;
2760e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
2770e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
278e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  Throwable* GetException() const {
2790cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    DCHECK(CanAccessDirectReferences());
2800e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    return exception_;
2810e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
2820e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
2830cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  void SetException(Throwable* new_exception) {
2840cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    DCHECK(CanAccessDirectReferences());
2850cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    CHECK(new_exception != NULL);
2860cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    // TODO: CHECK(exception_ == NULL);
2870cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    exception_ = new_exception;  // TODO
2880cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  }
2890cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
2900cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  void ClearException() {
2910cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    exception_ = NULL;
292a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  }
293a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
2941a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame GetTopOfStack() const {
2951a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return top_of_managed_stack_;
2961a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  }
2971a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
2981a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  // TODO: this is here for testing, remove when we have exception unit tests
2991a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  // that use the real stack
3001a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  void SetTopOfStack(void* stack) {
3010cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(stack));
3020e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
3030e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
304e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  void ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...)
305a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes      __attribute__ ((format(printf, 3, 4)));
306a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes
30779082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  // This exception is special, because we need to pre-allocate an instance.
30879082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes  void ThrowOutOfMemoryError();
30979082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes
3101a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame FindExceptionHandler(void* throw_pc, void** handler_pc);
3111a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
3121a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  void* FindExceptionHandlerInMethod(const Method* method,
3131a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                     void* throw_pc,
3141a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                     const DexFile& dex_file,
3151a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                                     ClassLinker* class_linker);
316668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  static ThreadOffset SelfOffset() {
317668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao    return ThreadOffset(OFFSETOF_MEMBER(Thread, self_));
318668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  }
3191a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao
32045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception within Thread, used by generated code
32145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionOffset() {
32245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_));
32345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
32445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
325c143c55718342519db5398e41dda31422cf16c79buzbee  // Offset of id within Thread, used by generated code
326c143c55718342519db5398e41dda31422cf16c79buzbee  static ThreadOffset IdOffset() {
327c143c55718342519db5398e41dda31422cf16c79buzbee    return ThreadOffset(OFFSETOF_MEMBER(Thread, id_));
328c143c55718342519db5398e41dda31422cf16c79buzbee  }
329c143c55718342519db5398e41dda31422cf16c79buzbee
330c143c55718342519db5398e41dda31422cf16c79buzbee  // Offset of card_table within Thread, used by generated code
331c143c55718342519db5398e41dda31422cf16c79buzbee  static ThreadOffset CardTableOffset() {
332c143c55718342519db5398e41dda31422cf16c79buzbee    return ThreadOffset(OFFSETOF_MEMBER(Thread, card_table_));
333c143c55718342519db5398e41dda31422cf16c79buzbee  }
334c143c55718342519db5398e41dda31422cf16c79buzbee
335b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetName(const char* name);
336b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
337b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Suspend();
338b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
339b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool IsSuspended();
340b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
341b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Resume();
342b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
343c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  static bool Startup();
344c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  static void Shutdown();
345b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
34645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountOffset() {
34745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_));
34845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
34945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
350b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of state within Thread, used by generated code
351b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset StateOffset() {
352b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, state_));
353b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
354b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
355b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // JNI methods
35669f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes  JNIEnvExt* GetJniEnv() const {
357b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return jni_env_;
358b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
359b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
360b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of JNI environment within Thread, used by generated code
361b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset JniEnvOffset() {
362b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_));
363b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
364b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
36545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of top of managed stack address, used by generated code
36645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset TopOfManagedStackOffset() {
3671a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_) +
3681a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao                        OFFSETOF_MEMBER(Frame, sp_));
36945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
37045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
371408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Offset of top stack indirect reference table within Thread, used by
372408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // generated code
373408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  static ThreadOffset TopSirtOffset() {
374408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_sirt_));
375b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
376b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
377408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Number of references allocated in SIRTs on this thread
378408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  size_t NumSirtReferences();
379a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
380408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Is the given obj in this thread's stack indirect reference table?
381408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  bool SirtContains(jobject obj);
382408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers
383408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Convert a jobject into a Object*
384408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  Object* DecodeJObject(jobject obj);
385b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
38645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception_entry_point_ within Thread, used by generated code
38745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionEntryPointOffset() {
38845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_entry_point_));
38945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
39045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
39145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterExceptionEntryPoint(void (*handler)(Method**)) {
39245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    exception_entry_point_ = handler;
39345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
39445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
39545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of suspend_count_entry_point_ within Thread, used by generated code
39645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountEntryPointOffset() {
39745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_entry_point_));
39845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
39945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
40045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterSuspendCountEntryPoint(void (*handler)(Method**)) {
40145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    suspend_count_entry_point_ = handler;
40245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
40345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
40445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Increasing the suspend count, will cause the thread to run to safepoint
40545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void IncrementSuspendCount() { suspend_count_++; }
40645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void DecrementSuspendCount() { suspend_count_--; }
40745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
4086de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // Linked list recording transitions from native to managed code
4096de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void PushNativeToManagedRecord(NativeToManagedRecord* record) {
4101a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    record->last_top_of_managed_stack = reinterpret_cast<void*>(top_of_managed_stack_.GetSP());
4116de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    record->link = native_to_managed_record_;
4126de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    native_to_managed_record_ = record;
4131a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao    top_of_managed_stack_.SetSP(NULL);
4146de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  }
4156de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void PopNativeToManagedRecord(const NativeToManagedRecord& record) {
4166de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    native_to_managed_record_ = record.link;
4170cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(record.last_top_of_managed_stack));
4186de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  }
4196de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
420bffb15585b8fd43d3ca534ddbb85e7f591595951Brian Carlstrom  const ClassLoader* GetClassLoaderOverride() {
4210cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    // TODO: need to place the class_loader_override_ in a handle
4220cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    // DCHECK(CanAccessDirectReferences());
423c143c55718342519db5398e41dda31422cf16c79buzbee    return class_loader_override_;
424c143c55718342519db5398e41dda31422cf16c79buzbee  }
425c143c55718342519db5398e41dda31422cf16c79buzbee
426bffb15585b8fd43d3ca534ddbb85e7f591595951Brian Carlstrom  void SetClassLoaderOverride(const ClassLoader* class_loader_override) {
427c143c55718342519db5398e41dda31422cf16c79buzbee    class_loader_override_ = class_loader_override;
428c143c55718342519db5398e41dda31422cf16c79buzbee  }
429c143c55718342519db5398e41dda31422cf16c79buzbee
4304417536522fd2a9d8215d8672331984769c9520bShih-wei Liao  // Allocate stack trace
4319b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao  ObjectArray<StackTraceElement>* AllocStackTrace();
43255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao
433410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  void VisitRoots(Heap::RootVisitor* visitor, void* arg) const;
434410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
4350e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
43640ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes  Thread()
437330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes      : id_(1234),
4381a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao        top_of_managed_stack_(),
4396de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers        native_to_managed_record_(NULL),
440408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers        top_sirt_(NULL),
441330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        jni_env_(NULL),
442330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        exception_(NULL),
443c143c55718342519db5398e41dda31422cf16c79buzbee        suspend_count_(0),
444c143c55718342519db5398e41dda31422cf16c79buzbee        class_loader_override_(NULL) {
4453ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee    InitFunctionPointers();
446df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  }
44769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
448c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  ~Thread();
4490cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  friend class Runtime;  // For ~Thread.
4500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
451d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  void DumpState(std::ostream& os) const;
452d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  void DumpStack(std::ostream& os) const;
453d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
454b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void InitCpu();
4553ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee  void InitFunctionPointers();
456b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
4579b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao  void WalkStack(StackVisitor* visitor);
4584417536522fd2a9d8215d8672331984769c9520bShih-wei Liao
45969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Managed thread id.
46069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  uint32_t id_;
461b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
462d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  // System thread id.
463d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  pid_t tid_;
464d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
465d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  // Native thread handle.
466d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  pthread_t handle_;
467d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
468c143c55718342519db5398e41dda31422cf16c79buzbee  // FIXME: placeholder for the gc cardTable
469c143c55718342519db5398e41dda31422cf16c79buzbee  uint32_t card_table_;
470c143c55718342519db5398e41dda31422cf16c79buzbee
47145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Top of the managed stack, written out prior to the state transition from
47245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // kRunnable to kNative. Uses include to give the starting point for scanning
47345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // a managed stack when a thread is in native code.
4741a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao  Frame top_of_managed_stack_;
47545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
4766de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // A linked list (of stack allocated records) recording transitions from
4776de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // native to managed code.
4786de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  NativeToManagedRecord* native_to_managed_record_;
4796de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
480408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Top of linked list of stack indirect reference tables or NULL for none
481408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  StackIndirectReferenceTable* top_sirt_;
482b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
483b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Every thread may have an associated JNI environment
48469f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes  JNIEnvExt* jni_env_;
485b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
486b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  State state_;
487b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
48869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Initialized to "this". On certain architectures (such as x86) reading
48969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // off of Thread::Current is easy but getting the address of Thread::Current
49069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // is hard. This field can be read off of Thread::Current to give the address.
49169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Thread* self_;
49269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
49369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* runtime_;
49469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
49569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The pending exception or NULL.
496e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes  Throwable* exception_;
4970e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
49845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // A non-zero value is used to tell the current thread to enter a safe point
49945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // at the next poll.
50045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  int suspend_count_;
50145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
502edcc09c737b00462881f147602656739d029571eElliott Hughes  // Needed to get the right ClassLoader in JNI_OnLoad, but also
503edcc09c737b00462881f147602656739d029571eElliott Hughes  // useful for testing.
504bffb15585b8fd43d3ca534ddbb85e7f591595951Brian Carlstrom  const ClassLoader* class_loader_override_;
505c143c55718342519db5398e41dda31422cf16c79buzbee
50669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // TLS key used to retrieve the VM thread object.
507b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static pthread_key_t pthread_key_self_;
508b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
50945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when exception_ is set
51045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*exception_entry_point_)(Method** frame);
51145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
51245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when suspend_count_ is non-zero
51345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*suspend_count_entry_point_)(Method** frame);
51445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
5150e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Thread);
5160e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
517330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread);
518b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state);
5190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
520b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList {
521b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
52261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMaxId = 0xFFFF;
52361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kInvalidId = 0;
52461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMainId = 1;
52561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
52661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static ThreadList* Create();
527b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
52861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  ~ThreadList();
529b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
530d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes  void Dump(std::ostream& os);
531d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes
532b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Register(Thread* thread);
533b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
534b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unregister(Thread* thread);
535b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
536c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes  bool Contains(Thread* thread);
537c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
538b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock() {
539b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Lock();
540b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
541b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
542b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock() {
543b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Unlock();
544b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
545b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
546410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  void VisitRoots(Heap::RootVisitor* visitor, void* arg) const;
547410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
548b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
549b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList();
550b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
551b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  std::list<Thread*> list_;
552b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
553b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  Mutex* lock_;
554b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
555b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadList);
556b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
557b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
558b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadListLock {
559b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
560b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadListLock(ThreadList* thread_list, Thread* current_thread)
561b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      : thread_list_(thread_list) {
562b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread == NULL) {  // try to get it from TLS
563b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread = Thread::Current();
564b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
565b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    Thread::State old_state;
566b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
567ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes      old_state = current_thread->SetState(Thread::kWaiting);  // TODO: VMWAIT
568b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    } else {
569b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      // happens during VM shutdown
570b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = Thread::kUnknown;  // TODO: something else
571b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
572b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Lock();
573b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
574b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(old_state);
575b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
576b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
577b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
578b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ~ThreadListLock() {
579b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Unlock();
580b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
581b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
582b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
583b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList* thread_list_;
584b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
585b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadListLock);
586b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
587b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
588ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughesclass ScopedThreadStateChange {
589ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes public:
590ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  ScopedThreadStateChange(Thread* thread, Thread::State new_state) : thread_(thread) {
591ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes    old_thread_state_ = thread_->SetState(new_state);
592ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  }
593ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
594ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  ~ScopedThreadStateChange() {
595ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes    thread_->SetState(old_thread_state_);
596ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  }
597ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
598ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes private:
599ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread* thread_;
600ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  Thread::State old_thread_state_;
601ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
602ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes};
603ad7c2a3b4daa2abd707375444f4b0db7d69a3838Elliott Hughes
6040e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}  // namespace art
6050e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
6060e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#endif  // ART_SRC_THREAD_H_
607