More threads work.
Adds stubs (and sometimes implementations) for dalvik.system.VMStack and
java.lang.Thread native methods. There was a bug in the dalvik
thread priority setting code, where the current thread and the passed-in
thread were confused.
I've also pulled Mutex and ThreadList out into their own files, and
moved some functionality around (with the aim of having more stuff
private, especially locks).
Change-Id: Ieb0f22669cac3df44ca34f7868f8e7d4dfa09ab6
diff --git a/src/thread.cc b/src/thread.cc
index 78cb1c6..4b477b8 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -17,6 +17,7 @@
#include "object.h"
#include "runtime.h"
#include "runtime_support.h"
+#include "thread_list.h"
#include "utils.h"
namespace art {
@@ -310,74 +311,6 @@
pDebugMe = DebugMe;
}
-Mutex::~Mutex() {
- errno = pthread_mutex_destroy(&mutex_);
- if (errno != 0) {
- PLOG(FATAL) << "pthread_mutex_destroy failed";
- }
-}
-
-Mutex* Mutex::Create(const char* name) {
- Mutex* mu = new Mutex(name);
-#ifndef NDEBUG
- pthread_mutexattr_t debug_attributes;
- errno = pthread_mutexattr_init(&debug_attributes);
- if (errno != 0) {
- PLOG(FATAL) << "pthread_mutexattr_init failed";
- }
-#if VERIFY_OBJECT_ENABLED
- errno = pthread_mutexattr_settype(&debug_attributes, PTHREAD_MUTEX_RECURSIVE);
-#else
- errno = pthread_mutexattr_settype(&debug_attributes, PTHREAD_MUTEX_ERRORCHECK);
-#endif
- if (errno != 0) {
- PLOG(FATAL) << "pthread_mutexattr_settype failed";
- }
- errno = pthread_mutex_init(&mu->mutex_, &debug_attributes);
- if (errno != 0) {
- PLOG(FATAL) << "pthread_mutex_init failed";
- }
- errno = pthread_mutexattr_destroy(&debug_attributes);
- if (errno != 0) {
- PLOG(FATAL) << "pthread_mutexattr_destroy failed";
- }
-#else
- errno = pthread_mutex_init(&mu->mutex_, NULL);
- if (errno != 0) {
- PLOG(FATAL) << "pthread_mutex_init failed";
- }
-#endif
- return mu;
-}
-
-void Mutex::Lock() {
- int result = pthread_mutex_lock(&mutex_);
- if (result != 0) {
- errno = result;
- PLOG(FATAL) << "pthread_mutex_lock failed";
- }
-}
-
-bool Mutex::TryLock() {
- int result = pthread_mutex_trylock(&mutex_);
- if (result == EBUSY) {
- return false;
- }
- if (result != 0) {
- errno = result;
- PLOG(FATAL) << "pthread_mutex_trylock failed";
- }
- return true;
-}
-
-void Mutex::Unlock() {
- int result = pthread_mutex_unlock(&mutex_);
- if (result != 0) {
- errno = result;
- PLOG(FATAL) << "pthread_mutex_unlock failed";
- }
-}
-
void Frame::Next() {
byte* next_sp = reinterpret_cast<byte*>(sp_) +
GetMethod()->GetFrameSizeInBytes();
@@ -478,15 +411,14 @@
jobject thread_group = NULL;
jobject thread_name = env->NewStringUTF(name);
- jint thread_priority = 123;
+ jint thread_priority = GetNativePriority();
jboolean thread_is_daemon = as_daemon;
jclass c = env->FindClass("java/lang/Thread");
jmethodID mid = env->GetMethodID(c, "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
- jobject o = env->NewObject(c, mid, thread_group, thread_name, thread_priority, thread_is_daemon);
- LOG(INFO) << "Created new java.lang.Thread " << (void*) o << " decoded=" << (void*) DecodeJObject(o);
- peer_ = DecodeJObject(o);
+ jobject peer = env->NewObject(c, mid, thread_group, thread_name, thread_priority, thread_is_daemon);
+ peer_ = env->NewGlobalRef(peer);
}
void Thread::InitStackHwm() {
@@ -631,7 +563,6 @@
int suspend_count = 0; // TODO
int debug_suspend_count = 0; // TODO
- void* peer_ = NULL; // TODO
os << " | group=\"" << group_name << "\""
<< " sCount=" << suspend_count
<< " dsCount=" << debug_suspend_count
@@ -706,6 +637,10 @@
Thread::Thread()
: peer_(NULL),
+ wait_mutex_("Thread wait mutex"),
+ wait_monitor_(NULL),
+ interrupted_(false),
+ stack_end_(NULL),
top_of_managed_stack_(),
native_to_managed_record_(NULL),
top_sirt_(NULL),
@@ -714,11 +649,8 @@
suspend_count_(0),
class_loader_override_(NULL) {
InitCpu();
- {
- ThreadListLock mu;
- thin_lock_id_ = Runtime::Current()->GetThreadList()->AllocThreadId();
- }
InitFunctionPointers();
+ thin_lock_id_ = Runtime::Current()->GetThreadList()->AllocThreadId();
}
void MonitorExitVisitor(const Object* object, void*) {
@@ -754,6 +686,10 @@
//dvmUnlockObject(self, lock);
//lock = NULL;
+ // Delete our global reference to the java.lang.Thread.
+ jni_env_->DeleteGlobalRef(peer_);
+ peer_ = NULL;
+
delete jni_env_;
jni_env_ = NULL;
@@ -1057,102 +993,10 @@
<< ",pthread_t=" << thread.GetImpl()
<< ",tid=" << thread.GetTid()
<< ",id=" << thread.GetThinLockId()
- << ",state=" << thread.GetState() << "]";
+ << ",state=" << thread.GetState()
+ << ",peer=" << thread.GetPeer()
+ << "]";
return os;
}
-ThreadList* ThreadList::Create() {
- return new ThreadList;
-}
-
-ThreadList::ThreadList() {
- lock_ = Mutex::Create("ThreadList::Lock");
-}
-
-ThreadList::~ThreadList() {
- if (Contains(Thread::Current())) {
- Runtime::Current()->DetachCurrentThread();
- }
-
- // All threads should have exited and unregistered when we
- // reach this point. This means that all daemon threads had been
- // shutdown cleanly.
- // TODO: dump ThreadList if non-empty.
- CHECK_EQ(list_.size(), 0U);
-
- delete lock_;
- lock_ = NULL;
-}
-
-bool ThreadList::Contains(Thread* thread) {
- return find(list_.begin(), list_.end(), thread) != list_.end();
-}
-
-void ThreadList::Dump(std::ostream& os) {
- MutexLock mu(lock_);
- os << "DALVIK THREADS (" << list_.size() << "):\n";
- typedef std::list<Thread*>::const_iterator It; // TODO: C++0x auto
- for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
- (*it)->Dump(os);
- os << "\n";
- }
-}
-
-void ThreadList::Register(Thread* thread) {
- //LOG(INFO) << "ThreadList::Register() " << *thread;
- MutexLock mu(lock_);
- CHECK(!Contains(thread));
- list_.push_back(thread);
-}
-
-void ThreadList::Unregister() {
- Thread* self = Thread::Current();
-
- //LOG(INFO) << "ThreadList::Unregister() " << self;
- MutexLock mu(lock_);
-
- // Remove this thread from the list.
- CHECK(Contains(self));
- list_.remove(self);
-
- // Delete the Thread* and release the thin lock id.
- uint32_t thin_lock_id = self->thin_lock_id_;
- delete self;
- ReleaseThreadId(thin_lock_id);
-
- // Clear the TLS data, so that thread is recognizably detached.
- // (It may wish to reattach later.)
- errno = pthread_setspecific(Thread::pthread_key_self_, NULL);
- if (errno != 0) {
- PLOG(FATAL) << "pthread_setspecific failed";
- }
-}
-
-void ThreadList::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
- MutexLock mu(lock_);
- typedef std::list<Thread*>::const_iterator It; // TODO: C++0x auto
- for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
- (*it)->VisitRoots(visitor, arg);
- }
-}
-
-uint32_t ThreadList::AllocThreadId() {
- DCHECK_LOCK_HELD(lock_);
- for (size_t i = 0; i < allocated_ids_.size(); ++i) {
- if (!allocated_ids_[i]) {
- allocated_ids_.set(i);
- return i + 1; // Zero is reserved to mean "invalid".
- }
- }
- LOG(FATAL) << "Out of internal thread ids";
- return 0;
-}
-
-void ThreadList::ReleaseThreadId(uint32_t id) {
- DCHECK_LOCK_HELD(lock_);
- --id; // Zero is reserved to mean "invalid".
- DCHECK(allocated_ids_[id]) << id;
- allocated_ids_.reset(id);
-}
-
-} // namespace
+} // namespace art