thread.h revision a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2
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>
7b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <list>
8b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
9578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "globals.h"
10578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "jni_internal.h"
11578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "logging.h"
12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "macros.h"
13578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "offsets.h"
14578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h"
150e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
16b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include "jni.h"
17b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
180e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapironamespace art {
190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
20a40f9bc48afe3a9d38be2fa298fece13ed82ba28Brian Carlstromclass Method;
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 {
137b20a554613609dc372073d2ebd9fbc3925a429f5Elliott Hughes    return 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
150a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes  void ThrowNewException(const char* exception_class_name, const char* fmt, ...)
151a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes      __attribute__ ((format(printf, 3, 4)));
152a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes
1530e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void ClearException() {
1540e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    exception_ = NULL;
1550e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
15745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception within Thread, used by generated code
15845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionOffset() {
15945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_));
16045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
16145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
162b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetName(const char* name);
163b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
164b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Suspend();
165b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
166b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool IsSuspended();
167b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
168b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Resume();
169b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
170b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static bool Init();
171b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
17269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* GetRuntime() const {
17369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    return runtime_;
17469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
17569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
176330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes  State GetState() const {
177b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return state_;
178b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
179b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
180b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetState(State new_state) {
181b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    state_ = new_state;
182b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
183b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
18445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountOffset() {
18545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_));
18645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
18745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
188b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of state within Thread, used by generated code
189b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset StateOffset() {
190b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, state_));
191b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
192b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
193b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // JNI methods
19440ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes  JNIEnv* GetJniEnv() const {
195b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return jni_env_;
196b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
197b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
198b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of JNI environment within Thread, used by generated code
199b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset JniEnvOffset() {
200b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_));
201b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
202b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
20345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of top of managed stack address, used by generated code
20445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset TopOfManagedStackOffset() {
20545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_));
20645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
20745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
208b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of top stack handle block within Thread, used by generated code
209b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset TopShbOffset() {
210b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_shb_));
211b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
212b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
213b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Number of references allocated in StackHandleBlocks on this thread
214b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t NumShbHandles() {
215b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    size_t count = 0;
216b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
217b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      count += cur->NumberOfReferences();
218b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    }
219b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return count;
220b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
221b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
22245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception_entry_point_ within Thread, used by generated code
22345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionEntryPointOffset() {
22445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_entry_point_));
22545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
22645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
22745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterExceptionEntryPoint(void (*handler)(Method**)) {
22845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    exception_entry_point_ = handler;
22945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
23045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
23145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of suspend_count_entry_point_ within Thread, used by generated code
23245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountEntryPointOffset() {
23345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_entry_point_));
23445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
23545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
23645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterSuspendCountEntryPoint(void (*handler)(Method**)) {
23745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    suspend_count_entry_point_ = handler;
23845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
23945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
24045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Increasing the suspend count, will cause the thread to run to safepoint
24145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void IncrementSuspendCount() { suspend_count_++; }
24245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void DecrementSuspendCount() { suspend_count_--; }
24345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
2440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
24540ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes  Thread()
246330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes      : id_(1234),
247330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        top_shb_(NULL),
248330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        jni_env_(NULL),
249330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        exception_(NULL),
250330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        suspend_count_(0) {
251df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  }
25269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
253df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  ~Thread() {
254df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers    delete jni_env_;
255b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
2560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
257b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void InitCpu();
258b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
25969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Managed thread id.
26069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  uint32_t id_;
261b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
26245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Top of the managed stack, written out prior to the state transition from
26345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // kRunnable to kNative. Uses include to give the starting point for scanning
26445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // a managed stack when a thread is in native code.
26545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void* top_of_managed_stack_;
26645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
267b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Top of linked list of stack handle blocks or NULL for none
268b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* top_shb_;
269b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
270b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Every thread may have an associated JNI environment
27140ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes  JNIEnv* jni_env_;
272b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
273b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  State state_;
274b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
27569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Native (kernel) thread id.
276b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pid_t native_id_;
277b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
27869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Native thread handle.
27961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  pthread_t handle_;
2800e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
28169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Initialized to "this". On certain architectures (such as x86) reading
28269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // off of Thread::Current is easy but getting the address of Thread::Current
28369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // is hard. This field can be read off of Thread::Current to give the address.
28469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Thread* self_;
28569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
28669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* runtime_;
28769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
28869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The pending exception or NULL.
2890e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Object* exception_;
2900e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
29145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // A non-zero value is used to tell the current thread to enter a safe point
29245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // at the next poll.
29345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  int suspend_count_;
29445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
29569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The inclusive base of the control stack.
29661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  byte* stack_base_;
29769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
29869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The exclusive limit of the control stack.
29961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  byte* stack_limit_;
30061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
30169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // TLS key used to retrieve the VM thread object.
302b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static pthread_key_t pthread_key_self_;
303b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
30445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when exception_ is set
30545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*exception_entry_point_)(Method** frame);
30645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
30745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when suspend_count_ is non-zero
30845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*suspend_count_entry_point_)(Method** frame);
30945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
3100e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Thread);
3110e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
312330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread);
313b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state);
3140e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
315b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList {
316b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
31761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMaxId = 0xFFFF;
31861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kInvalidId = 0;
31961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMainId = 1;
32061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
32161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static ThreadList* Create();
322b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
32361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  ~ThreadList();
324b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
325b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Register(Thread* thread);
326b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
327b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unregister(Thread* thread);
328b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
329b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock() {
330b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Lock();
331b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
332b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
333b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock() {
334b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Unlock();
335b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
336b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
337b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
338b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList();
339b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
340b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  std::list<Thread*> list_;
341b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
342b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  Mutex* lock_;
343b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
344b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadList);
345b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
346b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
347b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadListLock {
348b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
349b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadListLock(ThreadList* thread_list, Thread* current_thread)
350b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      : thread_list_(thread_list) {
351b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread == NULL) {  // try to get it from TLS
352b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread = Thread::Current();
353b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
354b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    Thread::State old_state;
355b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
356b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = current_thread->GetState();
357b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(Thread::kWaiting);  // TODO: VMWAIT
358b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    } else {
359b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      // happens during VM shutdown
360b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = Thread::kUnknown;  // TODO: something else
361b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
362b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Lock();
363b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
364b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(old_state);
365b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
366b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
367b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
368b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ~ThreadListLock() {
369b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Unlock();
370b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
371b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
372b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
373b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList* thread_list_;
374b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
375b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadListLock);
376b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
377b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
3780e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}  // namespace art
3790e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
3800e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#endif  // ART_SRC_THREAD_H_
381