Index: runtime/vm/thread.cc |
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc |
index fdd3272e340ecf1029b9a87c5c067bbcd3b80440..260f59088ae169ec397713235d46287c90f0e43b 100644 |
--- a/runtime/vm/thread.cc |
+++ b/runtime/vm/thread.cc |
@@ -21,6 +21,24 @@ namespace dart { |
ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; |
+// Remove |thread| from each isolate's thread registry. |
+class ThreadPruner : public IsolateVisitor { |
+ public: |
+ explicit ThreadPruner(Thread* thread) |
+ : thread_(thread) { |
+ ASSERT(thread_ != NULL); |
+ } |
+ |
+ void VisitIsolate(Isolate* isolate) { |
+ ThreadRegistry* registry = isolate->thread_registry(); |
+ ASSERT(registry != NULL); |
+ registry->PruneThread(thread_); |
+ } |
+ private: |
+ Thread* thread_; |
+}; |
+ |
+ |
static void DeleteThread(void* thread) { |
delete reinterpret_cast<Thread*>(thread); |
} |
@@ -29,6 +47,9 @@ static void DeleteThread(void* thread) { |
Thread::~Thread() { |
// We should cleanly exit any isolate before destruction. |
ASSERT(isolate_ == NULL); |
+ // Clear |this| from all isolate's thread registry. |
+ ThreadPruner pruner(this); |
+ Isolate::VisitIsolates(&pruner); |
} |
@@ -37,8 +58,11 @@ void Thread::InitOnceBeforeIsolate() { |
thread_key_ = OSThread::CreateThreadLocal(DeleteThread); |
ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); |
ASSERT(Thread::Current() == NULL); |
- // Postpone initialization of VM constants for this first thread. |
- SetCurrent(new Thread(false)); |
+ // Allocate a new Thread and postpone initialization of VM constants for |
+ // this first thread. |
+ Thread* thread = new Thread(false); |
+ // Verify that current thread was set. |
+ ASSERT(Thread::Current() == thread); |
} |
@@ -57,7 +81,10 @@ void Thread::SetCurrent(Thread* current) { |
void Thread::EnsureInit() { |
if (Thread::Current() == NULL) { |
- SetCurrent(new Thread()); |
+ // Allocate a new Thread. |
+ Thread* thread = new Thread(); |
+ // Verify that current thread was set. |
+ ASSERT(Thread::Current() == thread); |
} |
} |
@@ -74,7 +101,8 @@ void Thread::CleanUp() { |
Thread::Thread(bool init_vm_constants) |
- : isolate_(NULL), |
+ : id_(OSThread::GetCurrentThreadId()), |
+ isolate_(NULL), |
store_buffer_block_(NULL) { |
ClearState(); |
#define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ |
@@ -84,6 +112,7 @@ CACHED_CONSTANTS_LIST(DEFAULT_INIT) |
if (init_vm_constants) { |
InitVMConstants(); |
} |
+ SetCurrent(this); |
} |
@@ -131,15 +160,6 @@ void Thread::EnterIsolate(Isolate* isolate) { |
ASSERT(isolate->heap() != NULL); |
thread->heap_ = isolate->heap(); |
thread->Schedule(isolate); |
- ASSERT(thread->thread_state() == NULL); |
- InterruptableThreadState* thread_state = |
- ThreadInterrupter::GetCurrentThreadState(); |
-#if defined(DEBUG) |
- thread->set_thread_state(NULL); // Exclude thread itself from the dupe check. |
- Isolate::CheckForDuplicateThreadState(thread_state); |
- thread->set_thread_state(thread_state); |
-#endif |
- ASSERT(thread_state != NULL); |
// TODO(koda): Migrate profiler interface to use Thread. |
Profiler::BeginExecution(isolate); |
} |
@@ -151,7 +171,6 @@ void Thread::ExitIsolate() { |
if (thread == NULL || thread->isolate() == NULL) return; |
Isolate* isolate = thread->isolate(); |
Profiler::EndExecution(isolate); |
- thread->set_thread_state(NULL); |
thread->Unschedule(); |
// TODO(koda): Move store_buffer_block_ into State. |
thread->StoreBufferRelease(); |
@@ -259,6 +278,32 @@ void Thread::set_cha(CHA* value) { |
} |
+void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, |
+ void* data) { |
+ ASSERT(Thread::Current() == this); |
+ thread_interrupt_callback_ = callback; |
+ thread_interrupt_data_ = data; |
+} |
+ |
+ |
+bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, |
+ void** data) const { |
+#if defined(TARGET_OS_WINDOWS) |
+ // On Windows we expect this to be called from the thread interrupter thread. |
+ ASSERT(id() != OSThread::GetCurrentThreadId()); |
+#else |
+ // On posix platforms, we expect this to be called from signal handler. |
+ ASSERT(id() == OSThread::GetCurrentThreadId()); |
+#endif |
+ ASSERT(callback != NULL); |
+ ASSERT(data != NULL); |
+ *callback = thread_interrupt_callback_; |
+ *data = thread_interrupt_data_; |
+ return (*callback != NULL) && |
+ (*data != NULL); |
+} |
+ |
+ |
bool Thread::CanLoadFromThread(const Object& object) { |
#define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ |
if (object.raw() == expr) return true; |