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 |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #include "vm/thread_registry.h" |
6 | |
7 | #include "vm/json_stream.h" |
8 | #include "vm/lockers.h" |
9 | |
10 | namespace dart { |
11 | |
12 | ThreadRegistry::~ThreadRegistry() { |
13 | // Go over the free thread list and delete the thread objects. |
14 | { |
15 | MonitorLocker ml(threads_lock()); |
16 | // At this point the active list should be empty. |
17 | ASSERT(active_list_ == NULL); |
18 | |
19 | // Now delete all the threads in the free list. |
20 | while (free_list_ != NULL) { |
21 | Thread* thread = free_list_; |
22 | free_list_ = thread->next_; |
23 | delete thread; |
24 | } |
25 | } |
26 | } |
27 | |
28 | Thread* ThreadRegistry::GetFreeThreadLocked(bool is_vm_isolate) { |
29 | ASSERT(threads_lock()->IsOwnedByCurrentThread()); |
30 | Thread* thread = GetFromFreelistLocked(is_vm_isolate); |
31 | ASSERT(thread->api_top_scope() == NULL); |
32 | // Now add this Thread to the active list for the isolate. |
33 | AddToActiveListLocked(thread); |
34 | return thread; |
35 | } |
36 | |
37 | void ThreadRegistry::ReturnThreadLocked(Thread* thread) { |
38 | ASSERT(threads_lock()->IsOwnedByCurrentThread()); |
39 | // Remove thread from the active list for the isolate. |
40 | RemoveFromActiveListLocked(thread); |
41 | ReturnToFreelistLocked(thread); |
42 | } |
43 | |
44 | void ThreadRegistry::VisitObjectPointers( |
45 | IsolateGroup* isolate_group_of_interest, |
46 | ObjectPointerVisitor* visitor, |
47 | ValidationPolicy validate_frames) { |
48 | MonitorLocker ml(threads_lock()); |
49 | Thread* thread = active_list_; |
50 | while (thread != NULL) { |
51 | if (thread->isolate_group() == isolate_group_of_interest) { |
52 | // The mutator thread is visited by the isolate itself (see |
53 | // [IsolateGroup::VisitStackPointers]). |
54 | if (!thread->IsMutatorThread()) { |
55 | thread->VisitObjectPointers(visitor, validate_frames); |
56 | } |
57 | } |
58 | thread = thread->next_; |
59 | } |
60 | } |
61 | |
62 | void ThreadRegistry::ReleaseStoreBuffers() { |
63 | MonitorLocker ml(threads_lock()); |
64 | Thread* thread = active_list_; |
65 | while (thread != NULL) { |
66 | if (!thread->BypassSafepoints()) { |
67 | thread->ReleaseStoreBuffer(); |
68 | } |
69 | thread = thread->next_; |
70 | } |
71 | } |
72 | |
73 | void ThreadRegistry::AcquireMarkingStacks() { |
74 | MonitorLocker ml(threads_lock()); |
75 | Thread* thread = active_list_; |
76 | while (thread != NULL) { |
77 | if (!thread->BypassSafepoints()) { |
78 | thread->MarkingStackAcquire(); |
79 | thread->DeferredMarkingStackAcquire(); |
80 | } |
81 | thread = thread->next_; |
82 | } |
83 | } |
84 | |
85 | void ThreadRegistry::ReleaseMarkingStacks() { |
86 | MonitorLocker ml(threads_lock()); |
87 | Thread* thread = active_list_; |
88 | while (thread != NULL) { |
89 | if (!thread->BypassSafepoints()) { |
90 | thread->MarkingStackRelease(); |
91 | thread->DeferredMarkingStackRelease(); |
92 | ASSERT(!thread->is_marking()); |
93 | } |
94 | thread = thread->next_; |
95 | } |
96 | } |
97 | |
98 | #ifndef PRODUCT |
99 | void ThreadRegistry::PrintJSON(JSONStream* stream) const { |
100 | MonitorLocker ml(threads_lock()); |
101 | JSONArray threads(stream); |
102 | Thread* current = active_list_; |
103 | while (current != NULL) { |
104 | threads.AddValue(current); |
105 | current = current->next_; |
106 | } |
107 | } |
108 | #endif |
109 | |
110 | intptr_t ThreadRegistry::CountZoneHandles(Isolate* isolate_of_interest) const { |
111 | MonitorLocker ml(threads_lock()); |
112 | intptr_t count = 0; |
113 | Thread* current = active_list_; |
114 | while (current != NULL) { |
115 | if (current->isolate() == isolate_of_interest) { |
116 | count += current->CountZoneHandles(); |
117 | } |
118 | current = current->next_; |
119 | } |
120 | return count; |
121 | } |
122 | |
123 | intptr_t ThreadRegistry::CountScopedHandles( |
124 | Isolate* isolate_of_interest) const { |
125 | MonitorLocker ml(threads_lock()); |
126 | intptr_t count = 0; |
127 | Thread* current = active_list_; |
128 | while (current != NULL) { |
129 | if (current->isolate() == isolate_of_interest) { |
130 | count += current->CountScopedHandles(); |
131 | } |
132 | current = current->next_; |
133 | } |
134 | return count; |
135 | } |
136 | |
137 | void ThreadRegistry::AddToActiveListLocked(Thread* thread) { |
138 | ASSERT(thread != NULL); |
139 | ASSERT(threads_lock()->IsOwnedByCurrentThread()); |
140 | thread->next_ = active_list_; |
141 | active_list_ = thread; |
142 | } |
143 | |
144 | void ThreadRegistry::RemoveFromActiveListLocked(Thread* thread) { |
145 | ASSERT(thread != NULL); |
146 | ASSERT(threads_lock()->IsOwnedByCurrentThread()); |
147 | Thread* prev = NULL; |
148 | Thread* current = active_list_; |
149 | while (current != NULL) { |
150 | if (current == thread) { |
151 | if (prev == NULL) { |
152 | active_list_ = current->next_; |
153 | } else { |
154 | prev->next_ = current->next_; |
155 | } |
156 | break; |
157 | } |
158 | prev = current; |
159 | current = current->next_; |
160 | } |
161 | } |
162 | |
163 | Thread* ThreadRegistry::GetFromFreelistLocked(bool is_vm_isolate) { |
164 | ASSERT(threads_lock()->IsOwnedByCurrentThread()); |
165 | Thread* thread = NULL; |
166 | // Get thread structure from free list or create a new one. |
167 | if (free_list_ == NULL) { |
168 | thread = new Thread(is_vm_isolate); |
169 | } else { |
170 | thread = free_list_; |
171 | free_list_ = thread->next_; |
172 | } |
173 | return thread; |
174 | } |
175 | |
176 | void ThreadRegistry::ReturnToFreelistLocked(Thread* thread) { |
177 | ASSERT(thread != NULL); |
178 | ASSERT(thread->os_thread() == NULL); |
179 | ASSERT(thread->isolate_ == NULL); |
180 | ASSERT(thread->heap_ == NULL); |
181 | ASSERT(threads_lock()->IsOwnedByCurrentThread()); |
182 | // Add thread to the free list. |
183 | thread->next_ = free_list_; |
184 | free_list_ = thread; |
185 | } |
186 | |
187 | } // namespace dart |
188 |