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
10namespace dart {
11
12ThreadRegistry::~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
28Thread* 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
37void 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
44void 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
62void 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
73void 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
85void 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
99void 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
110intptr_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
123intptr_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
137void ThreadRegistry::AddToActiveListLocked(Thread* thread) {
138 ASSERT(thread != NULL);
139 ASSERT(threads_lock()->IsOwnedByCurrentThread());
140 thread->next_ = active_list_;
141 active_list_ = thread;
142}
143
144void 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
163Thread* 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
176void 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