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 Thread::SetCurrent(thread); |
| 95 os_thread->EnableThreadInterrupts(); |
| 96 return thread; |
70 } | 97 } |
71 | 98 |
72 | 99 |
73 ThreadRegistry::EntryIterator::EntryIterator(ThreadRegistry* registry) | 100 void ThreadRegistry::Unschedule(Thread* thread, |
74 : index_(0), | 101 bool is_mutator, |
75 registry_(NULL) { | 102 bool bypass_safepoint) { |
76 Reset(registry); | 103 MonitorLocker ml(monitor_); |
77 } | 104 OSThread* os_thread = thread->os_thread(); |
78 | 105 ASSERT(os_thread != NULL); |
79 | 106 os_thread->DisableThreadInterrupts(); |
80 ThreadRegistry::EntryIterator::~EntryIterator() { | 107 thread->isolate_ = NULL; |
81 Reset(NULL); | 108 thread->heap_ = NULL; |
82 } | 109 thread->set_os_thread(NULL); |
83 | 110 OSThread::SetCurrent(os_thread); |
84 | 111 if (!is_mutator) { |
85 void ThreadRegistry::EntryIterator::Reset(ThreadRegistry* registry) { | 112 ReturnThreadToFreelist(thread); |
86 // Reset index. | |
87 index_ = 0; | |
88 | |
89 // Unlock old registry. | |
90 if (registry_ != NULL) { | |
91 registry_->monitor_->Exit(); | |
92 } | 113 } |
93 | 114 if (!bypass_safepoint && in_rendezvous_) { |
94 registry_ = registry; | 115 // Don't wait for this thread. |
95 | 116 ASSERT(remaining_ > 0); |
96 // Lock new registry. | 117 if (--remaining_ == 0) { |
97 if (registry_ != NULL) { | 118 ml.NotifyAll(); |
98 registry_->monitor_->Enter(); | 119 } |
99 } | 120 } |
100 } | 121 } |
101 | 122 |
102 | 123 |
103 bool ThreadRegistry::EntryIterator::HasNext() const { | 124 void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor, |
104 if (registry_ == NULL) { | 125 bool validate_frames) { |
105 return false; | 126 MonitorLocker ml(monitor_); |
| 127 Thread* thread = active_list_; |
| 128 while (thread != NULL) { |
| 129 if (thread->zone() != NULL) { |
| 130 thread->zone()->VisitObjectPointers(visitor); |
| 131 } |
| 132 thread->VisitObjectPointers(visitor); |
| 133 // Iterate over all the stack frames and visit objects on the stack. |
| 134 StackFrameIterator frames_iterator(thread->top_exit_frame_info(), |
| 135 validate_frames); |
| 136 StackFrame* frame = frames_iterator.NextFrame(); |
| 137 while (frame != NULL) { |
| 138 frame->VisitObjectPointers(visitor); |
| 139 frame = frames_iterator.NextFrame(); |
| 140 } |
| 141 thread = thread->next_; |
106 } | 142 } |
107 return index_ < registry_->entries_.length(); | |
108 } | 143 } |
109 | 144 |
110 | 145 |
111 const ThreadRegistry::Entry& ThreadRegistry::EntryIterator::Next() { | 146 Thread* ThreadRegistry::GetThreadFromFreelist(Isolate* isolate) { |
112 ASSERT(HasNext()); | 147 ASSERT(monitor_->IsOwnedByCurrentThread()); |
113 return registry_->entries_.At(index_++); | 148 Thread* thread = NULL; |
| 149 // Get thread structure from free list or create a new one. |
| 150 if (free_list_ == NULL) { |
| 151 thread = new Thread(isolate); |
| 152 } else { |
| 153 thread = free_list_; |
| 154 free_list_ = thread->next_; |
| 155 } |
| 156 // Add thread to active list. |
| 157 thread->next_ = active_list_; |
| 158 active_list_ = thread; |
| 159 return thread; |
| 160 } |
| 161 |
| 162 void ThreadRegistry::ReturnThreadToFreelist(Thread* thread) { |
| 163 ASSERT(thread != NULL); |
| 164 ASSERT(thread->os_thread_ == NULL); |
| 165 ASSERT(thread->isolate_ == NULL); |
| 166 ASSERT(thread->heap_ == NULL); |
| 167 ASSERT(monitor_->IsOwnedByCurrentThread()); |
| 168 // First remove the thread from the active list. |
| 169 Thread* prev = NULL; |
| 170 Thread* iterator = active_list_; |
| 171 while (iterator != NULL) { |
| 172 if (iterator == thread) { |
| 173 if (prev == NULL) { |
| 174 active_list_ = iterator->next_; |
| 175 } else { |
| 176 prev->next_ = iterator->next_; |
| 177 } |
| 178 break; |
| 179 } |
| 180 prev = iterator; |
| 181 iterator = iterator->next_; |
| 182 } |
| 183 // Now add thread to the free list. |
| 184 thread->next_ = free_list_; |
| 185 free_list_ = thread; |
114 } | 186 } |
115 | 187 |
116 | 188 |
117 void ThreadRegistry::CheckSafepointLocked() { | 189 void ThreadRegistry::CheckSafepointLocked() { |
118 int64_t last_round = -1; | 190 int64_t last_round = -1; |
119 while (in_rendezvous_) { | 191 while (in_rendezvous_) { |
120 ASSERT(round_ >= last_round); | 192 ASSERT(round_ >= last_round); |
121 if (round_ != last_round) { | 193 if (round_ != last_round) { |
122 ASSERT((last_round == -1) || (round_ == (last_round + 1))); | 194 ASSERT((last_round == -1) || (round_ == (last_round + 1))); |
123 last_round = round_; | 195 last_round = round_; |
(...skipping 11 matching lines...) Expand all Loading... |
135 // b) after ResumeAllThreads, another call to SafepointThreads was | 207 // b) after ResumeAllThreads, another call to SafepointThreads was |
136 // made before this thread got a chance to reaquire monitor_, thus this | 208 // made before this thread got a chance to reaquire monitor_, thus this |
137 // thread should (again) decrease remaining_ to indicate cooperation in | 209 // thread should (again) decrease remaining_ to indicate cooperation in |
138 // this new round. | 210 // this new round. |
139 } | 211 } |
140 } | 212 } |
141 | 213 |
142 | 214 |
143 intptr_t ThreadRegistry::CountScheduledLocked() { | 215 intptr_t ThreadRegistry::CountScheduledLocked() { |
144 intptr_t count = 0; | 216 intptr_t count = 0; |
145 for (int i = 0; i < entries_.length(); ++i) { | 217 Thread* iterator = active_list_; |
146 const Entry& entry = entries_[i]; | 218 while (iterator != NULL) { |
147 if (entry.scheduled) { | 219 ++count; |
148 ++count; | 220 iterator = iterator->next_; |
149 } | |
150 } | 221 } |
151 return count; | 222 return count; |
152 } | 223 } |
153 | 224 |
154 } // namespace dart | 225 } // namespace dart |
OLD | NEW |