| 431 | } |
| 432 | |
| 433 | static void |
| 434 | background_thread0_work(tsd_t *tsd) { |
| 435 | /* Thread0 is also responsible for launching / terminating threads. */ |
| 436 | VARIABLE_ARRAY(bool, created_threads, max_background_threads); |
| 437 | unsigned i; |
| 438 | for (i = 1; i < max_background_threads; i++) { |
| 439 | created_threads[i] = false; |
| 440 | } |
| 441 | /* Start working, and create more threads when asked. */ |
| 442 | unsigned n_created = 1; |
| 443 | while (background_thread_info[0].state != background_thread_stopped) { |
| 444 | if (background_thread_pause_check(tsd_tsdn(tsd), |
| 445 | &background_thread_info[0])) { |
| 446 | continue; |
| 447 | } |
| 448 | if (check_background_thread_creation(tsd, &n_created, |
| 449 | (bool *)&created_threads)) { |
| 450 | continue; |
| 451 | } |
| 452 | background_work_sleep_once(tsd_tsdn(tsd), |
| 453 | &background_thread_info[0], 0); |
| 454 | } |
| 455 | |
| 456 | /* |
| 457 | * Shut down other threads at exit. Note that the ctl thread is holding |
| 458 | * the global background_thread mutex (and is waiting) for us. |
| 459 | */ |
| 460 | assert(!background_thread_enabled()); |
| 461 | for (i = 1; i < max_background_threads; i++) { |
| 462 | background_thread_info_t *info = &background_thread_info[i]; |
| 463 | assert(info->state != background_thread_paused); |
| 464 | if (created_threads[i]) { |
| 465 | background_threads_disable_single(tsd, info); |
| 466 | } else { |
| 467 | malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); |
| 468 | if (info->state != background_thread_stopped) { |
| 469 | /* The thread was not created. */ |
| 470 | assert(info->state == |
| 471 | background_thread_started); |
| 472 | n_background_threads--; |
| 473 | info->state = background_thread_stopped; |
| 474 | } |
| 475 | malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); |
| 476 | } |
| 477 | } |
| 478 | background_thread_info[0].state = background_thread_stopped; |
| 479 | assert(n_background_threads == 1); |
| 480 | } |
| 481 | |
| 482 | static void |
| 483 | background_work(tsd_t *tsd, unsigned ind) { |
no test coverage detected