Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Oops, fell into rpipe/wpipe trap:



details:   https://anonhg.NetBSD.org/src/rev/965c28384924
branches:  trunk
changeset: 511555:965c28384924
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Thu Jun 21 18:46:22 2001 +0000

description:
Oops, fell into rpipe/wpipe trap:
The end we want to do selwakeup() on is not necessarily same as the one
we send SIGIO to. Make pipeselwakeup() accept two parameters and update
callers accordingly. This change fixes behaviour for code, which does
select(2)s on the write end waiting for reader (watched on gv, the problem
manifestated itself as a too long delay before the document was displayed).

Clearly separate the resource free code for FreeBSD
and NetBSD case in pipeclose(), so that it's a bit clearer what's going on.
Also LK_DRAIN the lock before the memory is returned to pipe_pool.

Add missing wakeup() in pipe_write() for PIPE_WANTCLOSE case.

diffstat:

 sys/kern/sys_pipe.c |  60 ++++++++++++++++++++++++++--------------------------
 1 files changed, 30 insertions(+), 30 deletions(-)

diffs (181 lines):

diff -r 817ce937b6a3 -r 965c28384924 sys/kern/sys_pipe.c
--- a/sys/kern/sys_pipe.c       Thu Jun 21 18:03:37 2001 +0000
+++ b/sys/kern/sys_pipe.c       Thu Jun 21 18:46:22 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_pipe.c,v 1.2 2001/06/16 12:00:02 jdolecek Exp $    */
+/*     $NetBSD: sys_pipe.c,v 1.3 2001/06/21 18:46:22 jdolecek Exp $    */
 
 /*
  * Copyright (c) 1996 John S. Dyson
@@ -188,7 +188,8 @@
 static int pipe_create __P((struct pipe **cpipep));
 static __inline int pipelock __P((struct pipe *cpipe, int catch));
 static __inline void pipeunlock __P((struct pipe *cpipe));
-static __inline void pipeselwakeup __P((struct pipe *cpipe));
+static __inline void pipeselwakeup __P((struct pipe *selp,
+                       struct pipe *sigp));
 static int pipespace __P((struct pipe *cpipe, int size));
 
 #ifdef __FreeBSD__
@@ -522,30 +523,27 @@
  * 'sigpipe' side of pipe.
  */
 static __inline void
-pipeselwakeup(cpipe)
-       struct pipe *cpipe;
+pipeselwakeup(selp, sigp)
+       struct pipe *selp, *sigp;
 {
-       if (!cpipe)
-               return;
-
-       if (cpipe->pipe_state & PIPE_SEL) {
-               cpipe->pipe_state &= ~PIPE_SEL;
-               selwakeup(&cpipe->pipe_sel);
+       if (selp->pipe_state & PIPE_SEL) {
+               selp->pipe_state &= ~PIPE_SEL;
+               selwakeup(&selp->pipe_sel);
        }
 #ifdef __FreeBSD__
-       if ((cpipe->pipe_state & PIPE_ASYNC) && cpipe->pipe_sigio)
-               pgsigio(cpipe->pipe_sigio, SIGIO, 0);
-       KNOTE(&cpipe->pipe_sel.si_note, 0);
+       if (sigp && (sigp->pipe_state & PIPE_ASYNC) && sigp->pipe_sigio)
+               pgsigio(sigp->pipe_sigio, SIGIO, 0);
+       KNOTE(&selp->pipe_sel.si_note, 0);
 #endif
 
 #ifdef __NetBSD__
-       if (cpipe && (cpipe->pipe_state & PIPE_ASYNC)
-           && cpipe->pipe_pgid != NO_PID){
+       if (sigp && (sigp->pipe_state & PIPE_ASYNC)
+           && sigp->pipe_pgid != NO_PID){
                struct proc *p;
 
-               if (cpipe->pipe_pgid < 0)
-                       gsignal(-cpipe->pipe_pgid, SIGIO);
-               else if (cpipe->pipe_pgid > 0 && (p = pfind(cpipe->pipe_pgid)) != 0)
+               if (sigp->pipe_pgid < 0)
+                       gsignal(-sigp->pipe_pgid, SIGIO);
+               else if (sigp->pipe_pgid > 0 && (p = pfind(sigp->pipe_pgid)) != 0)
                        psignal(p, SIGIO);
        }
 #endif /* NetBSD */
@@ -686,7 +684,7 @@
                        /*
                         * We want to read more, wake up select/poll.
                         */
-                       pipeselwakeup(rpipe->pipe_peer);
+                       pipeselwakeup(rpipe, rpipe->pipe_peer);
 
                        rpipe->pipe_state |= PIPE_WANTR;
                        error = tsleep(rpipe, PRIBIO | PCATCH, "piperd", 0);
@@ -724,7 +722,7 @@
         */
        if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF
            && (ocnt != rpipe->pipe_buffer.cnt || (rpipe->pipe_state & PIPE_SIGNALR))) {
-               pipeselwakeup(rpipe->pipe_peer);
+               pipeselwakeup(rpipe, rpipe->pipe_peer);
                rpipe->pipe_state &= ~PIPE_SIGNALR;
        }
 
@@ -920,7 +918,7 @@
                        pipelock(wpipe, 0);
                        pipe_destroy_write_buffer(wpipe);
                        pipeunlock(wpipe);
-                       pipeselwakeup(wpipe);
+                       pipeselwakeup(wpipe, wpipe);
                        error = EPIPE;
                        goto error1;
                }
@@ -928,7 +926,7 @@
                        wpipe->pipe_state &= ~PIPE_WANTR;
                        wakeup(wpipe);
                }
