Chromium Code Reviews| 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..703c18c90cf0b8a763a04c804b8b2eb7d97e54a4 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,88 @@ void Monitor::NotifyAll() { |
| data_.SignalAndRemoveAllWaiters(); |
| } |
| -// This function is defined in thread.cc. |
| -extern void ThreadCleanupOnExit(); |
| -} // namespace dart |
| +void ThreadLocalData::AddThreadLocal(ThreadLocalKey key, |
| + ThreadDestructor destructor) { |
| + if (thread_locals_ == NULL) { |
| + return; |
| + } |
|
siva
2015/10/15 22:42:48
Should this be
ASSERT(thread_locals_ != NULL);
Cutch
2015/10/16 16:53:25
Done.
|
| + 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(); |
| +} |
| -// 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::RemoveThreadLocal(ThreadLocalKey key) { |
| + if (thread_locals_ == NULL) { |
| + return; |
| + } |
|
siva
2015/10/15 22:42:48
Ditto comment.
Cutch
2015/10/16 16:53:25
Done.
|
| + 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(); |
| +} |
| + |
| + |
| +void ThreadLocalData::RunDestructors() { |
| + ASSERT(mutex_ != NULL); |
| + mutex_->Lock(); |
| + ASSERT(thread_locals_ != NULL); |
| + for (intptr_t i = 0; i < thread_locals_->length(); i++) { |
| + const ThreadLocalEntry& entry = thread_locals_->At(i); |
| + void* p = reinterpret_cast<void*>(OSThread::GetThreadLocal(entry.key())); |
| + 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>(); |
| +} |
| + |
| + |
| +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 +599,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(); |
| } |
| } |