Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(509)

Unified Diff: runtime/vm/thread.cc

Issue 1439483003: - Add an OSThread structure which is the generic TLS structure for all C++ (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code-review Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/thread.h ('k') | runtime/vm/thread_interrupter.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/thread.cc
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 0d8493798217b5bfd188bfadc6348a523b4e54b6..7bdcff11e4c03a9f6afc8431aa983ad334fecc8d 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -20,183 +20,9 @@
namespace dart {
-// The single thread local key which stores all the thread local data
-// for a thread.
-ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey;
-Thread* Thread::thread_list_head_ = NULL;
-Mutex* Thread::thread_list_lock_ = NULL;
-
-// 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_;
-};
-
-
-void Thread::AddThreadToList(Thread* thread) {
- ASSERT(thread != NULL);
- ASSERT(thread->isolate() == NULL);
- ASSERT(thread_list_lock_ != NULL);
- MutexLocker ml(thread_list_lock_);
-
- ASSERT(thread->thread_list_next_ == NULL);
-
-#if defined(DEBUG)
- {
- // Ensure that we aren't already in the list.
- Thread* current = thread_list_head_;
- while (current != NULL) {
- ASSERT(current != thread);
- current = current->thread_list_next_;
- }
- }
-#endif
-
- // Insert at head of list.
- thread->thread_list_next_ = thread_list_head_;
- thread_list_head_ = thread;
-}
-
-
-void Thread::RemoveThreadFromList(Thread* thread) {
- ASSERT(thread != NULL);
- ASSERT(thread->isolate() == NULL);
- ASSERT(thread_list_lock_ != NULL);
- MutexLocker ml(thread_list_lock_);
-
- // Handle case where |thread| is head of list.
- if (thread_list_head_ == thread) {
- thread_list_head_ = thread->thread_list_next_;
- thread->thread_list_next_ = NULL;
- return;
- }
-
- Thread* current = thread_list_head_;
- Thread* previous = NULL;
-
- // Scan across list and remove |thread|.
- while (current != NULL) {
- previous = current;
- current = current->thread_list_next_;
- if (current == thread) {
- // We found |thread|, remove from list.
- previous->thread_list_next_ = current->thread_list_next_;
- thread->thread_list_next_ = NULL;
- return;
- }
- }
-
- UNREACHABLE();
-}
-
-
-bool Thread::IsThreadInList(ThreadId join_id) {
- if (join_id == OSThread::kInvalidThreadJoinId) {
- return false;
- }
- ThreadIterator it;
- while (it.HasNext()) {
- Thread* t = it.Next();
- // An address test is not sufficient because the allocator may recycle
- // the address for another Thread. Test against the thread's join id.
- if (t->join_id() == join_id) {
- return true;
- }
- }
- return false;
-}
-
-
-static void DeleteThread(void* thread) {
- delete reinterpret_cast<Thread*>(thread);
-}
-
-
-void Thread::Shutdown() {
- if (thread_list_lock_ != NULL) {
- // Delete the current thread.
- Thread* thread = Current();
- ASSERT(thread != NULL);
- delete thread;
- thread = NULL;
- SetCurrent(NULL);
-
- // Check that there are no more threads, then delete the lock.
- {
- MutexLocker ml(thread_list_lock_);
- ASSERT(thread_list_head_ == NULL);
- }
-
- // Clean up TLS.
- OSThread::DeleteThreadLocal(thread_key_);
- thread_key_ = OSThread::kUnsetThreadLocalKey;
-
- // Delete the thread list lock.
- delete thread_list_lock_;
- thread_list_lock_ = NULL;
- }
-}
-
-
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);
- delete log_;
- log_ = NULL;
- RemoveThreadFromList(this);
-}
-
-
-void Thread::InitOnceBeforeIsolate() {
- ASSERT(thread_list_lock_ == NULL);
- thread_list_lock_ = new Mutex();
- ASSERT(thread_list_lock_ != NULL);
- ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey);
- thread_key_ = OSThread::CreateThreadLocal(DeleteThread);
- ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey);
- ASSERT(Thread::Current() == NULL);
- // 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);
-}
-
-
-void Thread::InitOnceAfterObjectAndStubCode() {
- Thread* thread = Thread::Current();
- ASSERT(thread != NULL);
- ASSERT(thread->isolate() == Dart::vm_isolate());
- thread->InitVMConstants();
-}
-
-
-void Thread::SetCurrent(Thread* current) {
- OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current));
-}
-
-
-void Thread::EnsureInit() {
- if (Thread::Current() == NULL) {
- // Allocate a new Thread.
- Thread* thread = new Thread();
- // Verify that current thread was set.
- ASSERT(Thread::Current() == thread);
- }
}
@@ -211,28 +37,30 @@ void Thread::EnsureInit() {
object##_handle_(NULL),
-Thread::Thread(bool init_vm_constants)
- : id_(OSThread::GetCurrentThreadId()),
- join_id_(OSThread::GetCurrentThreadJoinId()),
- trace_id_(OSThread::GetCurrentThreadTraceId()),
- thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
+Thread::Thread(Isolate* isolate)
+ : BaseThread(false),
+ os_thread_(NULL),
isolate_(NULL),
heap_(NULL),
- timeline_block_(NULL),
+ zone_(NULL),
+ top_exit_frame_info_(0),
+ top_resource_(NULL),
+ long_jump_base_(NULL),
store_buffer_block_(NULL),
- log_(new class Log()),
- REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
- REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
+ no_callback_scope_depth_(0),
+#if defined(DEBUG)
+ top_handle_scope_(NULL),
+ no_handle_scope_depth_(0),
+ no_safepoint_scope_depth_(0),
+#endif
reusable_handles_(),
cha_(NULL),
deopt_id_(0),
vm_tag_(0),
pending_functions_(GrowableObjectArray::null()),
- no_callback_scope_depth_(0),
- thread_list_next_(NULL),
- name_(NULL) {
- ClearState();
-
+ REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
+ REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
+ next_(NULL) {
#define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \
member_name = default_init_value;
CACHED_CONSTANTS_LIST(DEFAULT_INIT)
@@ -248,11 +76,11 @@ RUNTIME_ENTRY_LIST(DEFAULT_INIT)
LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT)
#undef DEFAULT_INIT
- if (init_vm_constants) {
+ // We cannot initialize the VM constants here for the vm isolate thread
+ // due to boot strapping issues.
+ if ((Dart::vm_isolate() != NULL) && (isolate != Dart::vm_isolate())) {
InitVMConstants();
}
- SetCurrent(this);
- AddThreadToList(this);
}
@@ -288,12 +116,6 @@ LEAF_RUNTIME_ENTRY_LIST(INIT_VALUE)
}
-void Thread::ClearState() {
- memset(&state_, 0, sizeof(state_));
- pending_functions_ = GrowableObjectArray::null();
-}
-
-
RawGrowableObjectArray* Thread::pending_functions() {
if (pending_functions_ == GrowableObjectArray::null()) {
pending_functions_ = GrowableObjectArray::New(Heap::kOld);
@@ -302,96 +124,67 @@ RawGrowableObjectArray* Thread::pending_functions() {
}
-void Thread::Schedule(Isolate* isolate, bool bypass_safepoint) {
- State st;
- if (isolate->thread_registry()->RestoreStateTo(this, &st, bypass_safepoint)) {
- ASSERT(isolate->thread_registry()->Contains(this));
- state_ = st;
- }
-}
-
-
-void Thread::Unschedule(bool bypass_safepoint) {
- ThreadRegistry* reg = isolate_->thread_registry();
- ASSERT(reg->Contains(this));
- reg->SaveStateFrom(this, state_, bypass_safepoint);
- ClearState();
-}
-
-
void Thread::EnterIsolate(Isolate* isolate) {
- Thread* thread = Thread::Current();
- ASSERT(thread != NULL);
- ASSERT(thread->isolate() == NULL);
- ASSERT(!isolate->HasMutatorThread());
- thread->isolate_ = isolate;
+ const bool kIsMutatorThread = true;
+ const bool kDontBypassSafepoints = false;
+ ThreadRegistry* tr = isolate->thread_registry();
+ Thread* thread = tr->Schedule(
+ isolate, kIsMutatorThread, kDontBypassSafepoints);
isolate->MakeCurrentThreadMutator(thread);
thread->set_vm_tag(VMTag::kVMTagId);
ASSERT(thread->store_buffer_block_ == NULL);
thread->StoreBufferAcquire();
- ASSERT(isolate->heap() != NULL);
- thread->heap_ = isolate->heap();
- thread->Schedule(isolate);
- thread->EnableThreadInterrupts();
}
void Thread::ExitIsolate() {
Thread* thread = Thread::Current();
- // TODO(koda): Audit callers; they should know whether they're in an isolate.
- if (thread == NULL || thread->isolate() == NULL) return;
+ ASSERT(thread != NULL);
+ ASSERT(thread->IsMutatorThread());
#if defined(DEBUG)
ASSERT(!thread->IsAnyReusableHandleScopeActive());
#endif // DEBUG
- thread->DisableThreadInterrupts();
// Clear since GC will not visit the thread once it is unscheduled.
thread->ClearReusableHandles();
- Isolate* isolate = thread->isolate();
- thread->Unschedule();
- // TODO(koda): Move store_buffer_block_ into State.
thread->StoreBufferRelease();
+ Isolate* isolate = thread->isolate();
+ ASSERT(isolate != NULL);
if (isolate->is_runnable()) {
thread->set_vm_tag(VMTag::kIdleTagId);
} else {
thread->set_vm_tag(VMTag::kLoadWaitTagId);
}
+ const bool kIsMutatorThread = true;
+ const bool kDontBypassSafepoints = false;
+ ThreadRegistry* tr = isolate->thread_registry();
+ tr->Unschedule(thread, kIsMutatorThread, kDontBypassSafepoints);
isolate->ClearMutatorThread();
- thread->isolate_ = NULL;
- ASSERT(Isolate::Current() == NULL);
- thread->heap_ = NULL;
}
void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
- Thread* thread = Thread::Current();
- ASSERT(thread != NULL);
- ASSERT(thread->isolate() == NULL);
- thread->isolate_ = isolate;
+ const bool kIsNotMutatorThread = false;
+ ThreadRegistry* tr = isolate->thread_registry();
+ Thread* thread = tr->Schedule(isolate, kIsNotMutatorThread, bypass_safepoint);
ASSERT(thread->store_buffer_block_ == NULL);
// TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
thread->store_buffer_block_ =
thread->isolate()->store_buffer()->PopEmptyBlock();
- ASSERT(isolate->heap() != NULL);
- thread->heap_ = isolate->heap();
- // Do not update isolate->mutator_thread, but perform sanity check:
- // this thread should not be both the main mutator and helper.
+ // This thread should not be the main mutator.
ASSERT(!thread->IsMutatorThread());
- thread->Schedule(isolate, bypass_safepoint);
- thread->EnableThreadInterrupts();
}
void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
Thread* thread = Thread::Current();
- thread->DisableThreadInterrupts();
+ ASSERT(thread != NULL);
+ ASSERT(!thread->IsMutatorThread());
+ thread->StoreBufferRelease();
Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
- thread->Unschedule(bypass_safepoint);
- // TODO(koda): Move store_buffer_block_ into State.
- thread->StoreBufferRelease();
- thread->isolate_ = NULL;
- thread->heap_ = NULL;
- ASSERT(!thread->IsMutatorThread());
+ const bool kIsNotMutatorThread = false;
+ ThreadRegistry* tr = isolate->thread_registry();
+ tr->Unschedule(thread, kIsNotMutatorThread, bypass_safepoint);
}
@@ -459,23 +252,6 @@ bool Thread::HasExitedDartCode() const {
}
-CHA* Thread::cha() const {
- ASSERT(isolate_ != NULL);
- return cha_;
-}
-
-
-void Thread::set_cha(CHA* value) {
- ASSERT(isolate_ != NULL);
- cha_ = value;
-}
-
-
-Log* Thread::log() const {
- return log_;
-}
-
-
template<class C>
C* Thread::AllocateReusableHandle() {
C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle());
@@ -505,34 +281,6 @@ void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) {
}
-void Thread::DisableThreadInterrupts() {
- ASSERT(Thread::Current() == this);
- AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_);
-}
-
-
-void Thread::EnableThreadInterrupts() {
- ASSERT(Thread::Current() == this);
- uintptr_t old =
- AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_);
- if (old == 1) {
- // We just decremented from 1 to 0.
- // Make sure the thread interrupter is awake.
- ThreadInterrupter::WakeUp();
- }
- if (old == 0) {
- // We just decremented from 0, this means we've got a mismatched pair
- // of calls to EnableThreadInterrupts and DisableThreadInterrupts.
- FATAL("Invalid call to Thread::EnableThreadInterrupts()");
- }
-}
-
-
-bool Thread::ThreadInterruptsEnabled() {
- return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0;
-}
-
-
bool Thread::CanLoadFromThread(const Object& object) {
#define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \
if (object.raw() == expr) return true;
@@ -585,48 +333,21 @@ LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET)
}
-ThreadIterator::ThreadIterator() {
- ASSERT(Thread::thread_list_lock_ != NULL);
- // Lock the thread list while iterating.
- Thread::thread_list_lock_->Lock();
- next_ = Thread::thread_list_head_;
-}
-
-
-ThreadIterator::~ThreadIterator() {
- ASSERT(Thread::thread_list_lock_ != NULL);
- // Unlock the thread list when done.
- Thread::thread_list_lock_->Unlock();
-}
-
-
-bool ThreadIterator::HasNext() const {
- ASSERT(Thread::thread_list_lock_ != NULL);
- ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
- return next_ != NULL;
-}
-
-
-Thread* ThreadIterator::Next() {
- ASSERT(Thread::thread_list_lock_ != NULL);
- ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
- Thread* current = next_;
- next_ = next_->thread_list_next_;
- return current;
-}
-
-
DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread)
: StackResource(thread) {
if (thread != NULL) {
- thread->DisableThreadInterrupts();
+ OSThread* os_thread = thread->os_thread();
+ ASSERT(os_thread != NULL);
+ os_thread->DisableThreadInterrupts();
}
}
DisableThreadInterruptsScope::~DisableThreadInterruptsScope() {
if (thread() != NULL) {
- thread()->EnableThreadInterrupts();
+ OSThread* os_thread = thread()->os_thread();
+ ASSERT(os_thread != NULL);
+ os_thread->EnableThreadInterrupts();
}
}
« no previous file with comments | « runtime/vm/thread.h ('k') | runtime/vm/thread_interrupter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698