| 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 |