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 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 DEFINE_FLAG(int, worker_timeout_millis, 5000, | 13 DEFINE_FLAG(int, |
| 14 worker_timeout_millis, |
| 15 5000, |
14 "Free workers when they have been idle for this amount of time."); | 16 "Free workers when they have been idle for this amount of time."); |
15 | 17 |
16 ThreadPool::ThreadPool() | 18 ThreadPool::ThreadPool() |
17 : shutting_down_(false), | 19 : shutting_down_(false), |
18 all_workers_(NULL), | 20 all_workers_(NULL), |
19 idle_workers_(NULL), | 21 idle_workers_(NULL), |
20 count_started_(0), | 22 count_started_(0), |
21 count_stopped_(0), | 23 count_stopped_(0), |
22 count_running_(0), | 24 count_running_(0), |
23 count_idle_(0), | 25 count_idle_(0), |
24 shutting_down_workers_(NULL), | 26 shutting_down_workers_(NULL), |
25 join_list_(NULL) { | 27 join_list_(NULL) {} |
26 } | |
27 | 28 |
28 | 29 |
29 ThreadPool::~ThreadPool() { | 30 ThreadPool::~ThreadPool() { |
30 Shutdown(); | 31 Shutdown(); |
31 } | 32 } |
32 | 33 |
33 | 34 |
34 bool ThreadPool::Run(Task* task) { | 35 bool ThreadPool::Run(Task* task) { |
35 Worker* worker = NULL; | 36 Worker* worker = NULL; |
36 bool new_worker = false; | 37 bool new_worker = false; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 { | 140 { |
140 MutexLocker ml(&mutex_); | 141 MutexLocker ml(&mutex_); |
141 ASSERT(join_list_ == NULL); | 142 ASSERT(join_list_ == NULL); |
142 } | 143 } |
143 #endif | 144 #endif |
144 } | 145 } |
145 | 146 |
146 | 147 |
147 bool ThreadPool::IsIdle(Worker* worker) { | 148 bool ThreadPool::IsIdle(Worker* worker) { |
148 ASSERT(worker != NULL && worker->owned_); | 149 ASSERT(worker != NULL && worker->owned_); |
149 for (Worker* current = idle_workers_; | 150 for (Worker* current = idle_workers_; current != NULL; |
150 current != NULL; | |
151 current = current->idle_next_) { | 151 current = current->idle_next_) { |
152 if (current == worker) { | 152 if (current == worker) { |
153 return true; | 153 return true; |
154 } | 154 } |
155 } | 155 } |
156 return false; | 156 return false; |
157 } | 157 } |
158 | 158 |
159 | 159 |
160 bool ThreadPool::RemoveWorkerFromIdleList(Worker* worker) { | 160 bool ThreadPool::RemoveWorkerFromIdleList(Worker* worker) { |
161 ASSERT(worker != NULL && worker->owned_); | 161 ASSERT(worker != NULL && worker->owned_); |
162 if (idle_workers_ == NULL) { | 162 if (idle_workers_ == NULL) { |
163 return false; | 163 return false; |
164 } | 164 } |
165 | 165 |
166 // Special case head of list. | 166 // Special case head of list. |
167 if (idle_workers_ == worker) { | 167 if (idle_workers_ == worker) { |
168 idle_workers_ = worker->idle_next_; | 168 idle_workers_ = worker->idle_next_; |
169 worker->idle_next_ = NULL; | 169 worker->idle_next_ = NULL; |
170 return true; | 170 return true; |
171 } | 171 } |
172 | 172 |
173 for (Worker* current = idle_workers_; | 173 for (Worker* current = idle_workers_; current->idle_next_ != NULL; |
174 current->idle_next_ != NULL; | |
175 current = current->idle_next_) { | 174 current = current->idle_next_) { |
176 if (current->idle_next_ == worker) { | 175 if (current->idle_next_ == worker) { |
177 current->idle_next_ = worker->idle_next_; | 176 current->idle_next_ = worker->idle_next_; |
178 worker->idle_next_ = NULL; | 177 worker->idle_next_ = NULL; |
179 return true; | 178 return true; |
180 } | 179 } |
181 } | 180 } |
182 return false; | 181 return false; |
183 } | 182 } |
184 | 183 |
185 | 184 |
186 bool ThreadPool::RemoveWorkerFromAllList(Worker* worker) { | 185 bool ThreadPool::RemoveWorkerFromAllList(Worker* worker) { |
187 ASSERT(worker != NULL && worker->owned_); | 186 ASSERT(worker != NULL && worker->owned_); |
188 if (all_workers_ == NULL) { | 187 if (all_workers_ == NULL) { |
189 return false; | 188 return false; |
190 } | 189 } |
191 | 190 |
192 // Special case head of list. | 191 // Special case head of list. |
193 if (all_workers_ == worker) { | 192 if (all_workers_ == worker) { |
194 all_workers_ = worker->all_next_; | 193 all_workers_ = worker->all_next_; |
195 worker->all_next_ = NULL; | 194 worker->all_next_ = NULL; |
196 worker->owned_ = false; | 195 worker->owned_ = false; |
197 worker->done_ = true; | 196 worker->done_ = true; |
198 return true; | 197 return true; |
199 } | 198 } |
200 | 199 |
201 for (Worker* current = all_workers_; | 200 for (Worker* current = all_workers_; current->all_next_ != NULL; |
202 current->all_next_ != NULL; | |
203 current = current->all_next_) { | 201 current = current->all_next_) { |
204 if (current->all_next_ == worker) { | 202 if (current->all_next_ == worker) { |
205 current->all_next_ = worker->all_next_; | 203 current->all_next_ = worker->all_next_; |
206 worker->all_next_ = NULL; | 204 worker->all_next_ = NULL; |
207 worker->owned_ = false; | 205 worker->owned_ = false; |
208 return true; | 206 return true; |
209 } | 207 } |
210 } | 208 } |
211 return false; | 209 return false; |
212 } | 210 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 ASSERT(exit_monitor_.IsOwnedByCurrentThread()); | 289 ASSERT(exit_monitor_.IsOwnedByCurrentThread()); |
292 | 290 |
293 // Special case head of list. | 291 // Special case head of list. |
294 if (shutting_down_workers_ == worker) { | 292 if (shutting_down_workers_ == worker) { |
295 shutting_down_workers_ = worker->shutdown_next_; | 293 shutting_down_workers_ = worker->shutdown_next_; |
296 worker->shutdown_next_ = NULL; | 294 worker->shutdown_next_ = NULL; |
297 return true; | 295 return true; |
298 } | 296 } |
299 | 297 |
300 for (Worker* current = shutting_down_workers_; | 298 for (Worker* current = shutting_down_workers_; |
301 current->shutdown_next_ != NULL; | 299 current->shutdown_next_ != NULL; current = current->shutdown_next_) { |
302 current = current->shutdown_next_) { | |
303 if (current->shutdown_next_ == worker) { | 300 if (current->shutdown_next_ == worker) { |
304 current->shutdown_next_ = worker->shutdown_next_; | 301 current->shutdown_next_ = worker->shutdown_next_; |
305 worker->shutdown_next_ = NULL; | 302 worker->shutdown_next_ = NULL; |
306 return true; | 303 return true; |
307 } | 304 } |
308 } | 305 } |
309 return false; | 306 return false; |
310 } | 307 } |
311 | 308 |
312 | 309 |
313 void ThreadPool::JoinList::AddLocked(ThreadJoinId id, JoinList** list) { | 310 void ThreadPool::JoinList::AddLocked(ThreadJoinId id, JoinList** list) { |
314 *list = new JoinList(id, *list); | 311 *list = new JoinList(id, *list); |
315 } | 312 } |
316 | 313 |
317 | 314 |
318 void ThreadPool::JoinList::Join(JoinList** list) { | 315 void ThreadPool::JoinList::Join(JoinList** list) { |
319 while (*list != NULL) { | 316 while (*list != NULL) { |
320 JoinList* current = *list; | 317 JoinList* current = *list; |
321 *list = current->next(); | 318 *list = current->next(); |
322 OSThread::Join(current->id()); | 319 OSThread::Join(current->id()); |
323 delete current; | 320 delete current; |
324 } | 321 } |
325 } | 322 } |
326 | 323 |
327 | 324 |
328 ThreadPool::Task::Task() { | 325 ThreadPool::Task::Task() {} |
329 } | |
330 | 326 |
331 | 327 |
332 ThreadPool::Task::~Task() { | 328 ThreadPool::Task::~Task() {} |
333 } | |
334 | 329 |
335 | 330 |
336 ThreadPool::Worker::Worker(ThreadPool* pool) | 331 ThreadPool::Worker::Worker(ThreadPool* pool) |
337 : pool_(pool), | 332 : pool_(pool), |
338 task_(NULL), | 333 task_(NULL), |
339 id_(OSThread::kInvalidThreadId), | 334 id_(OSThread::kInvalidThreadId), |
340 done_(false), | 335 done_(false), |
341 owned_(false), | 336 owned_(false), |
342 all_next_(NULL), | 337 all_next_(NULL), |
343 idle_next_(NULL), | 338 idle_next_(NULL), |
344 shutdown_next_(NULL) { | 339 shutdown_next_(NULL) {} |
345 } | |
346 | 340 |
347 | 341 |
348 ThreadId ThreadPool::Worker::id() { | 342 ThreadId ThreadPool::Worker::id() { |
349 MonitorLocker ml(&monitor_); | 343 MonitorLocker ml(&monitor_); |
350 return id_; | 344 return id_; |
351 } | 345 } |
352 | 346 |
353 | 347 |
354 void ThreadPool::Worker::StartThread() { | 348 void ThreadPool::Worker::StartThread() { |
355 #if defined(DEBUG) | 349 #if defined(DEBUG) |
356 // Must call SetTask before StartThread. | 350 // Must call SetTask before StartThread. |
357 { // NOLINT | 351 { // NOLINT |
358 MonitorLocker ml(&monitor_); | 352 MonitorLocker ml(&monitor_); |
359 ASSERT(task_ != NULL); | 353 ASSERT(task_ != NULL); |
360 } | 354 } |
361 #endif | 355 #endif |
362 int result = OSThread::Start("Dart ThreadPool Worker", | 356 int result = OSThread::Start("Dart ThreadPool Worker", &Worker::Main, |
363 &Worker::Main, | |
364 reinterpret_cast<uword>(this)); | 357 reinterpret_cast<uword>(this)); |
365 if (result != 0) { | 358 if (result != 0) { |
366 FATAL1("Could not start worker thread: result = %d.", result); | 359 FATAL1("Could not start worker thread: result = %d.", result); |
367 } | 360 } |
368 } | 361 } |
369 | 362 |
370 | 363 |
371 void ThreadPool::Worker::SetTask(Task* task) { | 364 void ThreadPool::Worker::SetTask(Task* task) { |
372 MonitorLocker ml(&monitor_); | 365 MonitorLocker ml(&monitor_); |
373 ASSERT(task_ == NULL); | 366 ASSERT(task_ == NULL); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 // This worker is exiting because the thread pool is being shut down. | 464 // This worker is exiting because the thread pool is being shut down. |
472 // Inform the thread pool that we are exiting. We remove this worker from | 465 // Inform the thread pool that we are exiting. We remove this worker from |
473 // shutting_down_workers_ list because there will be no need for the | 466 // shutting_down_workers_ list because there will be no need for the |
474 // ThreadPool to take action for this worker. | 467 // ThreadPool to take action for this worker. |
475 ThreadJoinId join_id = OSThread::GetCurrentThreadJoinId(os_thread); | 468 ThreadJoinId join_id = OSThread::GetCurrentThreadJoinId(os_thread); |
476 { | 469 { |
477 MutexLocker ml(&pool->mutex_); | 470 MutexLocker ml(&pool->mutex_); |
478 JoinList::AddLocked(join_id, &pool->join_list_); | 471 JoinList::AddLocked(join_id, &pool->join_list_); |
479 } | 472 } |
480 | 473 |
481 // worker->id_ should never be read again, so set to invalid in debug mode | 474 // worker->id_ should never be read again, so set to invalid in debug mode |
482 // for asserts. | 475 // for asserts. |
483 #if defined(DEBUG) | 476 #if defined(DEBUG) |
484 { | 477 { |
485 MonitorLocker ml(&worker->monitor_); | 478 MonitorLocker ml(&worker->monitor_); |
486 worker->id_ = OSThread::kInvalidThreadId; | 479 worker->id_ = OSThread::kInvalidThreadId; |
487 } | 480 } |
488 #endif | 481 #endif |
489 | 482 |
490 // Remove from the shutdown list, delete, and notify the thread pool. | 483 // Remove from the shutdown list, delete, and notify the thread pool. |
491 { | 484 { |
492 MonitorLocker eml(&pool->exit_monitor_); | 485 MonitorLocker eml(&pool->exit_monitor_); |
(...skipping 12 matching lines...) Expand all Loading... |
505 } | 498 } |
506 | 499 |
507 // Call the thread exit hook here to notify the embedder that the | 500 // Call the thread exit hook here to notify the embedder that the |
508 // thread pool thread is exiting. | 501 // thread pool thread is exiting. |
509 if (Dart::thread_exit_callback() != NULL) { | 502 if (Dart::thread_exit_callback() != NULL) { |
510 (*Dart::thread_exit_callback())(); | 503 (*Dart::thread_exit_callback())(); |
511 } | 504 } |
512 } | 505 } |
513 | 506 |
514 } // namespace dart | 507 } // namespace dart |
OLD | NEW |