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 |