| 2647 | "Number of active local sockets."); |
| 2648 | |
| 2649 | static void |
| 2650 | unp_gc(__unused void *arg, int pending) |
| 2651 | { |
| 2652 | struct unp_head *heads[] = { &unp_dhead, &unp_shead, &unp_sphead, |
| 2653 | NULL }; |
| 2654 | struct unp_head **head; |
| 2655 | struct unp_head unp_deadhead; /* List of potentially-dead sockets. */ |
| 2656 | struct file *f, **unref; |
| 2657 | struct unpcb *unp, *unptmp; |
| 2658 | int i, total, unp_unreachable; |
| 2659 | |
| 2660 | LIST_INIT(&unp_deadhead); |
| 2661 | unp_taskcount++; |
| 2662 | UNP_LINK_RLOCK(); |
| 2663 | /* |
| 2664 | * First determine which sockets may be in cycles. |
| 2665 | */ |
| 2666 | unp_unreachable = 0; |
| 2667 | |
| 2668 | for (head = heads; *head != NULL; head++) |
| 2669 | LIST_FOREACH(unp, *head, unp_link) { |
| 2670 | KASSERT((unp->unp_gcflag & ~UNPGC_IGNORE_RIGHTS) == 0, |
| 2671 | ("%s: unp %p has unexpected gc flags 0x%x", |
| 2672 | __func__, unp, (unsigned int)unp->unp_gcflag)); |
| 2673 | |
| 2674 | f = unp->unp_file; |
| 2675 | |
| 2676 | /* |
| 2677 | * Check for an unreachable socket potentially in a |
| 2678 | * cycle. It must be in a queue as indicated by |
| 2679 | * msgcount, and this must equal the file reference |
| 2680 | * count. Note that when msgcount is 0 the file is |
| 2681 | * NULL. |
| 2682 | */ |
| 2683 | if (f != NULL && unp->unp_msgcount != 0 && |
| 2684 | refcount_load(&f->f_count) == unp->unp_msgcount) { |
| 2685 | LIST_INSERT_HEAD(&unp_deadhead, unp, unp_dead); |
| 2686 | unp->unp_gcflag |= UNPGC_DEAD; |
| 2687 | unp->unp_gcrefs = unp->unp_msgcount; |
| 2688 | unp_unreachable++; |
| 2689 | } |
| 2690 | } |
| 2691 | |
| 2692 | /* |
| 2693 | * Scan all sockets previously marked as potentially being in a cycle |
| 2694 | * and remove the references each socket holds on any UNPGC_DEAD |
| 2695 | * sockets in its queue. After this step, all remaining references on |
| 2696 | * sockets marked UNPGC_DEAD should not be part of any cycle. |
| 2697 | */ |
| 2698 | LIST_FOREACH(unp, &unp_deadhead, unp_dead) |
| 2699 | unp_gc_scan(unp, unp_remove_dead_ref); |
| 2700 | |
| 2701 | /* |
| 2702 | * If a socket still has a non-negative refcount, it cannot be in a |
| 2703 | * cycle. In this case increment refcount of all children iteratively. |
| 2704 | * Stop the scan once we do a complete loop without discovering |
| 2705 | * a new reachable socket. |
| 2706 | */ |
nothing calls this directly
no test coverage detected