Index: ifq.c =================================================================== RCS file: /cvs/src/sys/net/ifq.c,v retrieving revision 1.35 diff -u -p -r1.35 ifq.c --- ifq.c 8 Oct 2019 04:18:00 -0000 1.35 +++ ifq.c 25 Jan 2020 06:02:22 -0000 @@ -389,6 +389,45 @@ ifq_dequeue(struct ifqueue *ifq) } int +ifq_deq_sleep(struct ifqueue *ifq, struct mbuf **mp, int nbio, int priority, + const char *wmesg, volatile unsigned int *sleeping, + volatile unsigned int *alive) +{ + struct mbuf *m; + void *cookie; + int error; + + ifq_deq_enter(ifq); + if (ifq->ifq_len == 0 && nbio) + error = EWOULDBLOCK; + else { + for (;;) { + m = ifq->ifq_ops->ifqop_deq_begin(ifq, &cookie); + if (m != NULL) { + ifq->ifq_ops->ifqop_deq_commit(ifq, m, cookie); + ifq->ifq_len--; + *mp = m; + break; + } + + (*sleeping)++; + error = msleep_nsec(ifq, &ifq->ifq_mtx, + priority, wmesg, INFSLP); + (*sleeping)--; + if (error != 0) + break; + if (!(*alive)) { + error = ENXIO; + break; + } + } + } + ifq_deq_leave(ifq); + + return (error); +} + +int ifq_hdatalen(struct ifqueue *ifq) { struct mbuf *m; Index: ifq.h =================================================================== RCS file: /cvs/src/sys/net/ifq.h,v retrieving revision 1.26 diff -u -p -r1.26 ifq.h --- ifq.h 16 Apr 2019 04:04:19 -0000 1.26 +++ ifq.h 25 Jan 2020 06:02:22 -0000 @@ -413,6 +413,11 @@ void ifq_q_leave(struct ifqueue *, voi void ifq_serialize(struct ifqueue *, struct task *); void ifq_barrier(struct ifqueue *); + +int ifq_deq_sleep(struct ifqueue *, struct mbuf **, int, int, + const char *, volatile unsigned int *, + volatile unsigned int *); + #define ifq_len(_ifq) ((_ifq)->ifq_len) #define ifq_empty(_ifq) (ifq_len(_ifq) == 0) #define ifq_set_maxlen(_ifq, _l) ((_ifq)->ifq_maxlen = (_l)) Index: if_tun.c =================================================================== RCS file: /cvs/src/sys/net/if_tun.c,v retrieving revision 1.211 diff -u -p -r1.211 if_tun.c --- if_tun.c 25 Jan 2020 05:28:31 -0000 1.211 +++ if_tun.c 25 Jan 2020 06:02:22 -0000 @@ -766,29 +766,10 @@ tun_dev_read(dev_t dev, struct uio *uio, ifp = &sc->sc_if; - m0 = ifq_dequeue(&ifp->if_snd); - if (m0 == NULL) { - if (ISSET(ioflag, IO_NDELAY)) { - error = EWOULDBLOCK; - goto put; - } - - do { - sc->sc_reading++; - error = tsleep_nsec(sc, (PZERO + 1)|PCATCH, - "tunread", INFSLP); - sc->sc_reading--; - if (error != 0) - goto put; - - if (ISSET(sc->sc_flags, TUN_DEAD)) { - error = ENXIO; - goto put; - } - - m0 = ifq_dequeue(&ifp->if_snd); - } while (m0 == NULL); - } + error = ifq_deq_sleep(&ifp->if_snd, &m0, ioflag, (PZERO + 1)|PCATCH, + "tunread", &sc->sc_reading, &sc->sc_dev); + if (error != 0) + goto put; #if NBPFILTER > 0 if (ifp->if_bpf)