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

Unified Diff: runtime/vm/os_thread_win.cc

Issue 1410493002: Complete support for Windows TLS destructors (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 months 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_win.h ('k') | runtime/vm/os_win.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/os_thread_win.cc
diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc
index bcb5a5398138c38b67cd9f76942c2d0d9d2d755f..d2ae84c0c5c67ea87d69a8584cc50849f5016f44 100644
--- a/runtime/vm/os_thread_win.cc
+++ b/runtime/vm/os_thread_win.cc
@@ -5,6 +5,7 @@
#include "platform/globals.h" // NOLINT
#if defined(TARGET_OS_WINDOWS)
+#include "vm/growable_array.h"
#include "vm/os_thread.h"
#include <process.h> // NOLINT
@@ -73,11 +74,12 @@ ThreadLocalKey OSThread::kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES;
ThreadId OSThread::kInvalidThreadId = 0;
ThreadJoinId OSThread::kInvalidThreadJoinId = 0;
-ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor unused) {
+ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor destructor) {
ThreadLocalKey key = TlsAlloc();
if (key == kUnsetThreadLocalKey) {
FATAL1("TlsAlloc failed %d", GetLastError());
}
+ ThreadLocalData::AddThreadLocal(key, destructor);
return key;
}
@@ -88,6 +90,7 @@ void OSThread::DeleteThreadLocal(ThreadLocalKey key) {
if (!result) {
FATAL1("TlsFree failed %d", GetLastError());
}
+ ThreadLocalData::RemoveThreadLocal(key);
}
@@ -482,14 +485,87 @@ void Monitor::NotifyAll() {
data_.SignalAndRemoveAllWaiters();
}
-// This function is defined in thread.cc.
-extern void ThreadCleanupOnExit();
-} // namespace dart
+void ThreadLocalData::AddThreadLocal(ThreadLocalKey key,
+ ThreadDestructor destructor) {
+ ASSERT(thread_locals_ != NULL);
+ if (destructor == NULL) {
+ // We only care about thread locals with destructors.
+ return;
+ }
+ mutex_->Lock();
+#if defined(DEBUG)
+ // Verify that we aren't added twice.
+ for (intptr_t i = 0; i < thread_locals_->length(); i++) {
+ const ThreadLocalEntry& entry = thread_locals_->At(i);
+ ASSERT(entry.key() != key);
+ }
+#endif
+ // Add to list.
+ thread_locals_->Add(ThreadLocalEntry(key, destructor));
+ mutex_->Unlock();
+}
+
+
+void ThreadLocalData::RemoveThreadLocal(ThreadLocalKey key) {
+ ASSERT(thread_locals_ != NULL); mutex_->Lock();
+ intptr_t i = 0;
+ for (; i < thread_locals_->length(); i++) {
+ const ThreadLocalEntry& entry = thread_locals_->At(i);
+ if (entry.key() == key) {
+ break;
+ }
+ }
+ if (i == thread_locals_->length()) {
+ // Not found.
+ mutex_->Unlock();
+ return;
+ }
+ thread_locals_->RemoveAt(i);
+ mutex_->Unlock();
+}
+
+
+// This function is executed on the thread that is exiting. It is invoked
+// by |OnDartThreadExit| (see below for notes on TLS destructors on Windows).
+void ThreadLocalData::RunDestructors() {
+ ASSERT(thread_locals_ != NULL);
+ ASSERT(mutex_ != NULL);
+ mutex_->Lock();
+ for (intptr_t i = 0; i < thread_locals_->length(); i++) {
+ const ThreadLocalEntry& entry = thread_locals_->At(i);
+ // We access the exiting thread's TLS variable here.
+ void* p = reinterpret_cast<void*>(OSThread::GetThreadLocal(entry.key()));
+ // We invoke the constructor here.
+ entry.destructor()(p);
+ }
+ mutex_->Unlock();
+}
+
+
+Mutex* ThreadLocalData::mutex_ = NULL;
+MallocGrowableArray<ThreadLocalEntry>* ThreadLocalData::thread_locals_ = NULL;
+
+
+void ThreadLocalData::InitOnce() {
+ mutex_ = new Mutex();
+ thread_locals_ = new MallocGrowableArray<ThreadLocalEntry>();
+}
-// NOTE: We still do not respect arbitrary TLS destructors on Windows, but,
-// we do run known TLS cleanup functions. See |OnThreadExit| below for
-// the list of functions that are called.
+
+void ThreadLocalData::Shutdown() {
+ if (mutex_ != NULL) {
+ delete mutex_;
+ mutex_ = NULL;
+ }
+ if (thread_locals_ != NULL) {
+ delete thread_locals_;
+ thread_locals_ = NULL;
+ }
+}
+
+
+} // namespace dart
// The following was adapted from Chromium:
// src/base/threading/thread_local_storage_win.cc
@@ -522,7 +598,7 @@ void NTAPI OnDartThreadExit(PVOID module, DWORD reason, PVOID reserved) {
// On XP SP0 & SP1, the DLL_PROCESS_ATTACH is never seen. It is sent on SP2+
// and on W2K and W2K3. So don't assume it is sent.
if (DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason) {
- dart::ThreadCleanupOnExit();
+ dart::ThreadLocalData::RunDestructors();
dart::MonitorWaitData::ThreadExit();
}
}
« no previous file with comments | « runtime/vm/os_thread_win.h ('k') | runtime/vm/os_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698