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 |