From owner-freebsd-smp Sun Mar 10 16:11:58 2002 Delivered-To: freebsd-smp@freebsd.org Received: from elvis.mu.org (elvis.mu.org [192.203.228.196]) by hub.freebsd.org (Postfix) with ESMTP id 4ACE737B404; Sun, 10 Mar 2002 16:11:31 -0800 (PST) Received: by elvis.mu.org (Postfix, from userid 1192) id 2DFD2AE211; Sun, 10 Mar 2002 16:11:31 -0800 (PST) Date: Sun, 10 Mar 2002 16:11:31 -0800 From: Alfred Perlstein To: smp@freebsd.org Cc: davidc@freebsd.org, jhb@freebsd.org Subject: select fix and giant pushdown patch Message-ID: <20020311001131.GN26621@elvis.mu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.27i Sender: owner-freebsd-smp@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org Chad David and I have been working on fixing select(2) and poll(2)'s locking. I've been working on pushing pipe read/write ops down out from under Giant. The way it works is that there is a global select lock that is very close to a leaf lock, under select/poll you'll see this order of aquisition: filedesc -> objlock -> sellock where objlock is aquired in the fo_poll routine, from interrupt or writer POV you'll see: objlock -> sellock. Also, because pfind was broken by the proc locking such that it requires an sx lock we've fixed select such that the selinfo structure contains linkages back to the thread that is waiting on the resource, when leaving select all linkages not removed via selwakeup are removed. I've also been able to push down pipe reading/writing out from under Giant, so far the performance numbers don't look much better, hopefully they will improve as more code is pulled out from under Giant. It's starting to look like a lot of the system's requiring Giant just for MALLOC/FREE which is really dissappointing considering the work I put into fixing that months ago that was backed out. This code relies slightly on psignal being MPSAFE, if it's not a small amount of performance can be scrificed by grabbing Giant before calling it. Test, review please... bye, -Alfred Index: dev/bktr/bktr_core.c =================================================================== RCS file: /home/ncvs/src/sys/dev/bktr/bktr_core.c,v retrieving revision 1.117 diff -u -r1.117 bktr_core.c --- dev/bktr/bktr_core.c 12 Sep 2001 08:37:02 -0000 1.117 +++ dev/bktr/bktr_core.c 10 Mar 2002 08:08:36 -0000 @@ -809,7 +809,7 @@ } /* If someone has a select() on /dev/vbi, inform them */ - if (bktr->vbi_select.si_pid) { + if (SEL_WAITING(&bktr->vbi_select)) { selwakeup(&bktr->vbi_select); } Index: dev/kbd/kbd.c =================================================================== RCS file: /home/ncvs/src/sys/dev/kbd/kbd.c,v retrieving revision 1.27 diff -u -r1.27 kbd.c --- dev/kbd/kbd.c 12 Sep 2001 08:37:06 -0000 1.27 +++ dev/kbd/kbd.c 10 Mar 2002 08:08:36 -0000 @@ -524,7 +524,7 @@ #endif clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */ sc->gkb_rsel.si_flags = 0; - sc->gkb_rsel.si_pid = 0; + SEL_INIT(&sc->gkb_rsel); splx(s); return 0; Index: dev/snp/snp.c =================================================================== RCS file: /home/ncvs/src/sys/dev/snp/snp.c,v retrieving revision 1.69 diff -u -r1.69 snp.c --- dev/snp/snp.c 24 Nov 2001 15:59:46 -0000 1.69 +++ dev/snp/snp.c 10 Mar 2002 08:08:36 -0000 @@ -373,7 +373,6 @@ wakeup((caddr_t)snp); } selwakeup(&snp->snp_sel); - snp->snp_sel.si_pid = 0; return (n); } @@ -447,7 +446,6 @@ detach_notty: selwakeup(&snp->snp_sel); - snp->snp_sel.si_pid = 0; if ((snp->snp_flags & SNOOP_OPEN) == 0) free(snp, M_SNP); Index: dev/sound/pcm/channel.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/channel.c,v retrieving revision 1.81 diff -u -r1.81 channel.c --- dev/sound/pcm/channel.c 24 Feb 2002 00:49:43 -0000 1.81 +++ dev/sound/pcm/channel.c 10 Mar 2002 08:08:36 -0000 @@ -116,7 +116,7 @@ struct snd_dbuf *bs = c->bufsoft; CHN_LOCKASSERT(c); - if (sndbuf_getsel(bs)->si_pid && chn_polltrigger(c)) + if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c)) selwakeup(sndbuf_getsel(bs)); wakeup(bs); } Index: dev/usb/ums.c =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/ums.c,v retrieving revision 1.48 diff -u -r1.48 ums.c --- dev/usb/ums.c 15 Feb 2002 22:54:10 -0000 1.48 +++ dev/usb/ums.c 10 Mar 2002 08:08:36 -0000 @@ -345,7 +345,11 @@ sc->status.dx = sc->status.dy = sc->status.dz = 0; sc->rsel.si_flags = 0; +#ifdef __FreeBSD__ + SEL_INIT(&sc->rsel); +#else sc->rsel.si_pid = 0; +#endif sc->dev = make_dev(&ums_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR, Index: isa/psm.c =================================================================== RCS file: /home/ncvs/src/sys/isa/psm.c,v retrieving revision 1.43 diff -u -r1.43 psm.c --- isa/psm.c 19 Dec 2001 13:32:21 -0000 1.43 +++ isa/psm.c 10 Mar 2002 08:08:36 -0000 @@ -1314,8 +1314,7 @@ device_busy(devclass_get_device(psm_devclass, unit)); /* Initialize state */ - sc->rsel.si_flags = 0; - sc->rsel.si_pid = 0; + SEL_INIT(&sc->rsel); sc->mode.level = sc->dflt_mode.level; sc->mode.protocol = sc->dflt_mode.protocol; sc->watchdog = FALSE; Index: kern/kern_descrip.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_descrip.c,v retrieving revision 1.127 diff -u -r1.127 kern_descrip.c --- kern/kern_descrip.c 27 Feb 2002 18:32:12 -0000 1.127 +++ kern/kern_descrip.c 10 Mar 2002 08:09:25 -0000 @@ -1716,6 +1716,7 @@ FILE_UNLOCK(fp); return (0); } + mtx_lock(&Giant); if (fp->f_count < 0) panic("fdrop: count < 0"); if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) { @@ -1733,6 +1734,7 @@ else error = 0; ffree(fp); + mtx_unlock(&Giant); return (error); } Index: kern/kern_ktrace.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_ktrace.c,v retrieving revision 1.60 diff -u -r1.60 kern_ktrace.c --- kern/kern_ktrace.c 27 Feb 2002 19:10:50 -0000 1.60 +++ kern/kern_ktrace.c 10 Mar 2002 08:08:36 -0000 @@ -181,6 +181,8 @@ if (error) return; + + mtx_lock(&Giant); /* * don't let p_tracep get ripped out from under us */ @@ -200,6 +202,7 @@ vrele(vp); FREE(kth, M_KTRACE); p->p_traceflag &= ~KTRFAC_ACTIVE; + mtx_unlock(&Giant); } void Index: kern/sys_generic.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sys_generic.c,v retrieving revision 1.92 diff -u -r1.92 sys_generic.c --- kern/sys_generic.c 9 Mar 2002 22:44:37 -0000 1.92 +++ kern/sys_generic.c 10 Mar 2002 20:49:51 -0000 @@ -80,6 +80,7 @@ size_t, off_t, int); static int dofilewrite(struct thread *, struct file *, int, const void *, size_t, off_t, int); +static void clear_selinfo_list(struct thread *); /* * Read system call. @@ -102,13 +103,11 @@ struct file *fp; int error; - mtx_lock(&Giant); if ((error = fget_read(td, uap->fd, &fp)) == 0) { error = dofileread(td, fp, uap->fd, uap->buf, uap->nbyte, (off_t)-1, 0); fdrop(fp, td); } - mtx_unlock(&Giant); return(error); } @@ -137,7 +136,6 @@ if ((error = fget_read(td, uap->fd, &fp)) != 0) return (error); - mtx_lock(&Giant); if (fp->f_type != DTYPE_VNODE) { error = ESPIPE; } else { @@ -145,7 +143,6 @@ uap->offset, FOF_OFFSET); } fdrop(fp, td); - mtx_unlock(&Giant); return(error); } @@ -332,7 +329,6 @@ struct file *fp; int error; - mtx_lock(&Giant); if ((error = fget_write(td, uap->fd, &fp)) == 0) { error = dofilewrite(td, fp, uap->fd, uap->buf, uap->nbyte, (off_t)-1, 0); @@ -340,7 +336,6 @@ } else { error = EBADF; /* XXX this can't be right */ } - mtx_unlock(&Giant); return(error); } @@ -368,7 +363,6 @@ int error; if ((error = fget_write(td, uap->fd, &fp)) == 0) { - mtx_lock(&Giant); if (fp->f_type == DTYPE_VNODE) { error = dofilewrite(td, fp, uap->fd, uap->buf, uap->nbyte, uap->offset, FOF_OFFSET); @@ -376,7 +370,6 @@ error = ESPIPE; } fdrop(fp, td); - mtx_unlock(&Giant); } else { error = EBADF; /* this can't be right */ } @@ -423,8 +416,9 @@ } #endif cnt = nbyte; - if (fp->f_type == DTYPE_VNODE) + if (fp->f_type == DTYPE_VNODE) { bwillwrite(); + } if ((error = fo_write(fp, &auio, fp->f_cred, flags, td))) { if (auio.uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) @@ -696,11 +690,40 @@ return (error); } +/* + * These are initialized in selectinit() via SYSINIT + */ +static struct mtx sellock; static int nselcoll; /* Select collisions since boot */ struct cv selwait; SYSCTL_INT(_kern, OID_AUTO, nselcoll, CTLFLAG_RD, &nselcoll, 0, ""); /* + * Remove the references to the thread from all of the objects + * we were polling. + * + * This code assumes that the underlying owner of the selinfo + * structure will hold sellock before it changes it, and that + * it will unlink itself from our list if it goes away. + */ +static void +clear_selinfo_list(td) + struct thread *td; +{ + struct selinfo *si, *nsi; + + mtx_assert(&sellock, MA_OWNED); + + si = TAILQ_FIRST(&td->td_selinfo); + while (si != NULL) { + nsi = TAILQ_NEXT(si, si_thrlist); + si->si_thread = NULL; + si = nsi; + } + TAILQ_INIT(&td->td_selinfo); +} + +/* * Select system call. */ #ifndef _SYS_SYSPROTO_H_ @@ -801,34 +824,37 @@ atv.tv_usec = 0; } timo = 0; - PROC_LOCK(td->td_proc); + mtx_lock(&sellock); retry: + ncoll = nselcoll; mtx_lock_spin(&sched_lock); td->td_flags |= TDF_SELECT; mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(td->td_proc); + mtx_unlock(&sellock); + + /* XXX Is there a better place for this? */ + TAILQ_INIT(&td->td_selinfo); error = selscan(td, ibits, obits, uap->nd); - PROC_LOCK(td->td_proc); + mtx_lock(&sellock); if (error || td->td_retval[0]) goto done; if (atv.tv_sec || atv.tv_usec) { getmicrouptime(&rtv); if (timevalcmp(&rtv, &atv, >=)) { /* - * An event of our interest may occur during locking a process. - * In order to avoid missing the event that occured during locking - * the process, test TDF_SELECT and rescan file descriptors if - * necessary. + * An event of interest may occur while we do not hold + * sellock, so check TDF_SELECT and the number of collisions + * and rescan the file descriptors if necessary. */ mtx_lock_spin(&sched_lock); if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) { ncoll = nselcoll; td->td_flags |= TDF_SELECT; mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(td->td_proc); + mtx_unlock(&sellock); error = selscan(td, ibits, obits, uap->nd); - PROC_LOCK(td->td_proc); + mtx_lock(&sellock); } else mtx_unlock_spin(&sched_lock); goto done; @@ -838,23 +864,28 @@ timo = ttv.tv_sec > 24 * 60 * 60 ? 24 * 60 * 60 * hz : tvtohz(&ttv); } + + /* XXX What is the point of this? */ mtx_lock_spin(&sched_lock); td->td_flags &= ~TDF_SELECT; mtx_unlock_spin(&sched_lock); if (timo > 0) - error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo); + error = cv_timedwait_sig(&selwait, &sellock, timo); else - error = cv_wait_sig(&selwait, &td->td_proc->p_mtx); + error = cv_wait_sig(&selwait, &sellock); if (error == 0) goto retry; done: + clear_selinfo_list(td); + mtx_lock_spin(&sched_lock); td->td_flags &= ~TDF_SELECT; mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(td->td_proc); + mtx_unlock(&sellock); + done_noproclock: /* select is not restarted after signals... */ if (error == ERESTART) @@ -982,36 +1013,39 @@ atv.tv_usec = 0; } timo = 0; - PROC_LOCK(td->td_proc); + mtx_lock(&sellock); retry: ncoll = nselcoll; mtx_lock_spin(&sched_lock); td->td_flags |= TDF_SELECT; mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(td->td_proc); + mtx_unlock(&sellock); + + /* XXX Is there a better place for this? */ + TAILQ_INIT(&td->td_selinfo); error = pollscan(td, (struct pollfd *)bits, nfds); - PROC_LOCK(td->td_proc); + mtx_lock(&sellock); if (error || td->td_retval[0]) goto done; if (atv.tv_sec || atv.tv_usec) { getmicrouptime(&rtv); if (timevalcmp(&rtv, &atv, >=)) { /* - * An event of our interest may occur during locking a process. - * In order to avoid missing the event that occured during locking - * the process, test TDF_SELECT and rescan file descriptors if - * necessary. + * An event of interest may occur while we do not hold + * sellock, so check TDF_SELECT and the number of collisions + * and rescan the file descriptors if necessary. */ mtx_lock_spin(&sched_lock); if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) { ncoll = nselcoll; td->td_flags |= TDF_SELECT; mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(td->td_proc); + mtx_unlock(&sellock); error = pollscan(td, (struct pollfd *)bits, nfds); - PROC_LOCK(td->td_proc); + mtx_lock(&sellock); } else mtx_unlock_spin(&sched_lock); + goto done; } ttv = atv; @@ -1019,21 +1053,28 @@ timo = ttv.tv_sec > 24 * 60 * 60 ? 24 * 60 * 60 * hz : tvtohz(&ttv); } + + /* XXX What is the point of this? */ mtx_lock_spin(&sched_lock); td->td_flags &= ~TDF_SELECT; mtx_unlock_spin(&sched_lock); + if (timo > 0) - error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo); + error = cv_timedwait_sig(&selwait, &sellock, timo); else - error = cv_wait_sig(&selwait, &td->td_proc->p_mtx); + error = cv_wait_sig(&selwait, &sellock); + if (error == 0) goto retry; done: + clear_selinfo_list(td); + mtx_lock_spin(&sched_lock); td->td_flags &= ~TDF_SELECT; mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(td->td_proc); + mtx_unlock(&sellock); + done_noproclock: /* poll is not restarted after signals... */ if (error == ERESTART) @@ -1126,18 +1167,6 @@ return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); } -static int -find_thread_in_proc(struct proc *p, struct thread *td) -{ - struct thread *td2; - FOREACH_THREAD_IN_PROC(p, td2) { - if (td2 == td) { - return (1); - } - } - return (0); -} - /* * Record a select request. */ @@ -1146,29 +1175,21 @@ struct thread *selector; struct selinfo *sip; { - struct proc *p; - pid_t mypid; - mypid = selector->td_proc->p_pid; - if ((sip->si_pid == mypid) && - (sip->si_thread == selector)) { /* XXXKSE should be an ID? */ - return; - } - if (sip->si_pid && - (p = pfind(sip->si_pid)) && - (find_thread_in_proc(p, sip->si_thread))) { - mtx_lock_spin(&sched_lock); - if (sip->si_thread->td_wchan == (caddr_t)&selwait) { - mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(p); - sip->si_flags |= SI_COLL; - return; - } - mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(p); + mtx_lock(&sellock); + /* + * If the thread is not NULL there is another thread + * interested in this object, and we need to flag the + * collision so selwakeup() can broadcast. + */ + if (sip->si_thread != NULL) { + sip->si_flags |= SI_COLL; + } else { + sip->si_thread = selector; + TAILQ_INSERT_TAIL(&selector->td_selinfo, sip, si_thrlist); } - sip->si_pid = mypid; - sip->si_thread = selector; + + mtx_unlock(&sellock); } /* @@ -1176,37 +1197,37 @@ */ void selwakeup(sip) - register struct selinfo *sip; + struct selinfo *sip; { struct thread *td; - register struct proc *p; - if (sip->si_pid == 0) - return; - if (sip->si_flags & SI_COLL) { + mtx_lock(&sellock); + td = sip->si_thread; + + if ((sip->si_flags & SI_COLL) != 0) { nselcoll++; sip->si_flags &= ~SI_COLL; cv_broadcast(&selwait); } - p = pfind(sip->si_pid); - sip->si_pid = 0; - td = sip->si_thread; - if (p != NULL) { - if (!find_thread_in_proc(p, td)) { - PROC_UNLOCK(p); /* lock is in pfind() */; - return; - } - mtx_lock_spin(&sched_lock); - if (td->td_wchan == (caddr_t)&selwait) { - if (td->td_proc->p_stat == SSLEEP) - setrunnable(td); - else - cv_waitq_remove(td); - } else - td->td_flags &= ~TDF_SELECT; - mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(p); /* Lock is in pfind() */ + + if (td == NULL) { + mtx_unlock(&sellock); + return; } + + TAILQ_REMOVE(&td->td_selinfo, sip, si_thrlist); + mtx_lock_spin(&sched_lock); + if (td->td_wchan == (caddr_t)&selwait) { + if (td->td_proc->p_stat == SSLEEP) + setrunnable(td); + else + cv_waitq_remove(td); + } else + td->td_flags &= ~TDF_SELECT; + mtx_unlock_spin(&sched_lock); + + sip->si_thread = NULL; + mtx_unlock(&sellock); } static void selectinit __P((void *)); @@ -1218,4 +1239,5 @@ void *dummy; { cv_init(&selwait, "select"); + mtx_init(&sellock, "sellck", MTX_DEF); } Index: kern/sys_socket.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sys_socket.c,v retrieving revision 1.37 diff -u -r1.37 sys_socket.c --- kern/sys_socket.c 13 Jan 2002 11:57:59 -0000 1.37 +++ kern/sys_socket.c 10 Mar 2002 08:08:37 -0000 @@ -65,7 +65,12 @@ int flags; { struct socket *so = (struct socket *)fp->f_data; - return so->so_proto->pr_usrreqs->pru_soreceive(so, 0, uio, 0, 0, 0); + int error; + + mtx_lock(&Giant); + error = so->so_proto->pr_usrreqs->pru_soreceive(so, 0, uio, 0, 0, 0); + mtx_unlock(&Giant); + return (error); } /* ARGSUSED */ @@ -78,8 +83,13 @@ int flags; { struct socket *so = (struct socket *)fp->f_data; - return so->so_proto->pr_usrreqs->pru_sosend(so, 0, uio, 0, 0, 0, + int error; + + mtx_lock(&Giant); + error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, uio, 0, 0, 0, uio->uio_td); + mtx_unlock(&Giant); + return (error); } int Index: kern/tty.c =================================================================== RCS file: /home/ncvs/src/sys/kern/tty.c,v retrieving revision 1.165 diff -u -r1.165 tty.c --- kern/tty.c 2 Mar 2002 12:42:23 -0000 1.165 +++ kern/tty.c 10 Mar 2002 08:08:37 -0000 @@ -2273,7 +2273,7 @@ register struct tty *tp; { - if (tp->t_rsel.si_pid != 0) + if (SEL_WAITING(&tp->t_rsel)) selwakeup(&tp->t_rsel); if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL) pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL)); @@ -2289,7 +2289,7 @@ register struct tty *tp; { - if (tp->t_wsel.si_pid != 0 && tp->t_outq.c_cc <= tp->t_olowat) + if (SEL_WAITING(&tp->t_wsel) && tp->t_outq.c_cc <= tp->t_olowat) selwakeup(&tp->t_wsel); if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL) pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL)); Index: kern/vfs_bio.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v retrieving revision 1.302 diff -u -r1.302 vfs_bio.c --- kern/vfs_bio.c 5 Mar 2002 18:20:58 -0000 1.302 +++ kern/vfs_bio.c 10 Mar 2002 20:44:01 -0000 @@ -1079,6 +1079,7 @@ if (numdirtybuffers >= hidirtybuffers) { int s; + mtx_lock(&Giant); s = splbio(); while (numdirtybuffers >= hidirtybuffers) { bd_wakeup(1); @@ -1086,6 +1087,7 @@ tsleep(&needsbuffer, (PRIBIO + 4), "flswai", 0); } splx(s); + mtx_unlock(&Giant); } } Index: kern/vfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_vnops.c,v retrieving revision 1.136 diff -u -r1.136 vfs_vnops.c --- kern/vfs_vnops.c 5 Mar 2002 15:38:49 -0000 1.136 +++ kern/vfs_vnops.c 10 Mar 2002 08:08:37 -0000 @@ -409,6 +409,7 @@ struct vnode *vp; int error, ioflag; + mtx_lock(&Giant); KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td)); vp = (struct vnode *)fp->f_data; @@ -429,6 +430,7 @@ fp->f_offset = uio->uio_offset; fp->f_nextoff = uio->uio_offset; VOP_UNLOCK(vp, 0, td); + mtx_unlock(&Giant); return (error); } @@ -447,6 +449,7 @@ struct mount *mp; int error, ioflag; + mtx_lock(&Giant); KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td)); vp = (struct vnode *)fp->f_data; @@ -464,8 +467,10 @@ ioflag |= IO_SYNC; mp = NULL; if (vp->v_type != VCHR && - (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) + (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { + mtx_unlock(&Giant); return (error); + } VOP_LEASE(vp, td, cred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if ((flags & FOF_OFFSET) == 0) @@ -477,6 +482,7 @@ fp->f_nextoff = uio->uio_offset; VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); + mtx_unlock(&Giant); return (error); } Index: net/bpf.c =================================================================== RCS file: /home/ncvs/src/sys/net/bpf.c,v retrieving revision 1.86 diff -u -r1.86 bpf.c --- net/bpf.c 14 Dec 2001 22:17:54 -0000 1.86 +++ net/bpf.c 10 Mar 2002 08:08:37 -0000 @@ -514,8 +514,6 @@ pgsigio(d->bd_sigio, d->bd_sig, 0); selwakeup(&d->bd_sel); - /* XXX */ - d->bd_sel.si_pid = 0; } static void Index: sys/proc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.206 diff -u -r1.206 proc.h --- sys/proc.h 23 Feb 2002 11:12:57 -0000 1.206 +++ sys/proc.h 10 Mar 2002 08:08:37 -0000 @@ -147,6 +147,7 @@ * m - Giant * n - not locked, lazy * o - locked by pgrpsess_lock sx + * p - select lock (sellock) * * If the locking key specifies two identifiers (for example, p_pptr) then * either lock is sufficient for read access, but both locks must be held @@ -259,6 +260,8 @@ TAILQ_ENTRY(thread) td_slpq; /* (j) Sleep queue. XXXKSE */ TAILQ_ENTRY(thread) td_blkq; /* (j) Mutex queue. XXXKSE */ TAILQ_ENTRY(thread) td_runq; /* (j) Run queue(s). XXXKSE */ + + TAILQ_HEAD(, selinfo) td_selinfo; /* (p) List of selinfos */ #define td_startzero td_flags int td_flags; /* (j) TDF_* flags. */ Index: sys/selinfo.h =================================================================== RCS file: /home/ncvs/src/sys/sys/selinfo.h,v retrieving revision 1.12 diff -u -r1.12 selinfo.h --- sys/selinfo.h 27 Sep 2001 20:33:15 -0000 1.12 +++ sys/selinfo.h 10 Mar 2002 08:08:37 -0000 @@ -45,12 +45,21 @@ * notified when I/O becomes possible. */ struct selinfo { - pid_t si_pid; /* process to be notified */ + TAILQ_ENTRY(selinfo) si_thrlist; /* list hung off of thread */ struct thread *si_thread; /* thread in that process XXXKSE */ struct klist si_note; /* kernel note list */ short si_flags; /* see below */ }; #define SI_COLL 0x0001 /* collision occurred */ + +#define SEL_WAITING(si) \ + ((si)->si_thread != NULL || ((si)->si_flags & SI_COLL) != 0) + +#define SEL_INIT(si) \ + do { \ + (si)->si_thread = NULL; \ + (si)->si_flags = 0; \ + } while (0) #ifdef _KERNEL struct thread; To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-smp" in the body of the message