-               pipeselwakeup(wpipe);
+               pipeselwakeup(wpipe, wpipe);
                error = tsleep(wpipe, PRIBIO | PCATCH, "pipdwt", 0);
        }
 
@@ -1124,7 +1122,7 @@
                                wpipe->pipe_state &= ~PIPE_WANTR;
                                wakeup(wpipe);
                        }
-                       pipeselwakeup(wpipe);
+                       pipeselwakeup(wpipe, wpipe);
                        error = tsleep(wpipe, PRIBIO | PCATCH, "pipdwt", 0);
                }
 
@@ -1138,7 +1136,7 @@
        error:
                        /* XXX update uio ? */
                        if (error == EPIPE)
-                               pipeselwakeup(wpipe);
+                               pipeselwakeup(wpipe, wpipe);
 
                        wpipe->pipe_state &= ~PIPE_MOREW;
                        goto error1;
@@ -1218,6 +1216,7 @@
                            && (wpipe->pipe_state & PIPE_WANTCLOSE)) {
                                wpipe->pipe_state &=
                                    ~(PIPE_WANTCLOSE | PIPE_WANTR);
+                               wakeup(wpipe);
                        }
 
                        return (error);
@@ -1393,7 +1392,7 @@
                         * We have no more space and have something to offer,
                         * wake up select/poll.
                         */
-                       pipeselwakeup(wpipe);
+                       pipeselwakeup(wpipe, wpipe);
 
                        wpipe->pipe_state |= PIPE_WANTW;
                        error = tsleep(wpipe, PRIBIO | PCATCH, "pipewr", 0);
@@ -1441,7 +1440,7 @@
         * is only done synchronously), so check wpipe->only pipe_buffer.cnt
         */
        if (wpipe->pipe_buffer.cnt)
-               pipeselwakeup(wpipe);
+               pipeselwakeup(wpipe, wpipe);
 
        /*
         * Arrange for next read(2) to do a signal.
@@ -1667,7 +1666,7 @@
        if (!cpipe)
                return;
 
-       pipeselwakeup(cpipe->pipe_peer);
+       pipeselwakeup(cpipe, cpipe);
 
        /*
         * If the other side is blocked, wake it up saying that
@@ -1683,7 +1682,7 @@
         * Disconnect from peer
         */
        if ((ppipe = cpipe->pipe_peer) != NULL) {
-               pipeselwakeup(ppipe);
+               pipeselwakeup(ppipe, ppipe);
 
                ppipe->pipe_state |= PIPE_EOF;
                wakeup(ppipe);
@@ -1695,16 +1694,17 @@
         */
 #ifdef _FreeBSD__
        mtx_lock(&vm_mtx);
-#endif
        pipe_free_kmem(cpipe);
-#ifdef __FreeBSD__
        /* XXX: erm, doesn't zalloc already have its own locks and
         * not need the giant vm lock?
         */
        zfree(pipe_zone, cpipe);
        mtx_unlock(&vm_mtx);
 #endif /* FreeBSD */
+
 #ifdef __NetBSD__
+       pipe_free_kmem(cpipe);
+       (void) lockmgr(&cpipe->pipe_lock, LK_DRAIN, NULL);
        pool_put(&pipe_pool, cpipe);
 #endif
 }



Home | Main Index | Thread Index | Old Index