| 2081 | } |
| 2082 | |
| 2083 | static void |
| 2084 | kqueue_drain(struct kqueue *kq, struct thread *td) |
| 2085 | { |
| 2086 | struct knote *kn; |
| 2087 | int i; |
| 2088 | |
| 2089 | KQ_LOCK(kq); |
| 2090 | |
| 2091 | KASSERT((kq->kq_state & KQ_CLOSING) != KQ_CLOSING, |
| 2092 | ("kqueue already closing")); |
| 2093 | kq->kq_state |= KQ_CLOSING; |
| 2094 | if (kq->kq_refcnt > 1) |
| 2095 | msleep(&kq->kq_refcnt, &kq->kq_lock, PSOCK, "kqclose", 0); |
| 2096 | |
| 2097 | KASSERT(kq->kq_refcnt == 1, ("other refs are out there!")); |
| 2098 | |
| 2099 | KASSERT(knlist_empty(&kq->kq_sel.si_note), |
| 2100 | ("kqueue's knlist not empty")); |
| 2101 | |
| 2102 | for (i = 0; i < kq->kq_knlistsize; i++) { |
| 2103 | while ((kn = SLIST_FIRST(&kq->kq_knlist[i])) != NULL) { |
| 2104 | if (kn_in_flux(kn)) { |
| 2105 | kq->kq_state |= KQ_FLUXWAIT; |
| 2106 | msleep(kq, &kq->kq_lock, PSOCK, "kqclo1", 0); |
| 2107 | continue; |
| 2108 | } |
| 2109 | kn_enter_flux(kn); |
| 2110 | KQ_UNLOCK(kq); |
| 2111 | knote_drop(kn, td); |
| 2112 | KQ_LOCK(kq); |
| 2113 | } |
| 2114 | } |
| 2115 | if (kq->kq_knhashmask != 0) { |
| 2116 | for (i = 0; i <= kq->kq_knhashmask; i++) { |
| 2117 | while ((kn = SLIST_FIRST(&kq->kq_knhash[i])) != NULL) { |
| 2118 | if (kn_in_flux(kn)) { |
| 2119 | kq->kq_state |= KQ_FLUXWAIT; |
| 2120 | msleep(kq, &kq->kq_lock, PSOCK, |
| 2121 | "kqclo2", 0); |
| 2122 | continue; |
| 2123 | } |
| 2124 | kn_enter_flux(kn); |
| 2125 | KQ_UNLOCK(kq); |
| 2126 | knote_drop(kn, td); |
| 2127 | KQ_LOCK(kq); |
| 2128 | } |
| 2129 | } |
| 2130 | } |
| 2131 | |
| 2132 | if ((kq->kq_state & KQ_TASKSCHED) == KQ_TASKSCHED) { |
| 2133 | kq->kq_state |= KQ_TASKDRAIN; |
| 2134 | msleep(&kq->kq_state, &kq->kq_lock, PSOCK, "kqtqdr", 0); |
| 2135 | } |
| 2136 | |
| 2137 | if ((kq->kq_state & KQ_SEL) == KQ_SEL) { |
| 2138 | selwakeuppri(&kq->kq_sel, PSOCK); |
| 2139 | if (!SEL_WAITING(&kq->kq_sel)) |
| 2140 | kq->kq_state &= ~KQ_SEL; |
no test coverage detected