thread.h revision a8cd9f4a849835af7856f9c9782ea59e11ddef85
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 "logging.h"
11578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "macros.h"
12b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom#include "mem_map.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  void SetOwner(Thread* thread) { owner_ = thread; }
450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
4718c0753c1659629021b4becdaa3f6ea81aecce35Elliott Hughes  explicit Mutex(const char* name) : name_(name), owner_(NULL) {}
4818c0753c1659629021b4becdaa3f6ea81aecce35Elliott Hughes
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
83a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  Object** Handles() {
84a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers    return handles_;
85a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  }
86a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
87b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of length within SHB, used by generated code
88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t NumberOfReferencesOffset() {
89b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return OFFSETOF_MEMBER(StackHandleBlock, number_of_references_);
90b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
91b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
92b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of link within SHB, used by generated code
93b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static size_t LinkOffset() {
94b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return OFFSETOF_MEMBER(StackHandleBlock, link_);
95b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
96b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
97b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private:
98b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock() {}
99b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
100b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t number_of_references_;
101b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* link_;
102b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
103a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  // Fake array, really allocated and filled in by jni_compiler.
104a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  Object* handles_[0];
105a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
106b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  DISALLOW_COPY_AND_ASSIGN(StackHandleBlock);
107b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
108b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1096de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogersstruct NativeToManagedRecord {
1106de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  NativeToManagedRecord* link;
1116de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void* last_top_of_managed_stack;
1126de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers};
1136de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
1140e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread {
1150e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public:
116b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  enum State {
117b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kUnknown = -1,
118b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kNew,
119b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kRunnable,
120b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kBlocked,
121b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kWaiting,
122b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTimedWaiting,
123b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kNative,
124b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    kTerminated,
125b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
126b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
12761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const size_t kDefaultStackSize = 64 * KB;
12861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
12961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread.
130b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom  static Thread* Create(const Runtime* runtime);
13161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
13261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  // Creates a new thread from the calling thread.
133515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes  static Thread* Attach(const Runtime* runtime);
134b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
135b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static Thread* Current() {
136d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    void* thread = pthread_getspecific(Thread::pthread_key_self_);
137d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro    return reinterpret_cast<Thread*>(thread);
1380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
140b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  uint32_t GetId() const {
141b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return id_;
142b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
143b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
144b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pid_t GetNativeId() const {
145b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return native_id_;
1460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  bool IsExceptionPending() const {
149b20a554613609dc372073d2ebd9fbc3925a429f5Elliott Hughes    return exception_ != NULL;
1500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1520e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Object* GetException() const {
1530e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    return exception_;
1540e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1550e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
1560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void SetException(Object* new_exception) {
1570e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    CHECK(new_exception != NULL);
1580e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    // TODO: CHECK(exception_ == NULL);
1590e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    exception_ = new_exception;  // TODO
1600e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1610e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
162a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes  void ThrowNewException(const char* exception_class_name, const char* fmt, ...)
163a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes      __attribute__ ((format(printf, 3, 4)));
164a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes
1650e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  void ClearException() {
1660e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro    exception_ = NULL;
1670e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  }
1680e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
16945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception within Thread, used by generated code
17045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionOffset() {
17145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_));
17245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
17345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
174b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetName(const char* name);
175b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
176b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Suspend();
177b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
178b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  bool IsSuspended();
179b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
180b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Resume();
181b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
182b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static bool Init();
183b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
18469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* GetRuntime() const {
18569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro    return runtime_;
18669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  }
18769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
188330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes  State GetState() const {
189b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    return state_;
190b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
191b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
192b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void SetState(State new_state) {
193b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    state_ = new_state;
194b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
195b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
19645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountOffset() {
19745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_));
19845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
19945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
200b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of state within Thread, used by generated code
201b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset StateOffset() {
202b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, state_));
203b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
204b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
205b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // JNI methods
20640ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes  JNIEnv* GetJniEnv() const {
207b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return jni_env_;
208b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
209b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
210b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of JNI environment within Thread, used by generated code
211b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset JniEnvOffset() {
212b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_));
213b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
214b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
21545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of top of managed stack address, used by generated code
21645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset TopOfManagedStackOffset() {
21745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_));
21845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
21945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
220b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Offset of top stack handle block within Thread, used by generated code
221b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  static ThreadOffset TopShbOffset() {
222b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, top_shb_));
223b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
224b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
225b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Number of references allocated in StackHandleBlocks on this thread
226a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  size_t NumShbHandles();
227a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers
228a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  // Is the given obj in this thread's stack handle blocks?
229a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers  bool ShbContains(jobject obj);
230b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
23145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of exception_entry_point_ within Thread, used by generated code
23245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset ExceptionEntryPointOffset() {
23345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_entry_point_));
23445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
23545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
23645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterExceptionEntryPoint(void (*handler)(Method**)) {
23745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    exception_entry_point_ = handler;
23845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
23945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
24045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Offset of suspend_count_entry_point_ within Thread, used by generated code
24145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  static ThreadOffset SuspendCountEntryPointOffset() {
24245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_entry_point_));
24345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
24445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
24545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void RegisterSuspendCountEntryPoint(void (*handler)(Method**)) {
24645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    suspend_count_entry_point_ = handler;
24745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
24845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
24945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Increasing the suspend count, will cause the thread to run to safepoint
25045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void IncrementSuspendCount() { suspend_count_++; }
25145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void DecrementSuspendCount() { suspend_count_--; }
25245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
2536de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // Linked list recording transitions from native to managed code
2546de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void PushNativeToManagedRecord(NativeToManagedRecord* record) {
2556de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    record->last_top_of_managed_stack = top_of_managed_stack_;
2566de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    record->link = native_to_managed_record_;
2576de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    native_to_managed_record_ = record;
2586de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    top_of_managed_stack_ = NULL;
2596de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  }
2606de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  void PopNativeToManagedRecord(const NativeToManagedRecord& record) {
2616de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    native_to_managed_record_ = record.link;
2626de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers    top_of_managed_stack_ = record.last_top_of_managed_stack;
2636de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  }
2646de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
2650e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private:
26640ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes  Thread()
267330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes      : id_(1234),
2686de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers        top_of_managed_stack_(NULL),
2696de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers        native_to_managed_record_(NULL),
270330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        top_shb_(NULL),
271330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        jni_env_(NULL),
272330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        exception_(NULL),
273330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes        suspend_count_(0) {
274df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  }
27569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
276df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  ~Thread() {
277df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers    delete jni_env_;
278b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
2790e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
280b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void InitCpu();
281b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
28269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Managed thread id.
28369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  uint32_t id_;
284b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
28545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Top of the managed stack, written out prior to the state transition from
28645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // kRunnable to kNative. Uses include to give the starting point for scanning
28745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // a managed stack when a thread is in native code.
28845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void* top_of_managed_stack_;
28945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
2906de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // A linked list (of stack allocated records) recording transitions from
2916de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  // native to managed code.
2926de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers  NativeToManagedRecord* native_to_managed_record_;
2936de0860c491d390b7a53be436519ef2d9234c4c9Ian Rogers
294b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Top of linked list of stack handle blocks or NULL for none
295b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  StackHandleBlock* top_shb_;
296b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
297b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Every thread may have an associated JNI environment
29840ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes  JNIEnv* jni_env_;
299b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
300b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  State state_;
301b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
30269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Native (kernel) thread id.
303b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  pid_t native_id_;
304b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
30569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Native thread handle.
30661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  pthread_t handle_;
3070e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
30869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // Initialized to "this". On certain architectures (such as x86) reading
30969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // off of Thread::Current is easy but getting the address of Thread::Current
31069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // is hard. This field can be read off of Thread::Current to give the address.
31169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Thread* self_;
31269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
31369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  Runtime* runtime_;
31469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
31569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The pending exception or NULL.
3160e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  Object* exception_;
3170e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
31845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // A non-zero value is used to tell the current thread to enter a safe point
31945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // at the next poll.
32045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  int suspend_count_;
32145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
322b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom  // The memory mapping of the stack for non-attached threads.
323b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom  scoped_ptr<MemMap> stack_;
324b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom
32569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The inclusive base of the control stack.
32661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  byte* stack_base_;
32769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro
32869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // The exclusive limit of the control stack.
32961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  byte* stack_limit_;
33061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
33169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro  // TLS key used to retrieve the VM thread object.
332b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  static pthread_key_t pthread_key_self_;
333b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
33445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when exception_ is set
33545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*exception_entry_point_)(Method** frame);
33645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
33745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry point called when suspend_count_ is non-zero
33845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void (*suspend_count_entry_point_)(Method** frame);
33945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
3400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(Thread);
3410e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro};
342330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread);
343b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state);
3440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
345b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList {
346b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
34761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMaxId = 0xFFFF;
34861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kInvalidId = 0;
34961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static const int kMainId = 1;
35061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro
35161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  static ThreadList* Create();
352b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
35361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro  ~ThreadList();
354b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
355b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Register(Thread* thread);
356b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
357b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unregister(Thread* thread);
358b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
359b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Lock() {
360b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Lock();
361b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
362b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
363b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  void Unlock() {
364b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    lock_->Unlock();
365b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  };
366b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
367b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
368b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList();
369b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
370b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  std::list<Thread*> list_;
371b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
372b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  Mutex* lock_;
373b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
374b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadList);
375b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
376b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
377b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadListLock {
378b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public:
379b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadListLock(ThreadList* thread_list, Thread* current_thread)
380b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      : thread_list_(thread_list) {
381b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread == NULL) {  // try to get it from TLS
382b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread = Thread::Current();
383b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
384b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    Thread::State old_state;
385b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
386b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = current_thread->GetState();
387b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(Thread::kWaiting);  // TODO: VMWAIT
388b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    } else {
389b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      // happens during VM shutdown
390b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      old_state = Thread::kUnknown;  // TODO: something else
391b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
392b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Lock();
393b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    if (current_thread != NULL) {
394b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro      current_thread->SetState(old_state);
395b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    }
396b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
397b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
398b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ~ThreadListLock() {
399b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro    thread_list_->Unlock();
400b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  }
401b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
402b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private:
403b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  ThreadList* thread_list_;
404b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
405b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro  DISALLOW_COPY_AND_ASSIGN(ThreadListLock);
406b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro};
407b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro
4080e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}  // namespace art
4090e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro
4100e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#endif  // ART_SRC_THREAD_H_
411