| 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/growable_array.h" | 7 #include "vm/growable_array.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/lockers.h" | 9 #include "vm/lockers.h" |
| 10 #include "vm/log.h" | 10 #include "vm/log.h" |
| 11 #include "vm/native_entry.h" | 11 #include "vm/native_entry.h" |
| 12 #include "vm/object.h" | 12 #include "vm/object.h" |
| 13 #include "vm/os_thread.h" | 13 #include "vm/os_thread.h" |
| 14 #include "vm/profiler.h" | 14 #include "vm/profiler.h" |
| 15 #include "vm/runtime_entry.h" | 15 #include "vm/runtime_entry.h" |
| 16 #include "vm/stub_code.h" | 16 #include "vm/stub_code.h" |
| 17 #include "vm/symbols.h" | 17 #include "vm/symbols.h" |
| 18 #include "vm/thread_interrupter.h" | 18 #include "vm/thread_interrupter.h" |
| 19 #include "vm/thread_registry.h" | 19 #include "vm/thread_registry.h" |
| 20 | 20 |
| 21 namespace dart { | 21 namespace dart { |
| 22 | 22 |
| 23 // The single thread local key which stores all the thread local data | 23 // The single thread local key which stores all the thread local data |
| 24 // for a thread. | 24 // for a thread. |
| 25 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; | 25 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; |
| 26 | 26 Thread* Thread::thread_list_head_ = NULL; |
| 27 Mutex* Thread::thread_list_lock_; |
| 27 | 28 |
| 28 // Remove |thread| from each isolate's thread registry. | 29 // Remove |thread| from each isolate's thread registry. |
| 29 class ThreadPruner : public IsolateVisitor { | 30 class ThreadPruner : public IsolateVisitor { |
| 30 public: | 31 public: |
| 31 explicit ThreadPruner(Thread* thread) | 32 explicit ThreadPruner(Thread* thread) |
| 32 : thread_(thread) { | 33 : thread_(thread) { |
| 33 ASSERT(thread_ != NULL); | 34 ASSERT(thread_ != NULL); |
| 34 } | 35 } |
| 35 | 36 |
| 36 void VisitIsolate(Isolate* isolate) { | 37 void VisitIsolate(Isolate* isolate) { |
| 37 ThreadRegistry* registry = isolate->thread_registry(); | 38 ThreadRegistry* registry = isolate->thread_registry(); |
| 38 ASSERT(registry != NULL); | 39 ASSERT(registry != NULL); |
| 39 registry->PruneThread(thread_); | 40 registry->PruneThread(thread_); |
| 40 } | 41 } |
| 41 private: | 42 private: |
| 42 Thread* thread_; | 43 Thread* thread_; |
| 43 }; | 44 }; |
| 44 | 45 |
| 45 | 46 |
| 47 void Thread::AddThreadToList(Thread* thread) { |
| 48 ASSERT(thread != NULL); |
| 49 ASSERT(thread->isolate() == NULL); |
| 50 MutexLocker ml(thread_list_lock_); |
| 51 |
| 52 ASSERT(thread->thread_list_next_ == NULL); |
| 53 |
| 54 #if defined(DEBUG) |
| 55 { |
| 56 // Ensure that we aren't already in the list. |
| 57 Thread* current = thread_list_head_; |
| 58 while (current != NULL) { |
| 59 ASSERT(current != thread); |
| 60 current = current->thread_list_next_; |
| 61 } |
| 62 } |
| 63 #endif |
| 64 |
| 65 // Insert at head of list. |
| 66 thread->thread_list_next_ = thread_list_head_; |
| 67 thread_list_head_ = thread; |
| 68 } |
| 69 |
| 70 |
| 71 void Thread::RemoveThreadFromList(Thread* thread) { |
| 72 ASSERT(thread != NULL); |
| 73 ASSERT(thread->isolate() == NULL); |
| 74 MutexLocker ml(thread_list_lock_); |
| 75 |
| 76 // Handle case where |thread| is head of list. |
| 77 if (thread_list_head_ == thread) { |
| 78 thread_list_head_ = thread->thread_list_next_; |
| 79 thread->thread_list_next_ = NULL; |
| 80 return; |
| 81 } |
| 82 |
| 83 Thread* current = thread_list_head_; |
| 84 Thread* previous = NULL; |
| 85 |
| 86 // Scan across list and remove |thread|. |
| 87 while (current != NULL) { |
| 88 previous = current; |
| 89 current = current->thread_list_next_; |
| 90 if (current == thread) { |
| 91 // We found |thread|, remove from list. |
| 92 previous->thread_list_next_ = current->thread_list_next_; |
| 93 thread->thread_list_next_ = NULL; |
| 94 return; |
| 95 } |
| 96 } |
| 97 |
| 98 UNREACHABLE(); |
| 99 } |
| 100 |
| 101 |
| 46 static void DeleteThread(void* thread) { | 102 static void DeleteThread(void* thread) { |
| 47 delete reinterpret_cast<Thread*>(thread); | 103 delete reinterpret_cast<Thread*>(thread); |
| 48 } | 104 } |
| 49 | 105 |
| 50 | 106 |
| 107 void Thread::Shutdown() { |
| 108 if (thread_list_lock_ != NULL) { |
| 109 delete thread_list_lock_; |
| 110 thread_list_lock_ = NULL; |
| 111 } |
| 112 } |
| 113 |
| 114 |
| 51 Thread::~Thread() { | 115 Thread::~Thread() { |
| 52 // We should cleanly exit any isolate before destruction. | 116 // We should cleanly exit any isolate before destruction. |
| 53 ASSERT(isolate_ == NULL); | 117 ASSERT(isolate_ == NULL); |
| 54 // Clear |this| from all isolate's thread registry. | 118 // Clear |this| from all isolate's thread registry. |
| 55 ThreadPruner pruner(this); | 119 ThreadPruner pruner(this); |
| 56 Isolate::VisitIsolates(&pruner); | 120 Isolate::VisitIsolates(&pruner); |
| 57 delete log_; | 121 delete log_; |
| 58 log_ = NULL; | 122 log_ = NULL; |
| 123 RemoveThreadFromList(this); |
| 59 } | 124 } |
| 60 | 125 |
| 61 | 126 |
| 62 void Thread::InitOnceBeforeIsolate() { | 127 void Thread::InitOnceBeforeIsolate() { |
| 63 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); | 128 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); |
| 64 thread_key_ = OSThread::CreateThreadLocal(DeleteThread); | 129 thread_key_ = OSThread::CreateThreadLocal(DeleteThread); |
| 65 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); | 130 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); |
| 66 ASSERT(Thread::Current() == NULL); | 131 ASSERT(Thread::Current() == NULL); |
| 132 thread_list_lock_ = new Mutex(); |
| 67 // Allocate a new Thread and postpone initialization of VM constants for | 133 // Allocate a new Thread and postpone initialization of VM constants for |
| 68 // this first thread. | 134 // this first thread. |
| 69 Thread* thread = new Thread(false); | 135 Thread* thread = new Thread(false); |
| 70 // Verify that current thread was set. | 136 // Verify that current thread was set. |
| 71 ASSERT(Thread::Current() == thread); | 137 ASSERT(Thread::Current() == thread); |
| 72 } | 138 } |
| 73 | 139 |
| 74 | 140 |
| 75 void Thread::InitOnceAfterObjectAndStubCode() { | 141 void Thread::InitOnceAfterObjectAndStubCode() { |
| 76 Thread* thread = Thread::Current(); | 142 Thread* thread = Thread::Current(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 : id_(OSThread::GetCurrentThreadId()), | 186 : id_(OSThread::GetCurrentThreadId()), |
| 121 thread_interrupt_callback_(NULL), | 187 thread_interrupt_callback_(NULL), |
| 122 thread_interrupt_data_(NULL), | 188 thread_interrupt_data_(NULL), |
| 123 isolate_(NULL), | 189 isolate_(NULL), |
| 124 heap_(NULL), | 190 heap_(NULL), |
| 125 store_buffer_block_(NULL), | 191 store_buffer_block_(NULL), |
| 126 log_(new class Log()), | 192 log_(new class Log()), |
| 127 vm_tag_(0), | 193 vm_tag_(0), |
| 128 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) | 194 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) |
| 129 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) | 195 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) |
| 130 reusable_handles_() { | 196 reusable_handles_(), |
| 197 thread_list_next_(NULL) { |
| 131 ClearState(); | 198 ClearState(); |
| 132 | 199 |
| 133 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ | 200 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ |
| 134 member_name = default_init_value; | 201 member_name = default_init_value; |
| 135 CACHED_CONSTANTS_LIST(DEFAULT_INIT) | 202 CACHED_CONSTANTS_LIST(DEFAULT_INIT) |
| 136 #undef DEFAULT_INIT | 203 #undef DEFAULT_INIT |
| 137 | 204 |
| 138 #define DEFAULT_INIT(name) \ | 205 #define DEFAULT_INIT(name) \ |
| 139 name##_entry_point_ = 0; | 206 name##_entry_point_ = 0; |
| 140 RUNTIME_ENTRY_LIST(DEFAULT_INIT) | 207 RUNTIME_ENTRY_LIST(DEFAULT_INIT) |
| 141 #undef DEFAULT_INIT | 208 #undef DEFAULT_INIT |
| 142 | 209 |
| 143 #define DEFAULT_INIT(returntype, name, ...) \ | 210 #define DEFAULT_INIT(returntype, name, ...) \ |
| 144 name##_entry_point_ = 0; | 211 name##_entry_point_ = 0; |
| 145 LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT) | 212 LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT) |
| 146 #undef DEFAULT_INIT | 213 #undef DEFAULT_INIT |
| 147 | 214 |
| 148 if (init_vm_constants) { | 215 if (init_vm_constants) { |
| 149 InitVMConstants(); | 216 InitVMConstants(); |
| 150 } | 217 } |
| 151 SetCurrent(this); | 218 SetCurrent(this); |
| 219 AddThreadToList(this); |
| 152 } | 220 } |
| 153 | 221 |
| 154 | 222 |
| 155 void Thread::InitVMConstants() { | 223 void Thread::InitVMConstants() { |
| 156 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \ | 224 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \ |
| 157 ASSERT((init_expr)->IsOldObject()); | 225 ASSERT((init_expr)->IsOldObject()); |
| 158 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP) | 226 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP) |
| 159 #undef ASSERT_VM_HEAP | 227 #undef ASSERT_VM_HEAP |
| 160 | 228 |
| 161 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \ | 229 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \ |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 if (runtime_entry->function() == k##name##RuntimeEntry.function()) { \ | 492 if (runtime_entry->function() == k##name##RuntimeEntry.function()) { \ |
| 425 return Thread::name##_entry_point_offset(); \ | 493 return Thread::name##_entry_point_offset(); \ |
| 426 } | 494 } |
| 427 LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET) | 495 LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET) |
| 428 #undef COMPUTE_OFFSET | 496 #undef COMPUTE_OFFSET |
| 429 | 497 |
| 430 UNREACHABLE(); | 498 UNREACHABLE(); |
| 431 return -1; | 499 return -1; |
| 432 } | 500 } |
| 433 | 501 |
| 502 |
| 503 ThreadIterator::ThreadIterator() { |
| 504 ASSERT(Thread::thread_list_lock_ != NULL); |
| 505 // Lock the thread list while iterating. |
| 506 Thread::thread_list_lock_->Lock(); |
| 507 next_ = Thread::thread_list_head_; |
| 508 } |
| 509 |
| 510 |
| 511 ThreadIterator::~ThreadIterator() { |
| 512 ASSERT(Thread::thread_list_lock_ != NULL); |
| 513 // Unlock the thread list when done. |
| 514 Thread::thread_list_lock_->Unlock(); |
| 515 } |
| 516 |
| 517 |
| 518 bool ThreadIterator::HasNext() const { |
| 519 ASSERT(Thread::thread_list_lock_ != NULL); |
| 520 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread()); |
| 521 return next_ != NULL; |
| 522 } |
| 523 |
| 524 |
| 525 Thread* ThreadIterator::Next() { |
| 526 ASSERT(Thread::thread_list_lock_ != NULL); |
| 527 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread()); |
| 528 Thread* current = next_; |
| 529 next_ = next_->thread_list_next_; |
| 530 return current; |
| 531 } |
| 532 |
| 533 |
| 434 } // namespace dart | 534 } // namespace dart |
| OLD | NEW |