Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: runtime/vm/os_thread.cc

Issue 1537543002: Fix for issue 25236 (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code-review-comments Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/os_thread.h ('k') | runtime/vm/os_thread_android.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/os_thread.h" 5 #include "vm/os_thread.h"
6 6
7 #include "vm/atomic.h" 7 #include "vm/atomic.h"
8 #include "vm/lockers.h" 8 #include "vm/lockers.h"
9 #include "vm/log.h" 9 #include "vm/log.h"
10 #include "vm/thread_interrupter.h" 10 #include "vm/thread_interrupter.h"
11 11
12 namespace dart { 12 namespace dart {
13 13
14 // The single thread local key which stores all the thread local data 14 // The single thread local key which stores all the thread local data
15 // for a thread. 15 // for a thread.
16 ThreadLocalKey OSThread::thread_key_ = kUnsetThreadLocalKey; 16 ThreadLocalKey OSThread::thread_key_ = kUnsetThreadLocalKey;
17 OSThread* OSThread::thread_list_head_ = NULL; 17 OSThread* OSThread::thread_list_head_ = NULL;
18 Mutex* OSThread::thread_list_lock_ = NULL; 18 Mutex* OSThread::thread_list_lock_ = NULL;
19 bool OSThread::creation_enabled_ = false;
19 20
20 21
21 OSThread::OSThread() : 22 OSThread::OSThread() :
22 BaseThread(true), 23 BaseThread(true),
23 id_(OSThread::GetCurrentThreadId()), 24 id_(OSThread::GetCurrentThreadId()),
24 join_id_(OSThread::GetCurrentThreadJoinId()), 25 join_id_(OSThread::GetCurrentThreadJoinId()),
25 trace_id_(OSThread::GetCurrentThreadTraceId()), 26 trace_id_(OSThread::GetCurrentThreadTraceId()),
26 name_(NULL), 27 name_(NULL),
27 timeline_block_lock_(new Mutex()), 28 timeline_block_lock_(new Mutex()),
28 timeline_block_(NULL), 29 timeline_block_(NULL),
29 thread_list_next_(NULL), 30 thread_list_next_(NULL),
30 thread_interrupt_disabled_(1), // Thread interrupts disabled by default. 31 thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
31 log_(new class Log()), 32 log_(new class Log()),
32 stack_base_(0), 33 stack_base_(0),
33 thread_(NULL) { 34 thread_(NULL) {
34 AddThreadToList(this);
35 } 35 }
36 36
37 37
38 OSThread* OSThread::CreateOSThread() {
39 ASSERT(thread_list_lock_ != NULL);
40 MutexLocker ml(thread_list_lock_);
41 if (!creation_enabled_) {
42 return NULL;
43 }
44 OSThread* os_thread = new OSThread();
45 AddThreadToListLocked(os_thread);
46 return os_thread;
47 }
48
49
38 OSThread::~OSThread() { 50 OSThread::~OSThread() {
39 RemoveThreadFromList(this); 51 RemoveThreadFromList(this);
40 delete log_; 52 delete log_;
41 log_ = NULL; 53 log_ = NULL;
42 if (Timeline::recorder() != NULL) { 54 if (Timeline::recorder() != NULL) {
43 Timeline::recorder()->FinishBlock(timeline_block_); 55 Timeline::recorder()->FinishBlock(timeline_block_);
44 } 56 }
45 timeline_block_ = NULL; 57 timeline_block_ = NULL;
46 delete timeline_block_lock_; 58 delete timeline_block_lock_;
47 free(name_); 59 free(name_);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 // Allocate the global OSThread lock. 97 // Allocate the global OSThread lock.
86 ASSERT(thread_list_lock_ == NULL); 98 ASSERT(thread_list_lock_ == NULL);
87 thread_list_lock_ = new Mutex(); 99 thread_list_lock_ = new Mutex();
88 ASSERT(thread_list_lock_ != NULL); 100 ASSERT(thread_list_lock_ != NULL);
89 101
90 // Create the thread local key. 102 // Create the thread local key.
91 ASSERT(thread_key_ == kUnsetThreadLocalKey); 103 ASSERT(thread_key_ == kUnsetThreadLocalKey);
92 thread_key_ = CreateThreadLocal(DeleteThread); 104 thread_key_ = CreateThreadLocal(DeleteThread);
93 ASSERT(thread_key_ != kUnsetThreadLocalKey); 105 ASSERT(thread_key_ != kUnsetThreadLocalKey);
94 106
107 // Enable creation of OSThread structures in the VM.
108 EnableOSThreadCreation();
109
95 // Create a new OSThread strcture and set it as the TLS. 110 // Create a new OSThread strcture and set it as the TLS.
96 OSThread* os_thread = new OSThread(); 111 OSThread* os_thread = CreateOSThread();
112 ASSERT(os_thread != NULL);
97 OSThread::SetCurrent(os_thread); 113 OSThread::SetCurrent(os_thread);
98 os_thread->set_name("Dart_Initialize"); 114 os_thread->set_name("Dart_Initialize");
99 } 115 }
100 116
101 117
102 void OSThread::Cleanup() { 118 void OSThread::Cleanup() {
103 if (thread_list_lock_ != NULL) { 119 if (thread_list_lock_ != NULL) {
104 // Delete the thread local key. 120 // Delete the thread local key.
105 ASSERT(thread_key_ != kUnsetThreadLocalKey); 121 ASSERT(thread_key_ != kUnsetThreadLocalKey);
106 DeleteThreadLocal(thread_key_); 122 DeleteThreadLocal(thread_key_);
107 thread_key_ = kUnsetThreadLocalKey; 123 thread_key_ = kUnsetThreadLocalKey;
108 124
109 // Delete the global OSThread lock. 125 // Delete the global OSThread lock.
110 ASSERT(thread_list_lock_ != NULL); 126 ASSERT(thread_list_lock_ != NULL);
111 delete thread_list_lock_; 127 delete thread_list_lock_;
112 thread_list_lock_ = NULL; 128 thread_list_lock_ = NULL;
113 } 129 }
114 } 130 }
115 131
116 132
117 OSThread* OSThread::CreateAndSetUnknownThread() { 133 OSThread* OSThread::CreateAndSetUnknownThread() {
118 ASSERT(OSThread::Current() == NULL); 134 ASSERT(OSThread::GetCurrentTLS() == NULL);
119 OSThread* os_thread = new OSThread(); 135 OSThread* os_thread = CreateOSThread();
120 OSThread::SetCurrent(os_thread); 136 if (os_thread != NULL) {
121 os_thread->set_name("Unknown"); 137 OSThread::SetCurrent(os_thread);
138 os_thread->set_name("Unknown");
139 }
122 return os_thread; 140 return os_thread;
123 } 141 }
124 142
125 143
126 bool OSThread::IsThreadInList(ThreadJoinId join_id) { 144 bool OSThread::IsThreadInList(ThreadJoinId join_id) {
127 if (join_id == OSThread::kInvalidThreadJoinId) { 145 if (join_id == OSThread::kInvalidThreadJoinId) {
128 return false; 146 return false;
129 } 147 }
130 OSThreadIterator it; 148 OSThreadIterator it;
131 while (it.HasNext()) { 149 while (it.HasNext()) {
132 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); 150 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
133 OSThread* t = it.Next(); 151 OSThread* t = it.Next();
134 // An address test is not sufficient because the allocator may recycle 152 // An address test is not sufficient because the allocator may recycle
135 // the address for another Thread. Test against the thread's join id. 153 // the address for another Thread. Test against the thread's join id.
136 if (t->join_id() == join_id) { 154 if (t->join_id() == join_id) {
137 return true; 155 return true;
138 } 156 }
139 } 157 }
140 return false; 158 return false;
141 } 159 }
142 160
143 161
162 void OSThread::DisableOSThreadCreation() {
163 MutexLocker ml(thread_list_lock_);
164 creation_enabled_ = false;
165 }
166
167
168 void OSThread::EnableOSThreadCreation() {
169 MutexLocker ml(thread_list_lock_);
170 creation_enabled_ = true;
171 }
172
173
144 OSThread* OSThread::GetOSThreadFromThread(Thread* thread) { 174 OSThread* OSThread::GetOSThreadFromThread(Thread* thread) {
145 ASSERT(thread->os_thread() != NULL); 175 ASSERT(thread->os_thread() != NULL);
146 return thread->os_thread(); 176 return thread->os_thread();
147 } 177 }
148 178
149 179
150 void OSThread::AddThreadToList(OSThread* thread) { 180 void OSThread::AddThreadToListLocked(OSThread* thread) {
151 ASSERT(thread != NULL); 181 ASSERT(thread != NULL);
152 ASSERT(thread_list_lock_ != NULL); 182 ASSERT(thread_list_lock_ != NULL);
153 MutexLocker ml(thread_list_lock_); 183 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
154 184 ASSERT(creation_enabled_);
155 ASSERT(thread->thread_list_next_ == NULL); 185 ASSERT(thread->thread_list_next_ == NULL);
156 186
157 #if defined(DEBUG) 187 #if defined(DEBUG)
158 { 188 {
159 // Ensure that we aren't already in the list. 189 // Ensure that we aren't already in the list.
160 OSThread* current = thread_list_head_; 190 OSThread* current = thread_list_head_;
161 while (current != NULL) { 191 while (current != NULL) {
162 ASSERT(current != thread); 192 ASSERT(current != thread);
163 current = current->thread_list_next_; 193 current = current->thread_list_next_;
164 } 194 }
165 } 195 }
166 #endif 196 #endif
167 197
168 // Insert at head of list. 198 // Insert at head of list.
169 thread->thread_list_next_ = thread_list_head_; 199 thread->thread_list_next_ = thread_list_head_;
170 thread_list_head_ = thread; 200 thread_list_head_ = thread;
171 } 201 }
172 202
173 203
174 void OSThread::RemoveThreadFromList(OSThread* thread) { 204 void OSThread::RemoveThreadFromList(OSThread* thread) {
205 bool final_thread = false;
175 { 206 {
176 ASSERT(thread != NULL); 207 ASSERT(thread != NULL);
177 ASSERT(thread_list_lock_ != NULL); 208 ASSERT(thread_list_lock_ != NULL);
178 MutexLocker ml(thread_list_lock_); 209 MutexLocker ml(thread_list_lock_);
179 OSThread* current = thread_list_head_; 210 OSThread* current = thread_list_head_;
180 OSThread* previous = NULL; 211 OSThread* previous = NULL;
181 212
182 // Scan across list and remove |thread|. 213 // Scan across list and remove |thread|.
183 while (current != NULL) { 214 while (current != NULL) {
184 if (current == thread) { 215 if (current == thread) {
185 // We found |thread|, remove from list. 216 // We found |thread|, remove from list.
186 if (previous == NULL) { 217 if (previous == NULL) {
187 thread_list_head_ = thread->thread_list_next_; 218 thread_list_head_ = thread->thread_list_next_;
188 } else { 219 } else {
189 previous->thread_list_next_ = current->thread_list_next_; 220 previous->thread_list_next_ = current->thread_list_next_;
190 } 221 }
191 thread->thread_list_next_ = NULL; 222 thread->thread_list_next_ = NULL;
223 final_thread = !creation_enabled_ && (thread_list_head_ == NULL);
192 break; 224 break;
193 } 225 }
194 previous = current; 226 previous = current;
195 current = current->thread_list_next_; 227 current = current->thread_list_next_;
196 } 228 }
197 } 229 }
198 // Check if this is the last thread. The last thread does a cleanup 230 // Check if this is the last thread. The last thread does a cleanup
199 // which removes the thread local key and the associated mutex. 231 // which removes the thread local key and the associated mutex.
200 if (thread_list_head_ == NULL) { 232 if (final_thread) {
201 Cleanup(); 233 Cleanup();
202 } 234 }
203 } 235 }
204 236
205 237
206 void OSThread::SetCurrent(OSThread* current) { 238 void OSThread::SetCurrent(OSThread* current) {
207 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); 239 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current));
208 } 240 }
209 241
210 242
(...skipping 21 matching lines...) Expand all
232 264
233 OSThread* OSThreadIterator::Next() { 265 OSThread* OSThreadIterator::Next() {
234 ASSERT(OSThread::thread_list_lock_ != NULL); 266 ASSERT(OSThread::thread_list_lock_ != NULL);
235 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); 267 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
236 OSThread* current = next_; 268 OSThread* current = next_;
237 next_ = next_->thread_list_next_; 269 next_ = next_->thread_list_next_;
238 return current; 270 return current;
239 } 271 }
240 272
241 } // namespace dart 273 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/os_thread.h ('k') | runtime/vm/os_thread_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698