thread.h revision 578bbdc684db8ed68e9fedbc678669d27fa68b6e
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
10578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "globals.h"
11578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "jni_internal.h"
12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "logging.h"
13578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "macros.h"
14578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "object.h"
15578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "offsets.h"
16578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h"
170e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
18b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include "jni.h"
19b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapironamespace art {
210e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
220e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Object;
23b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass Runtime;
24b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass StackHandleBlock;
250e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread;
26b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList;
270e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
280e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Mutex {
290e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
300e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  virtual ~Mutex() {}
310e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
32b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock();
330e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
34b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool TryLock();
350e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
36b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock();
370e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  const char* GetName() { return name_; }
390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Thread* GetOwner() { return owner_; }
410e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
42b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Mutex* Create(const char* name);
43b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:  // TODO: protected
450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  explicit Mutex(const char* name) : name_(name), owner_(NULL) {}
460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void SetOwner(Thread* thread) { owner_ = thread; }
480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  const char* name_;
510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
520e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Thread* owner_;
530e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
54b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pthread_mutex_t lock_impl_;
55b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Mutex);
570e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
580e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
590e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass MutexLock {
600e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
610e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  explicit MutexLock(Mutex *mu) : mu_(mu) {
620e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    mu_->Lock();
630e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
640e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  ~MutexLock() { mu_->Unlock(); }
650e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
660e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Mutex* const mu_;
670e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(MutexLock);
680e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
690e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
70b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Stack handle blocks are allocated within the bridge frame between managed
71b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// and native code.
72b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass StackHandleBlock {
73b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public:
74b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Number of references contained within this SHB
75b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t NumberOfReferences() {
76b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return number_of_references_;
77b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
78b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
79b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Link to previous SHB or NULL
80b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* Link() {
81b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return link_;
82b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
83b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
84b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of length within SHB, used by generated code
85b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t NumberOfReferencesOffset() {
86b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return OFFSETOF_MEMBER(StackHandleBlock, number_of_references_);
87b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
89b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of link within SHB, used by generated code
90b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t LinkOffset() {
91b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return OFFSETOF_MEMBER(StackHandleBlock, link_);
92b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
93b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
94b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private:
95b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock() {}
96b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
97b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t number_of_references_;
98b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* link_;
99b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
100b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  DISALLOW_COPY_AND_ASSIGN(StackHandleBlock);
101b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
102b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1030e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread {
1040e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
105b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  enum State {
106b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kUnknown = -1,
107b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kNew,
108b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kRunnable,
109b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kBlocked,
110b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kWaiting,
111b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTimedWaiting,
112b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kNative,
113b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTerminated,
114b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
115b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
11661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const size_t kDefaultStackSize = 64 * KB;
11761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
11861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread.
11961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static Thread* Create(size_t stack_size);
12061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
12161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread from the calling thread.
12261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static Thread* Attach();
123b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
124b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Thread* Current() {
125d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    void* thread = pthread_getspecific(Thread::pthread_key_self_);
126d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    return reinterpret_cast<Thread*>(thread);
1270e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1280e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
129b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  uint32_t GetId() const {
130b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return id_;
131b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
132b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
133b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pid_t GetNativeId() const {
134b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return native_id_;
1350e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1360e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1370e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  bool IsExceptionPending() const {
1380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    return false;  // TODO exception_ != NULL;
1390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1410e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Object* GetException() const {
1420e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    return exception_;
1430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void SetException(Object* new_exception) {
1460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    CHECK(new_exception != NULL);
1470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    // TODO: CHECK(exception_ == NULL);
1480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    exception_ = new_exception;  // TODO
1490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void ClearException() {
1520e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    exception_ = NULL;
1530e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1540e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
15545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception within Thread, used by generated code
15645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionOffset() {
15745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_));
15845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
15945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
160b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetName(const char* name);
161b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
162b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Suspend();
163b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
164b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool IsSuspended();
165b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
166b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Resume();
167b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
168b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static bool Init();
169b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
17069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* GetRuntime() const {
17169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    return runtime_;
17269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
17369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
174b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  State GetState() {
175b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return state_;
176b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
177b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
178b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetState(State new_state) {
179b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    state_ = new_state;
180b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
181b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
18245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountOffset() {
18345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_));
18445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
18545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
186b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of state within Thread, used by generated code
187b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset StateOffset() {
188b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, state_));
189b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
190b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
191b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // JNI methods
192df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  JniEnvironment* GetJniEnv() const {
193b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return jni_env_;
194b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
195b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
196b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of JNI environment within Thread, used by generated code
197b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset JniEnvOffset() {
198b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_));
199b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
200b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
20145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of top of managed stack address, used by generated code
20245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset TopOfManagedStackOffset() {
20345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_));
20445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
20545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
206b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of top stack handle block within Thread, used by generated code
207b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset TopShbOffset() {
208b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_shb_));
209b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
210b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
211b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Number of references allocated in StackHandleBlocks on this thread
212b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t NumShbHandles() {
213b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    size_t count = 0;
214b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
215b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      count += cur->NumberOfReferences();
216b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    }
217b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return count;
218b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
219b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
22045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception_entry_point_ within Thread, used by generated code
22145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionEntryPointOffset() {
22245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_entry_point_));
22345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
22445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
22545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterExceptionEntryPoint(void (*handler)(Method**)) {
22645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    exception_entry_point_ = handler;
22745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
22845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
22945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of suspend_count_entry_point_ within Thread, used by generated code
23045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountEntryPointOffset() {
23145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_entry_point_));
23245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
23345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
23445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterSuspendCountEntryPoint(void (*handler)(Method**)) {
23545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    suspend_count_entry_point_ = handler;
23645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
23745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
23845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Increasing the suspend count, will cause the thread to run to safepoint
23945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void IncrementSuspendCount() { suspend_count_++; }
24045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void DecrementSuspendCount() { suspend_count_--; }
24145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
2420e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
243b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  Thread() :
24445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    id_(1234), top_shb_(NULL), exception_(NULL), suspend_count_(0) {
245df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers    jni_env_ = new JniEnvironment();
246df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  }
24769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
248df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  ~Thread() {
249df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers    delete jni_env_;
250b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
2510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
252b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void InitCpu();
253b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
25469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Managed thread id.
25569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  uint32_t id_;
256b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
25745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Top of the managed stack, written out prior to the state transition from
25845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // kRunnable to kNative. Uses include to give the starting point for scanning
25945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // a managed stack when a thread is in native code.
26045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void* top_of_managed_stack_;
26145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
262b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Top of linked list of stack handle blocks or NULL for none
263b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* top_shb_;
264b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
265b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Every thread may have an associated JNI environment
266df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  JniEnvironment* jni_env_;
267b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
268b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  State state_;
269b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
27069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Native (kernel) thread id.
271b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pid_t native_id_;
272b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
27369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Native thread handle.
27461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  pthread_t handle_;
2750e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
27669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Initialized to "this". On certain architectures (such as x86) reading
27769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // off of Thread::Current is easy but getting the address of Thread::Current
27869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // is hard. This field can be read off of Thread::Current to give the address.
27969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Thread* self_;
28069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
28169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* runtime_;
28269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
28369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The pending exception or NULL.
2840e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Object* exception_;
2850e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
28645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // A non-zero value is used to tell the current thread to enter a safe point
28745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // at the next poll.
28845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  int suspend_count_;
28945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
29069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The inclusive base of the control stack.
29161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  byte* stack_base_;
29269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
29369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The exclusive limit of the control stack.
29461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  byte* stack_limit_;
29561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
29669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // TLS key used to retrieve the VM thread object.
297b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static pthread_key_t pthread_key_self_;
298b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
29945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when exception_ is set
30045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*exception_entry_point_)(Method** frame);
30145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
30245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when suspend_count_ is non-zero
30345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*suspend_count_entry_point_)(Method** frame);
30445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
3050e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Thread);
3060e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
307b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state);
3080e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
309b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList {
310b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
31161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMaxId = 0xFFFF;
31261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kInvalidId = 0;
31361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMainId = 1;
31461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
31561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static ThreadList* Create();
316b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
31761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  ~ThreadList();
318b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
319b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Register(Thread* thread);
320b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
321b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unregister(Thread* thread);
322b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
323b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock() {
324b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Lock();
325b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
326b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
327b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock() {
328b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Unlock();
329b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
330b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
331b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
332b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList();
333b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
334b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  std::list<Thread*> list_;
335b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
336b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  Mutex* lock_;
337b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
338b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadList);
339b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
340b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
341b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadListLock {
342b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
343b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadListLock(ThreadList* thread_list, Thread* current_thread)
344b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      : thread_list_(thread_list) {
345b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread == NULL) {  // try to get it from TLS
346b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread = Thread::Current();
347b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
348b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    Thread::State old_state;
349b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
350b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = current_thread->GetState();
351b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(Thread::kWaiting);  // TODO: VMWAIT
352b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    } else {
353b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      // happens during VM shutdown
354b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = Thread::kUnknown;  // TODO: something else
355b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
356b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Lock();
357b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
358b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(old_state);
359b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
360b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
361b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
362b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ~ThreadListLock() {
363b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Unlock();
364b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
365b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
366b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
367b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList* thread_list_;
368b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
369b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadListLock);
370b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
371b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
3720e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}  // namespace art
3730e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
3740e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#endif  // ART_SRC_THREAD_H_
375