| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/thread_pool.h" | 5 #include "vm/thread_pool.h" |
| 6 | 6 |
| 7 #include "vm/dart.h" | 7 #include "vm/dart.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/lockers.h" | 9 #include "vm/lockers.h" |
| 10 | 10 |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 current->all_next_ = worker->all_next_; | 205 current->all_next_ = worker->all_next_; |
| 206 worker->all_next_ = NULL; | 206 worker->all_next_ = NULL; |
| 207 worker->owned_ = false; | 207 worker->owned_ = false; |
| 208 return true; | 208 return true; |
| 209 } | 209 } |
| 210 } | 210 } |
| 211 return false; | 211 return false; |
| 212 } | 212 } |
| 213 | 213 |
| 214 | 214 |
| 215 void ThreadPool::SetIdleLocked(Worker* worker) { |
| 216 ASSERT(mutex_.IsOwnedByCurrentThread()); |
| 217 ASSERT(worker->owned_ && !IsIdle(worker)); |
| 218 worker->idle_next_ = idle_workers_; |
| 219 idle_workers_ = worker; |
| 220 count_idle_++; |
| 221 count_running_--; |
| 222 } |
| 223 |
| 224 |
| 215 void ThreadPool::SetIdleAndReapExited(Worker* worker) { | 225 void ThreadPool::SetIdleAndReapExited(Worker* worker) { |
| 216 JoinList* list = NULL; | 226 JoinList* list = NULL; |
| 217 { | 227 { |
| 218 MutexLocker ml(&mutex_); | 228 MutexLocker ml(&mutex_); |
| 219 if (shutting_down_) { | 229 if (shutting_down_) { |
| 220 return; | 230 return; |
| 221 } | 231 } |
| 222 ASSERT(worker->owned_ && !IsIdle(worker)); | 232 if (join_list_ == NULL) { |
| 223 worker->idle_next_ = idle_workers_; | 233 // Nothing to join, add to the idle list and return. |
| 224 idle_workers_ = worker; | 234 SetIdleLocked(worker); |
| 225 count_idle_++; | 235 return; |
| 226 count_running_--; | 236 } |
| 227 | 237 // There is something to join. Grab the join list, drop the lock, do the |
| 228 // While we have the lock, opportunistically grab and clear the join_list_. | 238 // join, then grab the lock again and add to the idle list. |
| 229 list = join_list_; | 239 list = join_list_; |
| 230 join_list_ = NULL; | 240 join_list_ = NULL; |
| 231 } | 241 } |
| 232 JoinList::Join(&list); | 242 JoinList::Join(&list); |
| 243 |
| 244 { |
| 245 MutexLocker ml(&mutex_); |
| 246 if (shutting_down_) { |
| 247 return; |
| 248 } |
| 249 SetIdleLocked(worker); |
| 250 } |
| 233 } | 251 } |
| 234 | 252 |
| 235 | 253 |
| 236 bool ThreadPool::ReleaseIdleWorker(Worker* worker) { | 254 bool ThreadPool::ReleaseIdleWorker(Worker* worker) { |
| 237 MutexLocker ml(&mutex_); | 255 MutexLocker ml(&mutex_); |
| 238 if (shutting_down_) { | 256 if (shutting_down_) { |
| 239 return false; | 257 return false; |
| 240 } | 258 } |
| 241 // Remove from idle list. | 259 // Remove from idle list. |
| 242 if (!RemoveWorkerFromIdleList(worker)) { | 260 if (!RemoveWorkerFromIdleList(worker)) { |
| 243 return false; | 261 return false; |
| 244 } | 262 } |
| 245 // Remove from all list. | 263 // Remove from all list. |
| 246 bool found = RemoveWorkerFromAllList(worker); | 264 bool found = RemoveWorkerFromAllList(worker); |
| 247 ASSERT(found); | 265 ASSERT(found); |
| 248 | 266 |
| 249 // The thread for worker will exit. Add its ThreadId to the join_list_ | 267 // The thread for worker will exit. Add its ThreadId to the join_list_ |
| 250 // so that we can join on it at the next opportunity. | 268 // so that we can join on it at the next opportunity. |
| 251 OSThread* os_thread = OSThread::Current(); | 269 OSThread* os_thread = OSThread::Current(); |
| 252 ASSERT(os_thread != NULL); | 270 ASSERT(os_thread != NULL); |
| 253 JoinList::AddLocked(os_thread->join_id(), &join_list_); | 271 ThreadJoinId join_id = OSThread::GetCurrentThreadJoinId(os_thread); |
| 272 JoinList::AddLocked(join_id, &join_list_); |
| 254 count_stopped_++; | 273 count_stopped_++; |
| 255 count_idle_--; | 274 count_idle_--; |
| 256 return true; | 275 return true; |
| 257 } | 276 } |
| 258 | 277 |
| 259 | 278 |
| 260 // Only call while holding the exit_monitor_ | 279 // Only call while holding the exit_monitor_ |
| 261 void ThreadPool::AddWorkerToShutdownList(Worker* worker) { | 280 void ThreadPool::AddWorkerToShutdownList(Worker* worker) { |
| 262 ASSERT(exit_monitor_.IsOwnedByCurrentThread()); | 281 ASSERT(exit_monitor_.IsOwnedByCurrentThread()); |
| 263 worker->shutdown_next_ = shutting_down_workers_; | 282 worker->shutdown_next_ = shutting_down_workers_; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 ml.Notify(); | 442 ml.Notify(); |
| 424 } | 443 } |
| 425 | 444 |
| 426 | 445 |
| 427 // static | 446 // static |
| 428 void ThreadPool::Worker::Main(uword args) { | 447 void ThreadPool::Worker::Main(uword args) { |
| 429 Worker* worker = reinterpret_cast<Worker*>(args); | 448 Worker* worker = reinterpret_cast<Worker*>(args); |
| 430 OSThread* os_thread = OSThread::Current(); | 449 OSThread* os_thread = OSThread::Current(); |
| 431 ASSERT(os_thread != NULL); | 450 ASSERT(os_thread != NULL); |
| 432 ThreadId id = os_thread->id(); | 451 ThreadId id = os_thread->id(); |
| 433 ThreadJoinId join_id = os_thread->join_id(); | |
| 434 ThreadPool* pool; | 452 ThreadPool* pool; |
| 435 | 453 |
| 436 // Set the thread's stack_base based on the current stack pointer. | 454 // Set the thread's stack_base based on the current stack pointer. |
| 437 os_thread->set_stack_base(Thread::GetCurrentStackPointer()); | 455 os_thread->set_stack_base(Thread::GetCurrentStackPointer()); |
| 438 | 456 |
| 439 { | 457 { |
| 440 MonitorLocker ml(&worker->monitor_); | 458 MonitorLocker ml(&worker->monitor_); |
| 441 ASSERT(worker->task_); | 459 ASSERT(worker->task_); |
| 442 worker->id_ = id; | 460 worker->id_ = id; |
| 443 pool = worker->pool_; | 461 pool = worker->pool_; |
| 444 } | 462 } |
| 445 | 463 |
| 446 bool released = worker->Loop(); | 464 bool released = worker->Loop(); |
| 447 | 465 |
| 448 // It should be okay to access these unlocked here in this assert. | 466 // It should be okay to access these unlocked here in this assert. |
| 449 // worker->all_next_ is retained by the pool for shutdown monitoring. | 467 // worker->all_next_ is retained by the pool for shutdown monitoring. |
| 450 ASSERT(!worker->owned_ && (worker->idle_next_ == NULL)); | 468 ASSERT(!worker->owned_ && (worker->idle_next_ == NULL)); |
| 451 | 469 |
| 452 if (!released) { | 470 if (!released) { |
| 453 // This worker is exiting because the thread pool is being shut down. | 471 // This worker is exiting because the thread pool is being shut down. |
| 454 // Inform the thread pool that we are exiting. We remove this worker from | 472 // Inform the thread pool that we are exiting. We remove this worker from |
| 455 // shutting_down_workers_ list because there will be no need for the | 473 // shutting_down_workers_ list because there will be no need for the |
| 456 // ThreadPool to take action for this worker. | 474 // ThreadPool to take action for this worker. |
| 475 ThreadJoinId join_id = OSThread::GetCurrentThreadJoinId(os_thread); |
| 457 { | 476 { |
| 458 MutexLocker ml(&pool->mutex_); | 477 MutexLocker ml(&pool->mutex_); |
| 459 JoinList::AddLocked(join_id, &pool->join_list_); | 478 JoinList::AddLocked(join_id, &pool->join_list_); |
| 460 } | 479 } |
| 461 | 480 |
| 462 // worker->id_ should never be read again, so set to invalid in debug mode | 481 // worker->id_ should never be read again, so set to invalid in debug mode |
| 463 // for asserts. | 482 // for asserts. |
| 464 #if defined(DEBUG) | 483 #if defined(DEBUG) |
| 465 { | 484 { |
| 466 MonitorLocker ml(&worker->monitor_); | 485 MonitorLocker ml(&worker->monitor_); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 486 } | 505 } |
| 487 | 506 |
| 488 // Call the thread exit hook here to notify the embedder that the | 507 // Call the thread exit hook here to notify the embedder that the |
| 489 // thread pool thread is exiting. | 508 // thread pool thread is exiting. |
| 490 if (Dart::thread_exit_callback() != NULL) { | 509 if (Dart::thread_exit_callback() != NULL) { |
| 491 (*Dart::thread_exit_callback())(); | 510 (*Dart::thread_exit_callback())(); |
| 492 } | 511 } |
| 493 } | 512 } |
| 494 | 513 |
| 495 } // namespace dart | 514 } // namespace dart |
| OLD | NEW |