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

Unified Diff: runtime/vm/os_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/os_thread.h ('k') | runtime/vm/os_thread_android.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/os_thread.cc
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6f3d8e48d5f9c94d9a81e20b9522a9c5dda1e7cb
--- /dev/null
+++ b/runtime/vm/os_thread.cc
@@ -0,0 +1,231 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/os_thread.h"
+
+#include "vm/atomic.h"
+#include "vm/lockers.h"
+#include "vm/log.h"
+#include "vm/thread_interrupter.h"
+
+namespace dart {
+
+// The single thread local key which stores all the thread local data
+// for a thread.
+ThreadLocalKey OSThread::thread_key_ = OSThread::kUnsetThreadLocalKey;
+OSThread* OSThread::thread_list_head_ = NULL;
+Mutex* OSThread::thread_list_lock_ = NULL;
+
+
+OSThread::OSThread() :
+ BaseThread(true),
+ id_(OSThread::GetCurrentThreadId()),
+ join_id_(OSThread::GetCurrentThreadJoinId()),
+ trace_id_(OSThread::GetCurrentThreadTraceId()),
+ name_(NULL),
+ timeline_block_lock_(new Mutex()),
+ timeline_block_(NULL),
+ thread_list_next_(NULL),
+ thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
+ log_(new class Log()),
+ stack_base_(0),
+ thread_(NULL) {
+ AddThreadToList(this);
+}
+
+
+OSThread::~OSThread() {
+ RemoveThreadFromList(this);
+ delete log_;
+ log_ = NULL;
+ if (Timeline::recorder() != NULL) {
+ Timeline::recorder()->FinishBlock(timeline_block_);
+ }
+ timeline_block_ = NULL;
+ delete timeline_block_lock_;
+}
+
+
+void OSThread::DisableThreadInterrupts() {
+ ASSERT(OSThread::Current() == this);
+ AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_);
+}
+
+
+void OSThread::EnableThreadInterrupts() {
+ ASSERT(OSThread::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 OSThread::EnableThreadInterrupts()");
+ }
+}
+
+
+bool OSThread::ThreadInterruptsEnabled() {
+ return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0;
+}
+
+
+static void DeleteThread(void* thread) {
+ delete reinterpret_cast<OSThread*>(thread);
+}
+
+
+void OSThread::InitOnce() {
+ // Allocate the global OSThread lock.
+ ASSERT(thread_list_lock_ == NULL);
+ thread_list_lock_ = new Mutex();
+ ASSERT(thread_list_lock_ != NULL);
+
+ // Create the thread local key.
+ ASSERT(thread_key_ == kUnsetThreadLocalKey);
+ thread_key_ = CreateThreadLocal(DeleteThread);
+ ASSERT(thread_key_ != kUnsetThreadLocalKey);
+
+ // Create a new OSThread strcture and set it as the TLS.
+ OSThread* os_thread = new OSThread();
+ OSThread::SetCurrent(os_thread);
+ os_thread->set_name("Dart_Initialize");
+}
+
+
+void OSThread::Cleanup() {
+ if (thread_list_lock_ != NULL) {
+ // Delete the thread local key.
+ ASSERT(thread_key_ != kUnsetThreadLocalKey);
+ DeleteThreadLocal(thread_key_);
+ thread_key_ = kUnsetThreadLocalKey;
+
+ // Delete the global OSThread lock.
+ ASSERT(thread_list_lock_ != NULL);
+ delete thread_list_lock_;
+ thread_list_lock_ = NULL;
+ }
+}
+
+
+bool OSThread::IsThreadInList(ThreadId join_id) {
+ if (join_id == OSThread::kInvalidThreadJoinId) {
+ return false;
+ }
+ OSThreadIterator it;
+ while (it.HasNext()) {
+ ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
+ OSThread* 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;
+}
+
+
+OSThread* OSThread::GetOSThreadFromThread(Thread* thread) {
+ ASSERT(thread->os_thread() != NULL);
+ return thread->os_thread();
+}
+
+
+void OSThread::AddThreadToList(OSThread* thread) {
+ ASSERT(thread != 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.
+ OSThread* 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 OSThread::RemoveThreadFromList(OSThread* thread) {
+ {
+ ASSERT(thread != NULL);
+ ASSERT(thread_list_lock_ != NULL);
+ MutexLocker ml(thread_list_lock_);
+ OSThread* current = thread_list_head_;
+ OSThread* previous = NULL;
+
+ // Scan across list and remove |thread|.
+ while (current != NULL) {
+ if (current == thread) {
+ // We found |thread|, remove from list.
+ if (previous == NULL) {
+ thread_list_head_ = thread->thread_list_next_;
+ } else {
+ previous->thread_list_next_ = current->thread_list_next_;
+ }
+ thread->thread_list_next_ = NULL;
+ break;
+ }
+ previous = current;
+ current = current->thread_list_next_;
+ }
+ }
+ // 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) {
+ Cleanup();
+ }
+}
+
+
+void OSThread::SetCurrent(OSThread* current) {
+ OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current));
+}
+
+
+OSThreadIterator::OSThreadIterator() {
+ ASSERT(OSThread::thread_list_lock_ != NULL);
+ // Lock the thread list while iterating.
+ OSThread::thread_list_lock_->Lock();
+ next_ = OSThread::thread_list_head_;
+}
+
+
+OSThreadIterator::~OSThreadIterator() {
+ ASSERT(OSThread::thread_list_lock_ != NULL);
+ // Unlock the thread list when done.
+ OSThread::thread_list_lock_->Unlock();
+}
+
+
+bool OSThreadIterator::HasNext() const {
+ ASSERT(OSThread::thread_list_lock_ != NULL);
+ ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
+ return next_ != NULL;
+}
+
+
+OSThread* OSThreadIterator::Next() {
+ ASSERT(OSThread::thread_list_lock_ != NULL);
+ ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
+ OSThread* current = next_;
+ next_ = next_->thread_list_next_;
+ return current;
+}
+
+} // namespace dart
« no previous file with comments | « runtime/vm/os_thread.h ('k') | runtime/vm/os_thread_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698