* Reap zombies from passed domain. */
| 578 | * Reap zombies from passed domain. |
| 579 | */ |
| 580 | static void |
| 581 | thread_reap_domain(struct thread_domain_data *tdd) |
| 582 | { |
| 583 | struct thread *itd, *ntd; |
| 584 | struct tidbatch tidbatch; |
| 585 | struct credbatch credbatch; |
| 586 | int tdcount; |
| 587 | struct plimit *lim; |
| 588 | int limcount; |
| 589 | |
| 590 | /* |
| 591 | * Reading upfront is pessimal if followed by concurrent atomic_swap, |
| 592 | * but most of the time the list is empty. |
| 593 | */ |
| 594 | if (tdd->tdd_zombies == NULL) |
| 595 | return; |
| 596 | |
| 597 | itd = (struct thread *)atomic_swap_ptr((uintptr_t *)&tdd->tdd_zombies, |
| 598 | (uintptr_t)NULL); |
| 599 | if (itd == NULL) |
| 600 | return; |
| 601 | |
| 602 | /* |
| 603 | * Multiple CPUs can get here, the race is fine as ticks is only |
| 604 | * advisory. |
| 605 | */ |
| 606 | tdd->tdd_reapticks = ticks; |
| 607 | |
| 608 | tidbatch_prep(&tidbatch); |
| 609 | credbatch_prep(&credbatch); |
| 610 | tdcount = 0; |
| 611 | lim = NULL; |
| 612 | limcount = 0; |
| 613 | |
| 614 | while (itd != NULL) { |
| 615 | ntd = itd->td_zombie; |
| 616 | EVENTHANDLER_DIRECT_INVOKE(thread_dtor, itd); |
| 617 | tidbatch_add(&tidbatch, itd); |
| 618 | credbatch_add(&credbatch, itd); |
| 619 | MPASS(itd->td_limit != NULL); |
| 620 | if (lim != itd->td_limit) { |
| 621 | if (limcount != 0) { |
| 622 | lim_freen(lim, limcount); |
| 623 | limcount = 0; |
| 624 | } |
| 625 | } |
| 626 | lim = itd->td_limit; |
| 627 | limcount++; |
| 628 | thread_free_batched(itd); |
| 629 | tidbatch_process(&tidbatch); |
| 630 | credbatch_process(&credbatch); |
| 631 | tdcount++; |
| 632 | if (tdcount == 32) { |
| 633 | thread_count_sub(tdcount); |
| 634 | tdcount = 0; |
| 635 | } |
| 636 | itd = ntd; |
| 637 | } |
no test coverage detected