OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/thread.h" | 5 #include "vm/thread.h" |
6 | 6 |
7 #include "vm/isolate.h" | 7 #include "vm/isolate.h" |
8 #include "vm/os_thread.h" | 8 #include "vm/os_thread.h" |
| 9 #include "vm/profiler.h" |
| 10 #include "vm/thread_interrupter.h" |
9 | 11 |
10 | 12 |
11 namespace dart { | 13 namespace dart { |
12 | 14 |
13 // The single thread local key which stores all the thread local data | 15 // The single thread local key which stores all the thread local data |
14 // for a thread. | 16 // for a thread. |
15 // TODO(koda): Can we merge this with ThreadInterrupter::thread_state_key_? | 17 // TODO(koda): Can we merge this with ThreadInterrupter::thread_state_key_? |
16 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; | 18 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; |
17 | 19 |
18 | 20 |
19 void Thread::InitOnce() { | 21 void Thread::InitOnce() { |
20 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); | 22 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); |
21 thread_key_ = OSThread::CreateThreadLocal(); | 23 thread_key_ = OSThread::CreateThreadLocal(); |
22 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); | 24 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); |
23 } | 25 } |
24 | 26 |
25 | 27 |
26 void Thread::SetCurrent(Thread* current) { | 28 void Thread::SetCurrent(Thread* current) { |
27 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); | 29 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); |
28 } | 30 } |
29 | 31 |
| 32 |
| 33 void Thread::EnsureInit() { |
| 34 if (Thread::Current() == NULL) { |
| 35 SetCurrent(new Thread()); |
| 36 } |
| 37 } |
| 38 |
| 39 |
| 40 void Thread::CleanUp() { |
| 41 // We currently deallocate the Thread, to ensure that embedder threads don't |
| 42 // leak the Thread structure. An alternative approach would be to clear and |
| 43 // reuse it, but register a destructor at the OS level. |
| 44 Thread* current = Current(); |
| 45 if (current != NULL) { |
| 46 delete current; |
| 47 } |
| 48 SetCurrent(NULL); |
| 49 } |
| 50 |
| 51 |
| 52 void Thread::EnterIsolate(Isolate* isolate) { |
| 53 EnsureInit(); |
| 54 Thread* thread = Thread::Current(); |
| 55 ASSERT(thread->isolate() == NULL); |
| 56 ASSERT(isolate->mutator_thread() == NULL); |
| 57 isolate->set_mutator_thread(thread); |
| 58 // TODO(koda): Migrate thread_state_ and profile_data_ to Thread, to allow |
| 59 // helper threads concurrent with mutator. |
| 60 ASSERT(isolate->thread_state() == NULL); |
| 61 InterruptableThreadState* thread_state = |
| 62 ThreadInterrupter::GetCurrentThreadState(); |
| 63 #if defined(DEBUG) |
| 64 Isolate::CheckForDuplicateThreadState(thread_state); |
| 65 #endif |
| 66 ASSERT(thread_state != NULL); |
| 67 Profiler::BeginExecution(isolate); |
| 68 isolate->set_thread_state(thread_state); |
| 69 isolate->set_vm_tag(VMTag::kVMTagId); |
| 70 thread->isolate_ = isolate; |
| 71 } |
| 72 |
| 73 |
| 74 void Thread::ExitIsolate() { |
| 75 Thread* thread = Thread::Current(); |
| 76 // TODO(koda): Audit callers; they should know whether they're in an isolate. |
| 77 if (thread == NULL) return; |
| 78 Isolate* isolate = thread->isolate(); |
| 79 ASSERT(isolate != NULL); |
| 80 isolate->set_vm_tag(VMTag::kIdleTagId); |
| 81 isolate->set_thread_state(NULL); |
| 82 Profiler::EndExecution(isolate); |
| 83 isolate->set_mutator_thread(NULL); |
| 84 thread->isolate_ = NULL; |
| 85 ASSERT(Isolate::Current() == NULL); |
| 86 CleanUp(); |
| 87 } |
| 88 |
| 89 |
30 } // namespace dart | 90 } // namespace dart |
OLD | NEW |