Index: runtime/vm/os_thread.cc |
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc |
index 3789a60140a269b738a4ccdd5ebedbe8f3834573..766bbbed97d9f46800e24be459df8d8e0f2b6fe0 100644 |
--- a/runtime/vm/os_thread.cc |
+++ b/runtime/vm/os_thread.cc |
@@ -16,6 +16,7 @@ namespace dart { |
ThreadLocalKey OSThread::thread_key_ = kUnsetThreadLocalKey; |
OSThread* OSThread::thread_list_head_ = NULL; |
Mutex* OSThread::thread_list_lock_ = NULL; |
+bool OSThread::creation_enabled_ = false; |
OSThread::OSThread() : |
@@ -31,7 +32,18 @@ OSThread::OSThread() : |
log_(new class Log()), |
stack_base_(0), |
thread_(NULL) { |
- AddThreadToList(this); |
+} |
+ |
+ |
+OSThread* OSThread::CreateOSThread() { |
+ ASSERT(thread_list_lock_ != NULL); |
+ MutexLocker ml(thread_list_lock_); |
+ if (!creation_enabled_) { |
+ return NULL; |
+ } |
+ OSThread* os_thread = new OSThread(); |
+ AddThreadToListLocked(os_thread); |
+ return os_thread; |
} |
@@ -92,8 +104,12 @@ void OSThread::InitOnce() { |
thread_key_ = CreateThreadLocal(DeleteThread); |
ASSERT(thread_key_ != kUnsetThreadLocalKey); |
+ // Enable creation of OSThread structures in the VM. |
+ EnableOSThreadCreation(); |
+ |
// Create a new OSThread strcture and set it as the TLS. |
- OSThread* os_thread = new OSThread(); |
+ OSThread* os_thread = CreateOSThread(); |
+ ASSERT(os_thread != NULL); |
OSThread::SetCurrent(os_thread); |
os_thread->set_name("Dart_Initialize"); |
} |
@@ -115,10 +131,12 @@ void OSThread::Cleanup() { |
OSThread* OSThread::CreateAndSetUnknownThread() { |
- ASSERT(OSThread::Current() == NULL); |
- OSThread* os_thread = new OSThread(); |
- OSThread::SetCurrent(os_thread); |
- os_thread->set_name("Unknown"); |
+ ASSERT(OSThread::GetCurrentTLS() == NULL); |
+ OSThread* os_thread = CreateOSThread(); |
+ if (os_thread != NULL) { |
+ OSThread::SetCurrent(os_thread); |
+ os_thread->set_name("Unknown"); |
+ } |
return os_thread; |
} |
@@ -141,17 +159,29 @@ bool OSThread::IsThreadInList(ThreadJoinId join_id) { |
} |
+void OSThread::DisableOSThreadCreation() { |
+ MutexLocker ml(thread_list_lock_); |
+ creation_enabled_ = false; |
+} |
+ |
+ |
+void OSThread::EnableOSThreadCreation() { |
+ MutexLocker ml(thread_list_lock_); |
+ creation_enabled_ = true; |
+} |
+ |
+ |
OSThread* OSThread::GetOSThreadFromThread(Thread* thread) { |
ASSERT(thread->os_thread() != NULL); |
return thread->os_thread(); |
} |
-void OSThread::AddThreadToList(OSThread* thread) { |
+void OSThread::AddThreadToListLocked(OSThread* thread) { |
ASSERT(thread != NULL); |
ASSERT(thread_list_lock_ != NULL); |
- MutexLocker ml(thread_list_lock_); |
- |
+ ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); |
+ ASSERT(creation_enabled_); |
ASSERT(thread->thread_list_next_ == NULL); |
#if defined(DEBUG) |
@@ -172,6 +202,7 @@ void OSThread::AddThreadToList(OSThread* thread) { |
void OSThread::RemoveThreadFromList(OSThread* thread) { |
+ bool final_thread = false; |
{ |
ASSERT(thread != NULL); |
ASSERT(thread_list_lock_ != NULL); |
@@ -189,6 +220,7 @@ void OSThread::RemoveThreadFromList(OSThread* thread) { |
previous->thread_list_next_ = current->thread_list_next_; |
} |
thread->thread_list_next_ = NULL; |
+ final_thread = !creation_enabled_ && (thread_list_head_ == NULL); |
break; |
} |
previous = current; |
@@ -197,7 +229,7 @@ void OSThread::RemoveThreadFromList(OSThread* thread) { |
} |
// Check if this is the last thread. The last thread does a cleanup |
// which removes the thread local key and the associated mutex. |
- if (thread_list_head_ == NULL) { |
+ if (final_thread) { |
Cleanup(); |
} |
} |