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/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 #include "vm/timeline.h" | 11 #include "vm/timeline.h" |
12 | 12 |
13 namespace dart { | 13 namespace dart { |
14 | 14 |
15 // The single thread local key which stores all the thread local data | 15 // The single thread local key which stores all the thread local data |
16 // for a thread. | 16 // for a thread. |
17 ThreadLocalKey OSThread::thread_key_ = kUnsetThreadLocalKey; | 17 ThreadLocalKey OSThread::thread_key_ = kUnsetThreadLocalKey; |
18 OSThread* OSThread::thread_list_head_ = NULL; | 18 OSThread* OSThread::thread_list_head_ = NULL; |
19 Mutex* OSThread::thread_list_lock_ = NULL; | 19 Mutex* OSThread::thread_list_lock_ = NULL; |
20 bool OSThread::creation_enabled_ = false; | 20 bool OSThread::creation_enabled_ = false; |
21 | 21 |
22 | |
23 OSThread::OSThread() | 22 OSThread::OSThread() |
24 : BaseThread(true), | 23 : BaseThread(true), |
25 id_(OSThread::GetCurrentThreadId()), | 24 id_(OSThread::GetCurrentThreadId()), |
26 #if defined(DEBUG) | 25 #if defined(DEBUG) |
27 join_id_(kInvalidThreadJoinId), | 26 join_id_(kInvalidThreadJoinId), |
28 #endif | 27 #endif |
29 #ifndef PRODUCT | 28 #ifndef PRODUCT |
30 trace_id_(OSThread::GetCurrentThreadTraceId()), | 29 trace_id_(OSThread::GetCurrentThreadTraceId()), |
31 #endif | 30 #endif |
32 name_(NULL), | 31 name_(NULL), |
33 timeline_block_lock_(new Mutex()), | 32 timeline_block_lock_(new Mutex()), |
34 timeline_block_(NULL), | 33 timeline_block_(NULL), |
35 thread_list_next_(NULL), | 34 thread_list_next_(NULL), |
36 thread_interrupt_disabled_(1), // Thread interrupts disabled by default. | 35 thread_interrupt_disabled_(1), // Thread interrupts disabled by default. |
37 log_(new class Log()), | 36 log_(new class Log()), |
38 stack_base_(0), | 37 stack_base_(0), |
39 thread_(NULL) { | 38 thread_(NULL) { |
40 } | 39 } |
41 | 40 |
42 | |
43 OSThread* OSThread::CreateOSThread() { | 41 OSThread* OSThread::CreateOSThread() { |
44 ASSERT(thread_list_lock_ != NULL); | 42 ASSERT(thread_list_lock_ != NULL); |
45 MutexLocker ml(thread_list_lock_); | 43 MutexLocker ml(thread_list_lock_); |
46 if (!creation_enabled_) { | 44 if (!creation_enabled_) { |
47 return NULL; | 45 return NULL; |
48 } | 46 } |
49 OSThread* os_thread = new OSThread(); | 47 OSThread* os_thread = new OSThread(); |
50 AddThreadToListLocked(os_thread); | 48 AddThreadToListLocked(os_thread); |
51 return os_thread; | 49 return os_thread; |
52 } | 50 } |
53 | 51 |
54 | |
55 OSThread::~OSThread() { | 52 OSThread::~OSThread() { |
56 RemoveThreadFromList(this); | 53 RemoveThreadFromList(this); |
57 delete log_; | 54 delete log_; |
58 log_ = NULL; | 55 log_ = NULL; |
59 if (FLAG_support_timeline) { | 56 if (FLAG_support_timeline) { |
60 if (Timeline::recorder() != NULL) { | 57 if (Timeline::recorder() != NULL) { |
61 Timeline::recorder()->FinishBlock(timeline_block_); | 58 Timeline::recorder()->FinishBlock(timeline_block_); |
62 } | 59 } |
63 } | 60 } |
64 timeline_block_ = NULL; | 61 timeline_block_ = NULL; |
65 delete timeline_block_lock_; | 62 delete timeline_block_lock_; |
66 free(name_); | 63 free(name_); |
67 } | 64 } |
68 | 65 |
69 | |
70 void OSThread::SetName(const char* name) { | 66 void OSThread::SetName(const char* name) { |
71 MutexLocker ml(thread_list_lock_); | 67 MutexLocker ml(thread_list_lock_); |
72 // Clear the old thread name. | 68 // Clear the old thread name. |
73 if (name_ != NULL) { | 69 if (name_ != NULL) { |
74 free(name_); | 70 free(name_); |
75 name_ = NULL; | 71 name_ = NULL; |
76 } | 72 } |
77 set_name(name); | 73 set_name(name); |
78 } | 74 } |
79 | 75 |
80 | |
81 void OSThread::DisableThreadInterrupts() { | 76 void OSThread::DisableThreadInterrupts() { |
82 ASSERT(OSThread::Current() == this); | 77 ASSERT(OSThread::Current() == this); |
83 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_); | 78 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_); |
84 } | 79 } |
85 | 80 |
86 | |
87 void OSThread::EnableThreadInterrupts() { | 81 void OSThread::EnableThreadInterrupts() { |
88 ASSERT(OSThread::Current() == this); | 82 ASSERT(OSThread::Current() == this); |
89 uintptr_t old = | 83 uintptr_t old = |
90 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_); | 84 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_); |
91 if (FLAG_profiler && (old == 1)) { | 85 if (FLAG_profiler && (old == 1)) { |
92 // We just decremented from 1 to 0. | 86 // We just decremented from 1 to 0. |
93 // Make sure the thread interrupter is awake. | 87 // Make sure the thread interrupter is awake. |
94 ThreadInterrupter::WakeUp(); | 88 ThreadInterrupter::WakeUp(); |
95 } | 89 } |
96 if (old == 0) { | 90 if (old == 0) { |
97 // We just decremented from 0, this means we've got a mismatched pair | 91 // We just decremented from 0, this means we've got a mismatched pair |
98 // of calls to EnableThreadInterrupts and DisableThreadInterrupts. | 92 // of calls to EnableThreadInterrupts and DisableThreadInterrupts. |
99 FATAL("Invalid call to OSThread::EnableThreadInterrupts()"); | 93 FATAL("Invalid call to OSThread::EnableThreadInterrupts()"); |
100 } | 94 } |
101 } | 95 } |
102 | 96 |
103 | |
104 bool OSThread::ThreadInterruptsEnabled() { | 97 bool OSThread::ThreadInterruptsEnabled() { |
105 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0; | 98 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0; |
106 } | 99 } |
107 | 100 |
108 | |
109 static void DeleteThread(void* thread) { | 101 static void DeleteThread(void* thread) { |
110 delete reinterpret_cast<OSThread*>(thread); | 102 delete reinterpret_cast<OSThread*>(thread); |
111 } | 103 } |
112 | 104 |
113 | |
114 void OSThread::InitOnce() { | 105 void OSThread::InitOnce() { |
115 // Allocate the global OSThread lock. | 106 // Allocate the global OSThread lock. |
116 ASSERT(thread_list_lock_ == NULL); | 107 ASSERT(thread_list_lock_ == NULL); |
117 thread_list_lock_ = new Mutex(); | 108 thread_list_lock_ = new Mutex(); |
118 ASSERT(thread_list_lock_ != NULL); | 109 ASSERT(thread_list_lock_ != NULL); |
119 | 110 |
120 // Create the thread local key. | 111 // Create the thread local key. |
121 ASSERT(thread_key_ == kUnsetThreadLocalKey); | 112 ASSERT(thread_key_ == kUnsetThreadLocalKey); |
122 thread_key_ = CreateThreadLocal(DeleteThread); | 113 thread_key_ = CreateThreadLocal(DeleteThread); |
123 ASSERT(thread_key_ != kUnsetThreadLocalKey); | 114 ASSERT(thread_key_ != kUnsetThreadLocalKey); |
124 | 115 |
125 // Enable creation of OSThread structures in the VM. | 116 // Enable creation of OSThread structures in the VM. |
126 EnableOSThreadCreation(); | 117 EnableOSThreadCreation(); |
127 | 118 |
128 // Create a new OSThread strcture and set it as the TLS. | 119 // Create a new OSThread strcture and set it as the TLS. |
129 OSThread* os_thread = CreateOSThread(); | 120 OSThread* os_thread = CreateOSThread(); |
130 ASSERT(os_thread != NULL); | 121 ASSERT(os_thread != NULL); |
131 OSThread::SetCurrent(os_thread); | 122 OSThread::SetCurrent(os_thread); |
132 os_thread->set_name("Dart_Initialize"); | 123 os_thread->set_name("Dart_Initialize"); |
133 } | 124 } |
134 | 125 |
135 | |
136 void OSThread::Cleanup() { | 126 void OSThread::Cleanup() { |
137 // We cannot delete the thread local key and thread list lock, yet. | 127 // We cannot delete the thread local key and thread list lock, yet. |
138 // See the note on thread_list_lock_ in os_thread.h. | 128 // See the note on thread_list_lock_ in os_thread.h. |
139 #if 0 | 129 #if 0 |
140 if (thread_list_lock_ != NULL) { | 130 if (thread_list_lock_ != NULL) { |
141 // Delete the thread local key. | 131 // Delete the thread local key. |
142 ASSERT(thread_key_ != kUnsetThreadLocalKey); | 132 ASSERT(thread_key_ != kUnsetThreadLocalKey); |
143 DeleteThreadLocal(thread_key_); | 133 DeleteThreadLocal(thread_key_); |
144 thread_key_ = kUnsetThreadLocalKey; | 134 thread_key_ = kUnsetThreadLocalKey; |
145 | 135 |
146 // Delete the global OSThread lock. | 136 // Delete the global OSThread lock. |
147 ASSERT(thread_list_lock_ != NULL); | 137 ASSERT(thread_list_lock_ != NULL); |
148 delete thread_list_lock_; | 138 delete thread_list_lock_; |
149 thread_list_lock_ = NULL; | 139 thread_list_lock_ = NULL; |
150 } | 140 } |
151 #endif | 141 #endif |
152 } | 142 } |
153 | 143 |
154 | |
155 OSThread* OSThread::CreateAndSetUnknownThread() { | 144 OSThread* OSThread::CreateAndSetUnknownThread() { |
156 ASSERT(OSThread::GetCurrentTLS() == NULL); | 145 ASSERT(OSThread::GetCurrentTLS() == NULL); |
157 OSThread* os_thread = CreateOSThread(); | 146 OSThread* os_thread = CreateOSThread(); |
158 if (os_thread != NULL) { | 147 if (os_thread != NULL) { |
159 OSThread::SetCurrent(os_thread); | 148 OSThread::SetCurrent(os_thread); |
160 os_thread->set_name("Unknown"); | 149 os_thread->set_name("Unknown"); |
161 } | 150 } |
162 return os_thread; | 151 return os_thread; |
163 } | 152 } |
164 | 153 |
165 | |
166 bool OSThread::IsThreadInList(ThreadId id) { | 154 bool OSThread::IsThreadInList(ThreadId id) { |
167 if (id == OSThread::kInvalidThreadId) { | 155 if (id == OSThread::kInvalidThreadId) { |
168 return false; | 156 return false; |
169 } | 157 } |
170 OSThreadIterator it; | 158 OSThreadIterator it; |
171 while (it.HasNext()) { | 159 while (it.HasNext()) { |
172 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); | 160 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); |
173 OSThread* t = it.Next(); | 161 OSThread* t = it.Next(); |
174 // An address test is not sufficient because the allocator may recycle | 162 // An address test is not sufficient because the allocator may recycle |
175 // the address for another Thread. Test against the thread's id. | 163 // the address for another Thread. Test against the thread's id. |
176 if (t->id() == id) { | 164 if (t->id() == id) { |
177 return true; | 165 return true; |
178 } | 166 } |
179 } | 167 } |
180 return false; | 168 return false; |
181 } | 169 } |
182 | 170 |
183 | |
184 void OSThread::DisableOSThreadCreation() { | 171 void OSThread::DisableOSThreadCreation() { |
185 MutexLocker ml(thread_list_lock_); | 172 MutexLocker ml(thread_list_lock_); |
186 creation_enabled_ = false; | 173 creation_enabled_ = false; |
187 } | 174 } |
188 | 175 |
189 | |
190 void OSThread::EnableOSThreadCreation() { | 176 void OSThread::EnableOSThreadCreation() { |
191 MutexLocker ml(thread_list_lock_); | 177 MutexLocker ml(thread_list_lock_); |
192 creation_enabled_ = true; | 178 creation_enabled_ = true; |
193 } | 179 } |
194 | 180 |
195 | |
196 OSThread* OSThread::GetOSThreadFromThread(Thread* thread) { | 181 OSThread* OSThread::GetOSThreadFromThread(Thread* thread) { |
197 ASSERT(thread->os_thread() != NULL); | 182 ASSERT(thread->os_thread() != NULL); |
198 return thread->os_thread(); | 183 return thread->os_thread(); |
199 } | 184 } |
200 | 185 |
201 | |
202 void OSThread::AddThreadToListLocked(OSThread* thread) { | 186 void OSThread::AddThreadToListLocked(OSThread* thread) { |
203 ASSERT(thread != NULL); | 187 ASSERT(thread != NULL); |
204 ASSERT(thread_list_lock_ != NULL); | 188 ASSERT(thread_list_lock_ != NULL); |
205 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); | 189 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); |
206 ASSERT(creation_enabled_); | 190 ASSERT(creation_enabled_); |
207 ASSERT(thread->thread_list_next_ == NULL); | 191 ASSERT(thread->thread_list_next_ == NULL); |
208 | 192 |
209 #if defined(DEBUG) | 193 #if defined(DEBUG) |
210 { | 194 { |
211 // Ensure that we aren't already in the list. | 195 // Ensure that we aren't already in the list. |
212 OSThread* current = thread_list_head_; | 196 OSThread* current = thread_list_head_; |
213 while (current != NULL) { | 197 while (current != NULL) { |
214 ASSERT(current != thread); | 198 ASSERT(current != thread); |
215 current = current->thread_list_next_; | 199 current = current->thread_list_next_; |
216 } | 200 } |
217 } | 201 } |
218 #endif | 202 #endif |
219 | 203 |
220 // Insert at head of list. | 204 // Insert at head of list. |
221 thread->thread_list_next_ = thread_list_head_; | 205 thread->thread_list_next_ = thread_list_head_; |
222 thread_list_head_ = thread; | 206 thread_list_head_ = thread; |
223 } | 207 } |
224 | 208 |
225 | |
226 void OSThread::RemoveThreadFromList(OSThread* thread) { | 209 void OSThread::RemoveThreadFromList(OSThread* thread) { |
227 bool final_thread = false; | 210 bool final_thread = false; |
228 { | 211 { |
229 ASSERT(thread != NULL); | 212 ASSERT(thread != NULL); |
230 ASSERT(thread_list_lock_ != NULL); | 213 ASSERT(thread_list_lock_ != NULL); |
231 MutexLocker ml(thread_list_lock_); | 214 MutexLocker ml(thread_list_lock_); |
232 OSThread* current = thread_list_head_; | 215 OSThread* current = thread_list_head_; |
233 OSThread* previous = NULL; | 216 OSThread* previous = NULL; |
234 | 217 |
235 // Scan across list and remove |thread|. | 218 // Scan across list and remove |thread|. |
(...skipping 13 matching lines...) Expand all Loading... |
249 current = current->thread_list_next_; | 232 current = current->thread_list_next_; |
250 } | 233 } |
251 } | 234 } |
252 // Check if this is the last thread. The last thread does a cleanup | 235 // Check if this is the last thread. The last thread does a cleanup |
253 // which removes the thread local key and the associated mutex. | 236 // which removes the thread local key and the associated mutex. |
254 if (final_thread) { | 237 if (final_thread) { |
255 Cleanup(); | 238 Cleanup(); |
256 } | 239 } |
257 } | 240 } |
258 | 241 |
259 | |
260 void OSThread::SetCurrent(OSThread* current) { | 242 void OSThread::SetCurrent(OSThread* current) { |
261 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); | 243 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); |
262 } | 244 } |
263 | 245 |
264 | |
265 OSThreadIterator::OSThreadIterator() { | 246 OSThreadIterator::OSThreadIterator() { |
266 ASSERT(OSThread::thread_list_lock_ != NULL); | 247 ASSERT(OSThread::thread_list_lock_ != NULL); |
267 // Lock the thread list while iterating. | 248 // Lock the thread list while iterating. |
268 OSThread::thread_list_lock_->Lock(); | 249 OSThread::thread_list_lock_->Lock(); |
269 next_ = OSThread::thread_list_head_; | 250 next_ = OSThread::thread_list_head_; |
270 } | 251 } |
271 | 252 |
272 | |
273 OSThreadIterator::~OSThreadIterator() { | 253 OSThreadIterator::~OSThreadIterator() { |
274 ASSERT(OSThread::thread_list_lock_ != NULL); | 254 ASSERT(OSThread::thread_list_lock_ != NULL); |
275 // Unlock the thread list when done. | 255 // Unlock the thread list when done. |
276 OSThread::thread_list_lock_->Unlock(); | 256 OSThread::thread_list_lock_->Unlock(); |
277 } | 257 } |
278 | 258 |
279 | |
280 bool OSThreadIterator::HasNext() const { | 259 bool OSThreadIterator::HasNext() const { |
281 ASSERT(OSThread::thread_list_lock_ != NULL); | 260 ASSERT(OSThread::thread_list_lock_ != NULL); |
282 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); | 261 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); |
283 return next_ != NULL; | 262 return next_ != NULL; |
284 } | 263 } |
285 | 264 |
286 | |
287 OSThread* OSThreadIterator::Next() { | 265 OSThread* OSThreadIterator::Next() { |
288 ASSERT(OSThread::thread_list_lock_ != NULL); | 266 ASSERT(OSThread::thread_list_lock_ != NULL); |
289 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); | 267 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread()); |
290 OSThread* current = next_; | 268 OSThread* current = next_; |
291 next_ = next_->thread_list_next_; | 269 next_ = next_->thread_list_next_; |
292 return current; | 270 return current; |
293 } | 271 } |
294 | 272 |
295 } // namespace dart | 273 } // namespace dart |
OLD | NEW |