Diff for /src/sys/kern/sys_pipe.c between versions 1.16 and 1.17

version 1.16, 2004/03/30 19:14:11 version 1.17, 2004/04/01 17:58:02
Line 180  static __inline void pipeunlock (struct Line 180  static __inline void pipeunlock (struct
 static __inline void pipeselwakeup (struct pipe *cpipe);  static __inline void pipeselwakeup (struct pipe *cpipe);
 #ifndef PIPE_NODIRECT  #ifndef PIPE_NODIRECT
 static int pipe_build_write_buffer (struct pipe *wpipe, struct uio *uio);  static int pipe_build_write_buffer (struct pipe *wpipe, struct uio *uio);
 static void pipe_destroy_write_buffer (struct pipe *wpipe);  
 static int pipe_direct_write (struct pipe *wpipe, struct uio *uio);  static int pipe_direct_write (struct pipe *wpipe, struct uio *uio);
 static void pipe_clone_write_buffer (struct pipe *wpipe);  static void pipe_clone_write_buffer (struct pipe *wpipe);
 #endif  #endif
Line 435  pipe_read(struct file *fp, struct uio *u Line 434  pipe_read(struct file *fp, struct uio *u
                         nread += size;                          nread += size;
 #ifndef PIPE_NODIRECT  #ifndef PIPE_NODIRECT
                 /*                  /*
                 * Direct copy, bypassing a kernel buffer.                 * Direct copy, bypassing a kernel buffer.  We cannot mess
                  * with the direct-write buffer until PIPE_DIRECTIP is
                  * cleared.  In order to prevent the pipe_write code from
                  * racing itself in direct_write, we set DIRECTIP when we
                  * clear DIRECTW after we have exhausted the buffer.
                  */                   */
                } else if ((size = rpipe->pipe_map.cnt) &&                } else if (rpipe->pipe_map.xio_bytes &&
                           (rpipe->pipe_state & PIPE_DIRECTW)) {                           (rpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) == PIPE_DIRECTW) {
                        if (size > (u_int) uio->uio_resid)                        error = xio_uio_copy(&rpipe->pipe_map, uio, &size);
                                size = (u_int) uio->uio_resid; 
                        error = uiomove_fromphys(rpipe->pipe_map.ms, 
                                        rpipe->pipe_map.pos, size, uio); 
                         if (error)                          if (error)
                                 break;                                  break;
                         nread += size;                          nread += size;
                        rpipe->pipe_map.pos += size;                        if (rpipe->pipe_map.xio_bytes == 0) {
                        rpipe->pipe_map.cnt -= size;                                rpipe->pipe_state |= PIPE_DIRECTIP;
                        if (rpipe->pipe_map.cnt == 0) { 
                                 rpipe->pipe_state &= ~PIPE_DIRECTW;                                  rpipe->pipe_state &= ~PIPE_DIRECTW;
                                 wakeup(rpipe);                                  wakeup(rpipe);
                         }                          }
Line 538  pipe_build_write_buffer(wpipe, uio) Line 537  pipe_build_write_buffer(wpipe, uio)
         struct pipe *wpipe;          struct pipe *wpipe;
         struct uio *uio;          struct uio *uio;
 {  {
           int error;
         u_int size;          u_int size;
         int i;  
         vm_offset_t addr, endaddr;  
         vm_paddr_t paddr;  
   
         size = (u_int) uio->uio_iov->iov_len;          size = (u_int) uio->uio_iov->iov_len;
         if (size > wpipe->pipe_buffer.size)          if (size > wpipe->pipe_buffer.size)
                 size = wpipe->pipe_buffer.size;                  size = wpipe->pipe_buffer.size;
           if (size > XIO_INTERNAL_SIZE)
                   size = XIO_INTERNAL_SIZE;
   
        endaddr = round_page((vm_offset_t)uio->uio_iov->iov_base + size);        error = xio_init_ubuf(&wpipe->pipe_map, uio->uio_iov->iov_base, 
        addr = trunc_page((vm_offset_t)uio->uio_iov->iov_base);                                size, XIOF_READ);
        for (i = 0; addr < endaddr; addr += PAGE_SIZE, i++) {        if (error)
                vm_page_t m;                return(error);
 
                if (vm_fault_quick((caddr_t)addr, VM_PROT_READ) < 0 || 
                    (paddr = pmap_kextract(addr)) == 0) { 
                        int j; 
 
                        for (j = 0; j < i; j++) 
                                vm_page_unhold(wpipe->pipe_map.ms[j]); 
                        return (EFAULT); 
                } 
 
                m = PHYS_TO_VM_PAGE(paddr); 
                vm_page_hold(m); 
                wpipe->pipe_map.ms[i] = m; 
        } 
 
        /* 
         * set up the control block 
         */ 
        wpipe->pipe_map.npages = i; 
        wpipe->pipe_map.pos = 
            ((vm_offset_t) uio->uio_iov->iov_base) & PAGE_MASK; 
        wpipe->pipe_map.cnt = size; 
   
         /*          /*
          * and update the uio data           * and update the uio data
Line 587  pipe_build_write_buffer(wpipe, uio) Line 564  pipe_build_write_buffer(wpipe, uio)
 }  }
   
 /*  /*
  * unmap and unwire the process buffer  
  */  
 static void  
 pipe_destroy_write_buffer(wpipe)  
         struct pipe *wpipe;  
 {  
         int i;  
   
         for (i = 0; i < wpipe->pipe_map.npages; i++) {  
                 vm_page_unhold(wpipe->pipe_map.ms[i]);  
                 wpipe->pipe_map.ms[i] = NULL;   /* sanity */  
         }  
         wpipe->pipe_map.npages = 0;  
 }  
   
 /*  
  * In the case of a signal, the writing process might go away.  This   * In the case of a signal, the writing process might go away.  This
  * code copies the data into the circular buffer so that the source   * code copies the data into the circular buffer so that the source
  * pages can be freed without loss of data.   * pages can be freed without loss of data.
Line 611  static void Line 572  static void
 pipe_clone_write_buffer(wpipe)  pipe_clone_write_buffer(wpipe)
         struct pipe *wpipe;          struct pipe *wpipe;
 {  {
         struct uio uio;  
         struct iovec iov;  
         int size;          int size;
         int pos;  
   
        size = wpipe->pipe_map.cnt;        size = wpipe->pipe_map.xio_bytes;
        pos = wpipe->pipe_map.pos; 
   
         wpipe->pipe_buffer.in = size;          wpipe->pipe_buffer.in = size;
         wpipe->pipe_buffer.out = 0;          wpipe->pipe_buffer.out = 0;
         wpipe->pipe_buffer.cnt = size;          wpipe->pipe_buffer.cnt = size;
        wpipe->pipe_state &= ~PIPE_DIRECTW;        wpipe->pipe_state &= ~(PIPE_DIRECTW | PIPE_DIRECTIP);
   
        iov.iov_base = wpipe->pipe_buffer.buffer;        xio_copy_xtok(&wpipe->pipe_map, wpipe->pipe_buffer.buffer, size);
        iov.iov_len = size;        xio_release(&wpipe->pipe_map);
        uio.uio_iov = &iov; 
        uio.uio_iovcnt = 1; 
        uio.uio_offset = 0; 
        uio.uio_resid = size; 
        uio.uio_segflg = UIO_SYSSPACE; 
        uio.uio_rw = UIO_READ; 
        uio.uio_td = curthread; 
        uiomove_fromphys(wpipe->pipe_map.ms, pos, size, &uio); 
 
        pipe_destroy_write_buffer(wpipe); 
 }  }
   
 /*  /*
Line 653  pipe_direct_write(wpipe, uio) Line 600  pipe_direct_write(wpipe, uio)
         int error;          int error;
   
 retry:  retry:
        while (wpipe->pipe_state & PIPE_DIRECTW) {        while (wpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) {
                 if (wpipe->pipe_state & PIPE_WANTR) {                  if (wpipe->pipe_state & PIPE_WANTR) {
                         wpipe->pipe_state &= ~PIPE_WANTR;                          wpipe->pipe_state &= ~PIPE_WANTR;
                         wakeup(wpipe);                          wakeup(wpipe);
Line 661  retry: Line 608  retry:
                 wpipe->pipe_state |= PIPE_WANTW;                  wpipe->pipe_state |= PIPE_WANTW;
                 error = tsleep(wpipe, PCATCH, "pipdww", 0);                  error = tsleep(wpipe, PCATCH, "pipdww", 0);
                 if (error)                  if (error)
                        goto error1;                        goto error2;
                 if (wpipe->pipe_state & PIPE_EOF) {                  if (wpipe->pipe_state & PIPE_EOF) {
                         error = EPIPE;                          error = EPIPE;
                        goto error1;                        goto error2;
                 }                  }
         }          }
        wpipe->pipe_map.cnt = 0;        /* transfer not ready yet */        KKASSERT(wpipe->pipe_map.xio_bytes == 0);
         if (wpipe->pipe_buffer.cnt > 0) {          if (wpipe->pipe_buffer.cnt > 0) {
                 if (wpipe->pipe_state & PIPE_WANTR) {                  if (wpipe->pipe_state & PIPE_WANTR) {
                         wpipe->pipe_state &= ~PIPE_WANTR;                          wpipe->pipe_state &= ~PIPE_WANTR;
Line 677  retry: Line 624  retry:
                 wpipe->pipe_state |= PIPE_WANTW;                  wpipe->pipe_state |= PIPE_WANTW;
                 error = tsleep(wpipe, PCATCH, "pipdwc", 0);                  error = tsleep(wpipe, PCATCH, "pipdwc", 0);
                 if (error)                  if (error)
                        goto error1;                        goto error2;
                 if (wpipe->pipe_state & PIPE_EOF) {                  if (wpipe->pipe_state & PIPE_EOF) {
                         error = EPIPE;                          error = EPIPE;
                        goto error1;                        goto error2;
                 }                  }
                 goto retry;                  goto retry;
         }          }
Line 688  retry: Line 635  retry:
         /*          /*
          * Build our direct-write buffer           * Build our direct-write buffer
          */           */
        wpipe->pipe_state |= PIPE_DIRECTW;        wpipe->pipe_state |= PIPE_DIRECTW | PIPE_DIRECTIP;
         error = pipe_build_write_buffer(wpipe, uio);          error = pipe_build_write_buffer(wpipe, uio);
        if (error) {        if (error)
                wpipe->pipe_state &= ~PIPE_DIRECTW; 
                 goto error1;                  goto error1;
        }        wpipe->pipe_state &= ~PIPE_DIRECTIP;
   
         /*          /*
          * Wait until the receiver has snarfed the data.  Since we are likely           * Wait until the receiver has snarfed the data.  Since we are likely
Line 704  retry: Line 650  retry:
         while (!error && (wpipe->pipe_state & PIPE_DIRECTW)) {          while (!error && (wpipe->pipe_state & PIPE_DIRECTW)) {
                 if (wpipe->pipe_state & PIPE_EOF) {                  if (wpipe->pipe_state & PIPE_EOF) {
                         pipelock(wpipe, 0);                          pipelock(wpipe, 0);
                        pipe_destroy_write_buffer(wpipe);                        xio_release(&wpipe->pipe_map);
                         pipeunlock(wpipe);                          pipeunlock(wpipe);
                         pipeselwakeup(wpipe);                          pipeselwakeup(wpipe);
                         error = EPIPE;                          error = EPIPE;
Line 717  retry: Line 663  retry:
                 pipeselwakeup(wpipe);                  pipeselwakeup(wpipe);
                 error = tsleep(wpipe, PCATCH|PNORESCHED, "pipdwt", 0);                  error = tsleep(wpipe, PCATCH|PNORESCHED, "pipdwt", 0);
         }          }
   
         pipelock(wpipe,0);          pipelock(wpipe,0);
         if (wpipe->pipe_state & PIPE_DIRECTW) {          if (wpipe->pipe_state & PIPE_DIRECTW) {
                 /*                  /*
Line 725  retry: Line 670  retry:
                  * the process that might be going away.                   * the process that might be going away.
                  */                   */
                 pipe_clone_write_buffer(wpipe);                  pipe_clone_write_buffer(wpipe);
                   KKASSERT((wpipe->pipe_state & PIPE_DIRECTIP) == 0);
         } else {          } else {
                pipe_destroy_write_buffer(wpipe);                KKASSERT(wpipe->pipe_state & PIPE_DIRECTIP);
                 xio_release(&wpipe->pipe_map);
                 wpipe->pipe_state &= ~PIPE_DIRECTIP;
         }          }
         pipeunlock(wpipe);          pipeunlock(wpipe);
         return (error);          return (error);
   
           /*
            * Direct-write error, clear the direct write flags.
            */
 error1:  error1:
           wpipe->pipe_state &= ~(PIPE_DIRECTW | PIPE_DIRECTIP);
           /* fallthrough */
   
           /*
            * General error, wakeup the other side if it happens to be sleeping.
            */
   error2:
         wakeup(wpipe);          wakeup(wpipe);
         return (error);          return (error);
 }  }
Line 762  pipe_write(struct file *fp, struct uio * Line 720  pipe_write(struct file *fp, struct uio *
          */           */
         if ((uio->uio_resid > PIPE_SIZE) &&          if ((uio->uio_resid > PIPE_SIZE) &&
                 (pipe_nbig < pipe_maxbig) &&                  (pipe_nbig < pipe_maxbig) &&
                (wpipe->pipe_state & PIPE_DIRECTW) == 0 &&                (wpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) == 0 &&
                 (wpipe->pipe_buffer.size <= PIPE_SIZE) &&                  (wpipe->pipe_buffer.size <= PIPE_SIZE) &&
                 (wpipe->pipe_buffer.cnt == 0)) {                  (wpipe->pipe_buffer.cnt == 0)) {
   
Line 821  pipe_write(struct file *fp, struct uio * Line 779  pipe_write(struct file *fp, struct uio *
                  * reader goes away.                   * reader goes away.
                  */                   */
         retrywrite:          retrywrite:
                while (wpipe->pipe_state & PIPE_DIRECTW) {                while (wpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) {
                         if (wpipe->pipe_state & PIPE_WANTR) {                          if (wpipe->pipe_state & PIPE_WANTR) {
                                 wpipe->pipe_state &= ~PIPE_WANTR;                                  wpipe->pipe_state &= ~PIPE_WANTR;
                                 wakeup(wpipe);                                  wakeup(wpipe);
Line 857  pipe_write(struct file *fp, struct uio * Line 815  pipe_write(struct file *fp, struct uio *
                                  * It is possible for a direct write to                                   * It is possible for a direct write to
                                  * slip in on us... handle it here...                                   * slip in on us... handle it here...
                                  */                                   */
                                if (wpipe->pipe_state & PIPE_DIRECTW) {                                if (wpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) {
                                         pipeunlock(wpipe);                                          pipeunlock(wpipe);
                                         goto retrywrite;                                          goto retrywrite;
                                 }                                  }
Line 1031  pipe_ioctl(struct file *fp, u_long cmd, Line 989  pipe_ioctl(struct file *fp, u_long cmd,
                 return (0);                  return (0);
   
         case FIONREAD:          case FIONREAD:
                if (mpipe->pipe_state & PIPE_DIRECTW)                if (mpipe->pipe_state & PIPE_DIRECTW) {
                        *(int *)data = mpipe->pipe_map.cnt;                        *(int *)data = mpipe->pipe_map.xio_bytes;
                else                } else {
                         *(int *)data = mpipe->pipe_buffer.cnt;                          *(int *)data = mpipe->pipe_buffer.cnt;
                   }
                 return (0);                  return (0);
   
         case FIOSETOWN:          case FIOSETOWN:
Line 1144  pipe_free_kmem(struct pipe *cpipe) Line 1103  pipe_free_kmem(struct pipe *cpipe)
                 cpipe->pipe_buffer.object = NULL;                  cpipe->pipe_buffer.object = NULL;
         }          }
 #ifndef PIPE_NODIRECT  #ifndef PIPE_NODIRECT
        cpipe->pipe_map.cnt = 0;        KKASSERT(cpipe->pipe_map.xio_bytes == 0 &&
        cpipe->pipe_map.pos = 0;                cpipe->pipe_map.xio_offset == 0 &&
        cpipe->pipe_map.npages = 0;                cpipe->pipe_map.xio_npages == 0);
 #endif  #endif
 }  }
   
Line 1196  pipeclose(struct pipe *cpipe) Line 1155  pipeclose(struct pipe *cpipe)
                 pipe_free_kmem(cpipe);                  pipe_free_kmem(cpipe);
                 free(cpipe, M_PIPE);                  free(cpipe, M_PIPE);
         } else {          } else {
                KKASSERT(cpipe->pipe_map.npages == 0);                KKASSERT(cpipe->pipe_map.xio_npages == 0 &&
                        cpipe->pipe_map.xio_bytes == 0 &&
                         cpipe->pipe_map.xio_offset == 0);
                 cpipe->pipe_state = 0;                  cpipe->pipe_state = 0;
                 cpipe->pipe_busy = 0;                  cpipe->pipe_busy = 0;
                 cpipe->pipe_map.cnt = 0;  
                 cpipe->pipe_map.pos = 0;  
                 cpipe->pipe_peer = gd->gd_pipeq;                  cpipe->pipe_peer = gd->gd_pipeq;
                 gd->gd_pipeq = cpipe;                  gd->gd_pipeq = cpipe;
                 ++gd->gd_pipeqcount;                  ++gd->gd_pipeqcount;
Line 1251  filt_piperead(struct knote *kn, long hin Line 1209  filt_piperead(struct knote *kn, long hin
   
         kn->kn_data = rpipe->pipe_buffer.cnt;          kn->kn_data = rpipe->pipe_buffer.cnt;
         if ((kn->kn_data == 0) && (rpipe->pipe_state & PIPE_DIRECTW))          if ((kn->kn_data == 0) && (rpipe->pipe_state & PIPE_DIRECTW))
                kn->kn_data = rpipe->pipe_map.cnt;                kn->kn_data = rpipe->pipe_map.xio_bytes;
   
         if ((rpipe->pipe_state & PIPE_EOF) ||          if ((rpipe->pipe_state & PIPE_EOF) ||
             (wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {              (wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {

Removed from v.1.16  
changed lines
  Added in v.1.17