Chromium Code Reviews| 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 MutexLocker ml(&thread_list_lock_); | |
| 50 ASSERT(thread->thread_list_next_ == NULL); | |
| 51 #if defined(DEBUG) | |
| 52 { | |
| 53 // Ensure that we aren't already in the list. | |
| 54 Thread* current = thread_list_head_; | |
| 55 while (current != NULL) { | |
| 56 ASSERT(current != thread); | |
| 57 current = current->thread_list_next_; | |
| 58 } | |
| 59 } | |
| 60 #endif | |
| 61 // Insert at head of list. | |
| 62 thread->thread_list_next_ = thread_list_head_; | |
| 63 thread_list_head_ = thread; | |
| 64 } | |
| 65 | |
| 66 | |
| 67 void Thread::RemoveThreadFromList(Thread* thread) { | |
| 68 ASSERT(thread != NULL); | |
| 69 MutexLocker ml(&thread_list_lock_); | |
| 70 | |
| 71 // Handle case where |thread| is head of list. | |
| 72 if (thread_list_head_ == thread) { | |
| 73 thread_list_head_ = thread->thread_list_next_; | |
| 74 thread->thread_list_next_ = NULL; | |
| 75 return; | |
| 76 } | |
| 77 | |
| 78 Thread* current = thread_list_head_; | |
| 79 Thread* previous = NULL; | |
| 80 | |
| 81 #if defined(DEBUG) | |
| 82 bool found_in_list = false; | |
| 83 #endif | |
| 84 | |
| 85 // Scan across list and remove |thread|. | |
| 86 while (current != NULL) { | |
| 87 previous = current; | |
| 88 current = current->thread_list_next_; | |
| 89 if (current == thread) { | |
| 90 // We found |thread|, remove from list. | |
| 91 previous->thread_list_next_ = current->thread_list_next_; | |
| 92 #if defined(DEBUG) | |
| 93 found_in_list = true; | |
| 94 #endif | |
|
siva
2015/10/12 23:03:14
missing 'break;' here?
Maybe you could restructu
Cutch
2015/10/13 16:41:23
Done.
| |
| 95 } | |
| 96 } | |
| 97 | |
| 98 #if defined(DEBUG) | |
| 99 ASSERT(found_in_list); | |
| 100 #endif | |
| 101 thread->thread_list_next_ = NULL; | |
| 102 } | |
| 103 | |
| 104 | |
| 46 static void DeleteThread(void* thread) { | 105 static void DeleteThread(void* thread) { |
| 47 delete reinterpret_cast<Thread*>(thread); | 106 delete reinterpret_cast<Thread*>(thread); |
| 48 } | 107 } |
| 49 | 108 |
| 50 | 109 |
| 51 Thread::~Thread() { | 110 Thread::~Thread() { |
| 52 // We should cleanly exit any isolate before destruction. | 111 // We should cleanly exit any isolate before destruction. |
| 53 ASSERT(isolate_ == NULL); | 112 ASSERT(isolate_ == NULL); |
| 54 // Clear |this| from all isolate's thread registry. | 113 // Clear |this| from all isolate's thread registry. |
| 55 ThreadPruner pruner(this); | 114 ThreadPruner pruner(this); |
| 56 Isolate::VisitIsolates(&pruner); | 115 Isolate::VisitIsolates(&pruner); |
| 57 delete log_; | 116 delete log_; |
| 58 log_ = NULL; | 117 log_ = NULL; |
| 118 RemoveThreadFromList(this); | |
| 59 } | 119 } |
| 60 | 120 |
| 61 | 121 |
| 62 void Thread::InitOnceBeforeIsolate() { | 122 void Thread::InitOnceBeforeIsolate() { |
| 63 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); | 123 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); |
| 64 thread_key_ = OSThread::CreateThreadLocal(DeleteThread); | 124 thread_key_ = OSThread::CreateThreadLocal(DeleteThread); |
| 65 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); | 125 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); |
| 66 ASSERT(Thread::Current() == NULL); | 126 ASSERT(Thread::Current() == NULL); |
| 67 // Allocate a new Thread and postpone initialization of VM constants for | 127 // Allocate a new Thread and postpone initialization of VM constants for |
| 68 // this first thread. | 128 // this first thread. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 : id_(OSThread::GetCurrentThreadId()), | 180 : id_(OSThread::GetCurrentThreadId()), |
| 121 thread_interrupt_callback_(NULL), | 181 thread_interrupt_callback_(NULL), |
| 122 thread_interrupt_data_(NULL), | 182 thread_interrupt_data_(NULL), |
| 123 isolate_(NULL), | 183 isolate_(NULL), |
| 124 heap_(NULL), | 184 heap_(NULL), |
| 125 store_buffer_block_(NULL), | 185 store_buffer_block_(NULL), |
| 126 log_(new class Log()), | 186 log_(new class Log()), |
| 127 vm_tag_(0), | 187 vm_tag_(0), |
| 128 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) | 188 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) |
| 129 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) | 189 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) |
| 130 reusable_handles_() { | 190 reusable_handles_(), |
| 191 thread_list_next_(NULL) { | |
| 131 ClearState(); | 192 ClearState(); |
| 132 | 193 |
| 133 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ | 194 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ |
| 134 member_name = default_init_value; | 195 member_name = default_init_value; |
| 135 CACHED_CONSTANTS_LIST(DEFAULT_INIT) | 196 CACHED_CONSTANTS_LIST(DEFAULT_INIT) |
| 136 #undef DEFAULT_INIT | 197 #undef DEFAULT_INIT |
| 137 | 198 |
| 138 #define DEFAULT_INIT(name) \ | 199 #define DEFAULT_INIT(name) \ |
| 139 name##_entry_point_ = 0; | 200 name##_entry_point_ = 0; |
| 140 RUNTIME_ENTRY_LIST(DEFAULT_INIT) | 201 RUNTIME_ENTRY_LIST(DEFAULT_INIT) |
| 141 #undef DEFAULT_INIT | 202 #undef DEFAULT_INIT |
| 142 | 203 |
| 143 #define DEFAULT_INIT(returntype, name, ...) \ | 204 #define DEFAULT_INIT(returntype, name, ...) \ |
| 144 name##_entry_point_ = 0; | 205 name##_entry_point_ = 0; |
| 145 LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT) | 206 LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT) |
| 146 #undef DEFAULT_INIT | 207 #undef DEFAULT_INIT |
| 147 | 208 |
| 148 if (init_vm_constants) { | 209 if (init_vm_constants) { |
| 149 InitVMConstants(); | 210 InitVMConstants(); |
| 150 } | 211 } |
| 151 SetCurrent(this); | 212 SetCurrent(this); |
| 213 AddThreadToList(this); | |
| 152 } | 214 } |
| 153 | 215 |
| 154 | 216 |
| 155 void Thread::InitVMConstants() { | 217 void Thread::InitVMConstants() { |
| 156 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \ | 218 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \ |
| 157 ASSERT((init_expr)->IsOldObject()); | 219 ASSERT((init_expr)->IsOldObject()); |
| 158 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP) | 220 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP) |
| 159 #undef ASSERT_VM_HEAP | 221 #undef ASSERT_VM_HEAP |
| 160 | 222 |
| 161 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \ | 223 #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()) { \ | 486 if (runtime_entry->function() == k##name##RuntimeEntry.function()) { \ |
| 425 return Thread::name##_entry_point_offset(); \ | 487 return Thread::name##_entry_point_offset(); \ |
| 426 } | 488 } |
| 427 LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET) | 489 LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET) |
| 428 #undef COMPUTE_OFFSET | 490 #undef COMPUTE_OFFSET |
| 429 | 491 |
| 430 UNREACHABLE(); | 492 UNREACHABLE(); |
| 431 return -1; | 493 return -1; |
| 432 } | 494 } |
| 433 | 495 |
| 496 | |
| 497 ThreadIterator::ThreadIterator() { | |
| 498 // Lock the thread list while iterating. | |
| 499 Thread::thread_list_lock_.Lock(); | |
| 500 next_ = Thread::thread_list_head_; | |
| 501 } | |
| 502 | |
| 503 | |
| 504 ThreadIterator::~ThreadIterator() { | |
| 505 // Unlock the thread list when done. | |
| 506 Thread::thread_list_lock_.Unlock(); | |
| 507 } | |
| 508 | |
| 509 | |
| 510 bool ThreadIterator::HasNext() { | |
|
siva
2015/10/12 23:03:14
ASSERT(Thread::thread_list_lock_->IsOwnedByCurrent
Cutch
2015/10/13 16:41:23
Done.
| |
| 511 return next_ != NULL; | |
| 512 } | |
| 513 | |
| 514 | |
| 515 Thread* ThreadIterator::Next() { | |
|
siva
2015/10/12 23:03:14
ASSERT(Thread::thread_list_lock_->IsOwnedByCurrent
Cutch
2015/10/13 16:41:23
Done.
| |
| 516 Thread* current = next_; | |
| 517 next_ = next_->thread_list_next_; | |
| 518 return current; | |
| 519 } | |
| 520 | |
| 521 | |
| 434 } // namespace dart | 522 } // namespace dart |
| OLD | NEW |