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_ == nullptr);
18
19 // Now delete all the threads in the free list.
20 while (free_list_ != nullptr) {
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() == nullptr);
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 != nullptr) {
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->IsDartMutatorThread()) {
55 thread->VisitObjectPointers(visitor, validate_frames);
56 }
57 }
58 thread = thread->next_;
59 }
60}
61
62void ThreadRegistry::ForEachThread(
63 std::function<void(Thread* thread)> callback) {
64 MonitorLocker ml(threads_lock());
65 Thread* thread = active_list_;
66 while (thread != nullptr) {
67 callback(thread);
68 thread = thread->next_;
69 }
70}
71
72void ThreadRegistry::ReleaseStoreBuffers() {
73 MonitorLocker ml(threads_lock());
74 Thread* thread = active_list_;
75 while (thread != nullptr) {
76 if (!thread->BypassSafepoints()) {
77 thread->ReleaseStoreBuffer();
78 }
79 thread = thread->next_;
80 }
81}
82
83void ThreadRegistry::AcquireMarkingStacks() {
84 MonitorLocker ml(threads_lock());
85 Thread* thread = active_list_;
86 while (thread != nullptr) {
87 if (!thread->BypassSafepoints()) {
88 thread->MarkingStackAcquire();
89 thread->DeferredMarkingStackAcquire();
90 }
91 thread = thread->next_;
92 }
93}
94
95void ThreadRegistry::ReleaseMarkingStacks() {
96 MonitorLocker ml(threads_lock());
97 Thread* thread = active_list_;
98 while (thread != nullptr) {
99 if (!thread->BypassSafepoints()) {
100 thread->MarkingStackRelease();
101 thread->DeferredMarkingStackRelease();
102 ASSERT(!thread->is_marking());
103 }
104 thread = thread->next_;
105 }
106}
107
108void ThreadRegistry::AddToActiveListLocked(Thread* thread) {
109 ASSERT(thread != nullptr);
110 ASSERT(threads_lock()->IsOwnedByCurrentThread());
111 thread->next_ = active_list_;
112 active_list_ = thread;
113 active_isolates_count_.fetch_add(1);
114}
115
116void ThreadRegistry::RemoveFromActiveListLocked(Thread* thread) {
117 ASSERT(thread != nullptr);
118 ASSERT(threads_lock()->IsOwnedByCurrentThread());
119 Thread* prev = nullptr;
120 Thread* current = active_list_;
121 while (current != nullptr) {
122 if (current == thread) {
123 if (prev == nullptr) {
124 active_list_ = current->next_;
125 } else {
126 prev->next_ = current->next_;
127 }
128 active_isolates_count_.fetch_sub(1);
129 break;
130 }
131 prev = current;
132 current = current->next_;
133 }
134}
135
136Thread* ThreadRegistry::GetFromFreelistLocked(bool is_vm_isolate) {
137 ASSERT(threads_lock()->IsOwnedByCurrentThread());
138 Thread* thread = nullptr;
139 // Get thread structure from free list or create a new one.
140 if (free_list_ == nullptr) {
141 thread = new Thread(is_vm_isolate);
142 } else {
143 thread = free_list_;
144 free_list_ = thread->next_;
145 }
146 return thread;
147}
148
149void ThreadRegistry::ReturnToFreelistLocked(Thread* thread) {
150 ASSERT(thread != nullptr);
151 ASSERT(thread->os_thread() == nullptr);
152 ASSERT(thread->isolate_ == nullptr);
153 ASSERT(thread->isolate_group_ == nullptr);
154 ASSERT(thread->field_table_values_ == nullptr);
155 ASSERT(threads_lock()->IsOwnedByCurrentThread());
156 // Add thread to the free list.
157 thread->next_ = free_list_;
158 free_list_ = thread;
159}
160
161} // namespace dart
162

source code of dart_sdk/runtime/vm/thread_registry.cc