| 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;
|
|
|