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_registry.h" | 5 #include "vm/thread_registry.h" |
| 6 | 6 |
| 7 #include "vm/isolate.h" | 7 #include "vm/isolate.h" |
| 8 #include "vm/lockers.h" | 8 #include "vm/lockers.h" |
| 9 | 9 |
| 10 namespace dart { | 10 namespace dart { |
| 11 | 11 |
| 12 ThreadRegistry::~ThreadRegistry() { | 12 ThreadRegistry::~ThreadRegistry() { |
| 13 // Go over the free thread list and delete the thread objects. | |
| 14 { | |
| 15 MonitorLocker ml(monitor_); | |
| 16 // At this point the mutator thread should be the only thread | |
| 17 // in the active list, delete it. | |
| 18 ASSERT(active_list_->next_ == NULL); | |
| 19 ASSERT(active_list_ == mutator_thread_); | |
| 20 delete mutator_thread_; | |
| 21 active_list_ = NULL; | |
| 22 mutator_thread_ = NULL; | |
| 23 // Now delete all the threads in the free list. | |
| 24 while (free_list_ != NULL) { | |
| 25 Thread* thread = free_list_; | |
| 26 free_list_ = thread->next_; | |
| 27 delete thread; | |
| 28 } | |
| 29 } | |
| 30 | |
| 13 // Delete monitor. | 31 // Delete monitor. |
| 14 delete monitor_; | 32 delete monitor_; |
| 15 } | 33 } |
| 16 | 34 |
| 17 | 35 |
| 18 void ThreadRegistry::SafepointThreads() { | 36 void ThreadRegistry::SafepointThreads() { |
| 19 MonitorLocker ml(monitor_); | 37 MonitorLocker ml(monitor_); |
| 20 // First wait for any older rounds that are still in progress. | 38 // First wait for any older rounds that are still in progress. |
| 21 while (in_rendezvous_) { | 39 while (in_rendezvous_) { |
| 22 // Assert we are not the organizer trying to nest calls to SafepointThreads. | 40 // Assert we are not the organizer trying to nest calls to SafepointThreads. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 43 | 61 |
| 44 | 62 |
| 45 void ThreadRegistry::ResumeAllThreads() { | 63 void ThreadRegistry::ResumeAllThreads() { |
| 46 MonitorLocker ml(monitor_); | 64 MonitorLocker ml(monitor_); |
| 47 ASSERT(in_rendezvous_); | 65 ASSERT(in_rendezvous_); |
| 48 in_rendezvous_ = false; | 66 in_rendezvous_ = false; |
| 49 ml.NotifyAll(); | 67 ml.NotifyAll(); |
| 50 } | 68 } |
| 51 | 69 |
| 52 | 70 |
| 53 void ThreadRegistry::PruneThread(Thread* thread) { | 71 Thread* ThreadRegistry::Schedule(Isolate* isolate, |
| 72 bool is_mutator, | |
| 73 bool bypass_safepoint) { | |
| 54 MonitorLocker ml(monitor_); | 74 MonitorLocker ml(monitor_); |
| 55 intptr_t length = entries_.length(); | 75 // Wait for any rendezvous in progress. |
| 56 if (length == 0) { | 76 while (!bypass_safepoint && in_rendezvous_) { |
| 57 return; | 77 ml.Wait(Monitor::kNoTimeout); |
| 58 } | 78 } |
| 59 intptr_t found_index = -1; | 79 Thread* thread = NULL; |
| 60 for (intptr_t index = 0; index < length; index++) { | 80 OSThread* os_thread = OSThread::Current(); |
| 61 if (entries_.At(index).thread == thread) { | 81 ASSERT(os_thread != NULL); |
| 62 found_index = index; | 82 ASSERT(isolate->heap() != NULL); |
| 63 break; | 83 if (is_mutator) { |
| 84 if (mutator_thread_ == NULL) { | |
| 85 mutator_thread_ = GetThreadFromFreelist(isolate); | |
| 64 } | 86 } |
| 87 thread = mutator_thread_; | |
| 88 } else { | |
| 89 thread = GetThreadFromFreelist(isolate); | |
| 65 } | 90 } |
| 66 if (found_index < 0) { | 91 thread->isolate_ = isolate; |
| 67 return; | 92 thread->heap_ = isolate->heap(); |
| 68 } | 93 thread->set_os_thread(os_thread); |
| 69 entries_.RemoveAt(found_index); | 94 os_thread->set_thread(thread); |
| 95 Thread::SetCurrent(thread); | |
| 96 os_thread->EnableThreadInterrupts(); | |
| 97 return thread; | |
| 70 } | 98 } |
| 71 | 99 |
| 72 | 100 |
| 73 ThreadRegistry::EntryIterator::EntryIterator(ThreadRegistry* registry) | 101 void ThreadRegistry::Unschedule(Thread* thread, |
| 74 : index_(0), | 102 bool is_mutator, |
| 75 registry_(NULL) { | 103 bool bypass_safepoint) { |
| 76 Reset(registry); | 104 MonitorLocker ml(monitor_); |
| 77 } | 105 OSThread* os_thread = thread->os_thread(); |
| 78 | 106 ASSERT(os_thread != NULL); |
| 79 | 107 os_thread->DisableThreadInterrupts(); |
| 80 ThreadRegistry::EntryIterator::~EntryIterator() { | 108 thread->isolate_ = NULL; |
| 81 Reset(NULL); | 109 thread->heap_ = NULL; |
| 82 } | 110 thread->set_os_thread(NULL); |
| 83 | 111 os_thread->set_thread(NULL); |
| 84 | 112 OSThread::SetCurrent(os_thread); |
| 85 void ThreadRegistry::EntryIterator::Reset(ThreadRegistry* registry) { | 113 if (!is_mutator) { |
| 86 // Reset index. | 114 ReturnThreadToFreelist(thread); |
| 87 index_ = 0; | |
| 88 | |
| 89 // Unlock old registry. | |
| 90 if (registry_ != NULL) { | |
| 91 registry_->monitor_->Exit(); | |
| 92 } | 115 } |
| 93 | 116 if (!bypass_safepoint && in_rendezvous_) { |
| 94 registry_ = registry; | 117 // Don't wait for this thread. |
| 95 | 118 ASSERT(remaining_ > 0); |
| 96 // Lock new registry. | 119 if (--remaining_ == 0) { |
| 97 if (registry_ != NULL) { | 120 ml.NotifyAll(); |
| 98 registry_->monitor_->Enter(); | 121 } |
| 99 } | 122 } |
| 100 } | 123 } |
| 101 | 124 |
| 102 | 125 |
| 103 bool ThreadRegistry::EntryIterator::HasNext() const { | 126 void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor, |
| 104 if (registry_ == NULL) { | 127 bool validate_frames) { |
| 105 return false; | 128 MonitorLocker ml(monitor_); |
| 129 Thread* thread = active_list_; | |
| 130 while (thread != NULL) { | |
| 131 if (thread->zone() != NULL) { | |
| 132 thread->zone()->VisitObjectPointers(visitor); | |
| 133 } | |
| 134 thread->VisitObjectPointers(visitor); | |
| 135 // Iterate over all the stack frames and visit objects on the stack. | |
| 136 StackFrameIterator frames_iterator(thread->top_exit_frame_info(), | |
| 137 validate_frames); | |
| 138 StackFrame* frame = frames_iterator.NextFrame(); | |
| 139 while (frame != NULL) { | |
| 140 frame->VisitObjectPointers(visitor); | |
| 141 frame = frames_iterator.NextFrame(); | |
| 142 } | |
| 143 thread = thread->next_; | |
| 106 } | 144 } |
| 107 return index_ < registry_->entries_.length(); | |
| 108 } | 145 } |
| 109 | 146 |
| 110 | 147 |
| 111 const ThreadRegistry::Entry& ThreadRegistry::EntryIterator::Next() { | 148 Thread* ThreadRegistry::GetThreadFromFreelist(Isolate* isolate) { |
| 112 ASSERT(HasNext()); | 149 ASSERT(monitor_->IsOwnedByCurrentThread()); |
| 113 return registry_->entries_.At(index_++); | 150 Thread* thread = NULL; |
| 151 // Get thread structure from free list or create a new one. | |
| 152 if (free_list_ == NULL) { | |
| 153 thread = new Thread(isolate); | |
| 154 } else { | |
| 155 thread = free_list_; | |
| 156 free_list_ = thread->next_; | |
| 157 } | |
| 158 // Add thread to active list. | |
| 159 thread->next_ = active_list_; | |
| 160 active_list_ = thread; | |
| 161 return thread; | |
| 162 } | |
| 163 | |
| 164 void ThreadRegistry::ReturnThreadToFreelist(Thread* thread) { | |
| 165 ASSERT(thread != NULL); | |
| 166 ASSERT(thread->os_thread_ == NULL); | |
| 167 ASSERT(thread->isolate_ == NULL); | |
| 168 ASSERT(thread->heap_ == NULL); | |
| 169 ASSERT(monitor_->IsOwnedByCurrentThread()); | |
| 170 // First remove the thread from the active list. | |
| 171 Thread* prev = NULL; | |
| 172 Thread* iterator = active_list_; | |
| 173 while (iterator != NULL) { | |
|
Ivan Posva
2015/11/19 06:23:23
iterator is a weird name for this. How about using
siva
2015/11/19 20:54:05
Done.
| |
| 174 if (iterator == thread) { | |
| 175 if (prev == NULL) { | |
| 176 active_list_ = iterator->next_; | |
| 177 } else { | |
| 178 prev->next_ = iterator->next_; | |
| 179 } | |
| 180 break; | |
| 181 } | |
| 182 prev = iterator; | |
| 183 iterator = iterator->next_; | |
| 184 } | |
| 185 // Now add thread to the free list. | |
| 186 thread->next_ = free_list_; | |
| 187 free_list_ = thread; | |
| 114 } | 188 } |
| 115 | 189 |
| 116 | 190 |
| 117 void ThreadRegistry::CheckSafepointLocked() { | 191 void ThreadRegistry::CheckSafepointLocked() { |
| 118 int64_t last_round = -1; | 192 int64_t last_round = -1; |
| 119 while (in_rendezvous_) { | 193 while (in_rendezvous_) { |
| 120 ASSERT(round_ >= last_round); | 194 ASSERT(round_ >= last_round); |
| 121 if (round_ != last_round) { | 195 if (round_ != last_round) { |
| 122 ASSERT((last_round == -1) || (round_ == (last_round + 1))); | 196 ASSERT((last_round == -1) || (round_ == (last_round + 1))); |
| 123 last_round = round_; | 197 last_round = round_; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 135 // b) after ResumeAllThreads, another call to SafepointThreads was | 209 // b) after ResumeAllThreads, another call to SafepointThreads was |
| 136 // made before this thread got a chance to reaquire monitor_, thus this | 210 // made before this thread got a chance to reaquire monitor_, thus this |
| 137 // thread should (again) decrease remaining_ to indicate cooperation in | 211 // thread should (again) decrease remaining_ to indicate cooperation in |
| 138 // this new round. | 212 // this new round. |
| 139 } | 213 } |
| 140 } | 214 } |
| 141 | 215 |
| 142 | 216 |
| 143 intptr_t ThreadRegistry::CountScheduledLocked() { | 217 intptr_t ThreadRegistry::CountScheduledLocked() { |
| 144 intptr_t count = 0; | 218 intptr_t count = 0; |
| 145 for (int i = 0; i < entries_.length(); ++i) { | 219 Thread* iterator = active_list_; |
|
Ivan Posva
2015/11/19 06:23:23
ditto
siva
2015/11/19 20:54:05
Done.
| |
| 146 const Entry& entry = entries_[i]; | 220 while (iterator != NULL) { |
| 147 if (entry.scheduled) { | 221 ++count; |
| 148 ++count; | 222 iterator = iterator->next_; |
| 149 } | |
| 150 } | 223 } |
| 151 return count; | 224 return count; |
| 152 } | 225 } |
| 153 | 226 |
| 154 } // namespace dart | 227 } // namespace dart |
| OLD | NEW |