From 0472a84988ae8b754d84409901ca6a30c5f40e76 Mon Sep 17 00:00:00 2001 From: attilio Date: Thu, 15 Sep 2011 12:27:26 +0000 Subject: [PATCH] MFC r225177,225181: Introduce and use seldrain() function for dealing with fast selrecord/selinfo destruction. Sponsored by: Sandvine Incorporated git-svn-id: svn://svn.freebsd.org/base/stable/8@225585 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- share/man/man9/Makefile | 3 ++- share/man/man9/selrecord.9 | 21 +++++++++++++++++++-- sys/i386/acpica/acpi_machdep.c | 1 + sys/kern/kern_event.c | 1 + sys/kern/sys_generic.c | 17 +++++++++++++++++ sys/kern/sys_pipe.c | 1 + sys/kern/tty.c | 2 ++ sys/kern/tty_pts.c | 2 ++ sys/kern/uipc_mqueue.c | 2 ++ sys/kern/uipc_socket.c | 2 ++ sys/kern/vfs_subr.c | 1 + sys/net/bpf.c | 2 +- sys/net/if_tap.c | 1 + sys/net/if_tun.c | 1 + sys/security/audit/audit_pipe.c | 1 + sys/sys/selinfo.h | 1 + 16 files changed, 55 insertions(+), 4 deletions(-) diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index ab6e86b40..682773c28 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1050,7 +1050,8 @@ MLINKS+=scheduler.9 curpriority_cmp.9 \ scheduler.9 setrunnable.9 \ scheduler.9 updatepri.9 MLINKS+=securelevel_gt.9 securelevel_ge.9 -MLINKS+=selrecord.9 selwakeup.9 +MLINKS+=selrecord.9 seldrain.9 \ + selrecord.9 selwakeup.9 MLINKS+=sema.9 sema_destroy.9 \ sema.9 sema_init.9 \ sema.9 sema_post.9 \ diff --git a/share/man/man9/selrecord.9 b/share/man/man9/selrecord.9 index 15c5a18cf..f7a0113fc 100644 --- a/share/man/man9/selrecord.9 +++ b/share/man/man9/selrecord.9 @@ -26,10 +26,11 @@ .\" .\" $FreeBSD$ .\" -.Dd June 13, 2007 +.Dd August 25, 2011 .Dt SELRECORD 9 .Os .Sh NAME +.Nm seldrain , .Nm selrecord , .Nm selwakeup .Nd "record and wakeup select requests" @@ -37,14 +38,17 @@ .In sys/param.h .In sys/selinfo.h .Ft void +.Fn seldrain "struct selinfo *sip" +.Ft void .Fn selrecord "struct thread *td" "struct selinfo *sip" .Ft void .Fn selwakeup "struct selinfo *sip" .Sh DESCRIPTION +.Fn seldrain , .Fn selrecord and .Fn selwakeup -are the two central functions used by +are the three central functions used by .Xr select 2 , .Xr poll 2 and the objects that are being selected on. @@ -86,6 +90,15 @@ and .Xr poll 2 when they wake up. .Pp +.Fn seldrain +will flush the waiters queue on a specified object before its +destruction. +The object handling code must ensure that +.Fa *sip +cannot be used once +.Fn seldrain +has been called. +.Pp The contents of .Fa *sip must be zeroed, such as by softc initialization, before any call to @@ -98,6 +111,10 @@ acquires and releases .Va sellock and may acquire and release .Va sched_lock . +.Fn seldrain +could usually be just a wrapper for +.Fn selwakeup , +but consumers should not generally rely on this feature. .Sh SEE ALSO .Xr poll 2 , .Xr select 2 diff --git a/sys/i386/acpica/acpi_machdep.c b/sys/i386/acpica/acpi_machdep.c index fa99b48c1..ae8484584 100644 --- a/sys/i386/acpica/acpi_machdep.c +++ b/sys/i386/acpica/acpi_machdep.c @@ -313,6 +313,7 @@ apmclose(struct cdev *dev, int flag, int fmt, struct thread *td) /* Remove this clone's data from the list and free it. */ ACPI_LOCK(acpi); STAILQ_REMOVE(&acpi_sc->apm_cdevs, clone, apm_clone_data, entries); + seldrain(&clone->sel_read); knlist_destroy(&clone->sel_read.si_note); ACPI_UNLOCK(acpi); free(clone, M_APMDEV); diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index bcfe2767a..b439245af 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1686,6 +1686,7 @@ kqueue_close(struct file *fp, struct thread *td) SLIST_REMOVE(&fdp->fd_kqlist, kq, kqueue, kq_list); FILEDESC_XUNLOCK(fdp); + seldrain(&kq->kq_sel); knlist_destroy(&kq->kq_sel.si_note); mtx_destroy(&kq->kq_lock); kq->kq_fdp = NULL; diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 0f26df681..5fe35ac5b 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1442,6 +1442,23 @@ selfdfree(struct seltd *stp, struct selfd *sfp) uma_zfree(selfd_zone, sfp); } +/* Drain the waiters tied to all the selfd belonging the specified selinfo. */ +void +seldrain(sip) + struct selinfo *sip; +{ + + /* + * This feature is already provided by doselwakeup(), thus it is + * enough to go for it. + * Eventually, the context, should take care to avoid races + * between thread calling select()/poll() and file descriptor + * detaching, but, again, the races are just the same as + * selwakeup(). + */ + doselwakeup(sip, -1); +} + /* * Record a select request. */ diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index ce20d280c..985dfc4c8 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1536,6 +1536,7 @@ pipeclose(cpipe) */ knlist_clear(&cpipe->pipe_sel.si_note, 1); cpipe->pipe_present = PIPE_FINALIZED; + seldrain(&cpipe->pipe_sel); knlist_destroy(&cpipe->pipe_sel.si_note); /* diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 035bae987..eb006781e 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -986,6 +986,8 @@ tty_dealloc(void *arg) MPASS(ttyinq_getsize(&tp->t_inq) == 0); MPASS(ttyoutq_getsize(&tp->t_outq) == 0); + seldrain(&tp->t_inpoll); + seldrain(&tp->t_outpoll); knlist_destroy(&tp->t_inpoll.si_note); knlist_destroy(&tp->t_outpoll.si_note); diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index 363bdebad..31223a598 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -698,6 +698,8 @@ ptsdrv_free(void *softc) chgptscnt(psc->pts_uidinfo, -1, 0); uifree(psc->pts_uidinfo); + seldrain(&psc->pts_inpoll); + seldrain(&psc->pts_outpoll); knlist_destroy(&psc->pts_inpoll.si_note); knlist_destroy(&psc->pts_outpoll.si_note); diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index a9a9c0374..fe89287e7 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -1553,6 +1553,8 @@ mqueue_free(struct mqueue *mq) } mtx_destroy(&mq->mq_mutex); + seldrain(&mq->mq_rsel); + seldrain(&mq->mq_wsel); knlist_destroy(&mq->mq_rsel.si_note); knlist_destroy(&mq->mq_wsel.si_note); uma_zfree(mqueue_zone, mq); diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 9ca3fc1d6..86da2a35c 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -652,6 +652,8 @@ sofree(struct socket *so) */ sbdestroy(&so->so_snd, so); sbdestroy(&so->so_rcv, so); + seldrain(&so->so_snd.sb_sel); + seldrain(&so->so_rcv.sb_sel); knlist_destroy(&so->so_rcv.sb_sel.si_note); knlist_destroy(&so->so_snd.sb_sel.si_note); sodealloc(so); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 8186ee2c8..fe362ace9 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -3311,6 +3311,7 @@ vbusy(struct vnode *vp) static void destroy_vpollinfo(struct vpollinfo *vi) { + seldrain(&vi->vpi_selinfo); knlist_destroy(&vi->vpi_selinfo.si_note); mtx_destroy(&vi->vpi_lock); uma_zfree(vnodepoll_zone, vi); diff --git a/sys/net/bpf.c b/sys/net/bpf.c index b670a93d7..41539d79a 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -644,10 +644,10 @@ bpf_dtor(void *data) if (d->bd_bif) bpf_detachd(d); mtx_unlock(&bpf_mtx); - selwakeuppri(&d->bd_sel, PRINET); #ifdef MAC mac_bpfdesc_destroy(d); #endif /* MAC */ + seldrain(&d->bd_sel); knlist_destroy(&d->bd_sel.si_note); callout_drain(&d->bd_callout); bpf_freed(d); diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c index ad29da044..08c669ab3 100644 --- a/sys/net/if_tap.c +++ b/sys/net/if_tap.c @@ -214,6 +214,7 @@ tap_destroy(struct tap_softc *tp) KASSERT(!(tp->tap_flags & TAP_OPEN), ("%s flags is out of sync", ifp->if_xname)); + seldrain(&tp->tap_rsel); knlist_destroy(&tp->tap_rsel.si_note); destroy_dev(tp->tap_dev); ether_ifdetach(ifp); diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 49a524936..4811bac7f 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -259,6 +259,7 @@ tun_destroy(struct tun_softc *tp) if_detach(TUN2IFP(tp)); if_free(TUN2IFP(tp)); destroy_dev(dev); + seldrain(&tp->tun_rsel); knlist_destroy(&tp->tun_rsel.si_note); mtx_destroy(&tp->tun_mtx); cv_destroy(&tp->tun_cv); diff --git a/sys/security/audit/audit_pipe.c b/sys/security/audit/audit_pipe.c index a8db1135d..a953eb020 100644 --- a/sys/security/audit/audit_pipe.c +++ b/sys/security/audit/audit_pipe.c @@ -646,6 +646,7 @@ audit_pipe_free(struct audit_pipe *ap) cv_destroy(&ap->ap_cv); AUDIT_PIPE_SX_LOCK_DESTROY(ap); AUDIT_PIPE_LOCK_DESTROY(ap); + seldrain(&ap->ap_selinfo); knlist_destroy(&ap->ap_selinfo.si_note); TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); free(ap, M_AUDIT_PIPE); diff --git a/sys/sys/selinfo.h b/sys/sys/selinfo.h index 2d2f8485e..590d184ad 100644 --- a/sys/sys/selinfo.h +++ b/sys/sys/selinfo.h @@ -51,6 +51,7 @@ struct selinfo { #define SEL_WAITING(si) (!TAILQ_EMPTY(&(si)->si_tdlist)) #ifdef _KERNEL +void seldrain(struct selinfo *sip); void selrecord(struct thread *selector, struct selinfo *sip); void selwakeup(struct selinfo *sip); void selwakeuppri(struct selinfo *sip, int pri); -- 2.45.0