thread.h revision 69759eaa6fd4386f1e6d8748052ad221087b3476
10e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro// Copyright 2011 Google Inc. All Rights Reserved.
20e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro// Author: cshapiro@google.com (Carl Shapiro)
30e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
40e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#ifndef ART_SRC_THREAD_H_
50e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#define ART_SRC_THREAD_H_
60e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
7b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <pthread.h>
8b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <list>
9b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
100e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#include "src/globals.h"
11df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers#include "src/jni_internal.h"
120e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#include "src/logging.h"
130e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#include "src/macros.h"
1469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro#include "src/offsets.h"
1561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro#include "src/runtime.h"
160e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
17b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include "jni.h"
18b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapironamespace art {
200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
210e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Object;
22b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass Runtime;
23b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass StackHandleBlock;
240e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread;
25b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList;
260e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
270e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Mutex {
280e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
290e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  virtual ~Mutex() {}
300e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
31b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock();
320e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
33b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool TryLock();
340e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
35b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock();
360e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
370e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  const char* GetName() { return name_; }
380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Thread* GetOwner() { return owner_; }
400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
41b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Mutex* Create(const char* name);
42b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:  // TODO: protected
440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  explicit Mutex(const char* name) : name_(name), owner_(NULL) {}
450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void SetOwner(Thread* thread) { owner_ = thread; }
470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  const char* name_;
500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Thread* owner_;
520e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
53b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pthread_mutex_t lock_impl_;
54b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
550e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Mutex);
560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
570e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
580e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass MutexLock {
590e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
600e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  explicit MutexLock(Mutex *mu) : mu_(mu) {
610e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    mu_->Lock();
620e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
630e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  ~MutexLock() { mu_->Unlock(); }
640e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
650e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Mutex* const mu_;
660e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(MutexLock);
670e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
680e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
69b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Stack handle blocks are allocated within the bridge frame between managed
70b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// and native code.
71b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass StackHandleBlock {
72b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public:
73b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Number of references contained within this SHB
74b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t NumberOfReferences() {
75b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return number_of_references_;
76b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
77b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
78b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Link to previous SHB or NULL
79b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* Link() {
80b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return link_;
81b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
82b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
83b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of length within SHB, used by generated code
84b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t NumberOfReferencesOffset() {
85b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return OFFSETOF_MEMBER(StackHandleBlock, number_of_references_);
86b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
87b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of link within SHB, used by generated code
89b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t LinkOffset() {
90b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return OFFSETOF_MEMBER(StackHandleBlock, link_);
91b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
92b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
93b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private:
94b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock() {}
95b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
96b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t number_of_references_;
97b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* link_;
98b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
99b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  DISALLOW_COPY_AND_ASSIGN(StackHandleBlock);
100b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
101b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1020e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread {
1030e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
104b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  enum State {
105b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kUnknown = -1,
106b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kNew,
107b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kRunnable,
108b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kBlocked,
109b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kWaiting,
110b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTimedWaiting,
111b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kNative,
112b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTerminated,
113b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
114b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
11561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const size_t kDefaultStackSize = 64 * KB;
11661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
11761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread.
11861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static Thread* Create(size_t stack_size);
11961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
12061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread from the calling thread.
12161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static Thread* Attach();
122b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
123b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Thread* Current() {
124d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    void* thread = pthread_getspecific(Thread::pthread_key_self_);
125d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    return reinterpret_cast<Thread*>(thread);
1260e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1270e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
128b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  uint32_t GetId() const {
129b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return id_;
130b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
131b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
132b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pid_t GetNativeId() const {
133b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return native_id_;
1340e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1350e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1360e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  bool IsExceptionPending() const {
1370e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    return false;  // TODO exception_ != NULL;
1380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Object* GetException() const {
1410e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    return exception_;
1420e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void SetException(Object* new_exception) {
1450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    CHECK(new_exception != NULL);
1460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    // TODO: CHECK(exception_ == NULL);
1470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    exception_ = new_exception;  // TODO
1480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void ClearException() {
1510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    exception_ = NULL;
1520e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1530e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
154b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetName(const char* name);
155b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
156b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Suspend();
157b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
158b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool IsSuspended();
159b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
160b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Resume();
161b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
162b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static bool Init();
163b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
16469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* GetRuntime() const {
16569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    return runtime_;
16669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
16769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
168b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  State GetState() {
169b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return state_;
170b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
171b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
172b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetState(State new_state) {
173b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    state_ = new_state;
174b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
175b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
176b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of state within Thread, used by generated code
177b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset StateOffset() {
178b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, state_));
179b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
180b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
181b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // JNI methods
182df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  JniEnvironment* GetJniEnv() const {
183b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return jni_env_;
184b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
185b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
186b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of JNI environment within Thread, used by generated code
187b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset JniEnvOffset() {
188b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_));
189b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
190b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
191b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of top stack handle block within Thread, used by generated code
192b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset TopShbOffset() {
193b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_shb_));
194b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
195b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
196b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Number of references allocated in StackHandleBlocks on this thread
197b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t NumShbHandles() {
198b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    size_t count = 0;
199b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
200b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      count += cur->NumberOfReferences();
201b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    }
202b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return count;
203b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
204b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2050e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
206b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  Thread() :
20769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    id_(1234), top_shb_(NULL), exception_(NULL) {
208df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers    jni_env_ = new JniEnvironment();
209df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  }
21069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
211df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  ~Thread() {
212df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers    delete jni_env_;
213b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
2140e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
215b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void InitCpu();
216b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
21769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Managed thread id.
21869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  uint32_t id_;
219b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
220b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Top of linked list of stack handle blocks or NULL for none
221b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* top_shb_;
222b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
223b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Every thread may have an associated JNI environment
224df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  JniEnvironment* jni_env_;
225b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
226b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  State state_;
227b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
22869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Native (kernel) thread id.
229b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pid_t native_id_;
230b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
23169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Native thread handle.
23261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  pthread_t handle_;
2330e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
23469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Initialized to "this". On certain architectures (such as x86) reading
23569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // off of Thread::Current is easy but getting the address of Thread::Current
23669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // is hard. This field can be read off of Thread::Current to give the address.
23769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Thread* self_;
23869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
23969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* runtime_;
24069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
24169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The pending exception or NULL.
2420e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Object* exception_;
2430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
24469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The inclusive base of the control stack.
24561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  byte* stack_base_;
24669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
24769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The exclusive limit of the control stack.
24861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  byte* stack_limit_;
24961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
25069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // TLS key used to retrieve the VM thread object.
251b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static pthread_key_t pthread_key_self_;
252b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
2530e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Thread);
2540e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
255b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state);
2560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
257b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList {
258b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
25961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMaxId = 0xFFFF;
26061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kInvalidId = 0;
26161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMainId = 1;
26261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
26361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static ThreadList* Create();
264b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
26561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  ~ThreadList();
266b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
267b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Register(Thread* thread);
268b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
269b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unregister(Thread* thread);
270b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
271b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock() {
272b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Lock();
273b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
274b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
275b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock() {
276b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Unlock();
277b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
278b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
279b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
280b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList();
281b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
282b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  std::list<Thread*> list_;
283b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
284b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  Mutex* lock_;
285b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
286b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadList);
287b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
288b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
289b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadListLock {
290b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
291b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadListLock(ThreadList* thread_list, Thread* current_thread)
292b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      : thread_list_(thread_list) {
293b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread == NULL) {  // try to get it from TLS
294b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread = Thread::Current();
295b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
296b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    Thread::State old_state;
297b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
298b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = current_thread->GetState();
299b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(Thread::kWaiting);  // TODO: VMWAIT
300b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    } else {
301b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      // happens during VM shutdown
302b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = Thread::kUnknown;  // TODO: something else
303b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
304b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Lock();
305b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
306b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(old_state);
307b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
308b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
309b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
310b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ~ThreadListLock() {
311b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Unlock();
312b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
313b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
314b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
315b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList* thread_list_;
316b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
317b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadListLock);
318b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
319b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
3200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}  // namespace art
3210e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
3220e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#endif  // ART_SRC_THREAD_H_
323