sys_pipe.c revision 40700
113675Sdyson/* 213675Sdyson * Copyright (c) 1996 John S. Dyson 313675Sdyson * All rights reserved. 413675Sdyson * 513675Sdyson * Redistribution and use in source and binary forms, with or without 613675Sdyson * modification, are permitted provided that the following conditions 713675Sdyson * are met: 813675Sdyson * 1. Redistributions of source code must retain the above copyright 913675Sdyson * notice immediately at the beginning of the file, without modification, 1013675Sdyson * this list of conditions, and the following disclaimer. 1113675Sdyson * 2. Redistributions in binary form must reproduce the above copyright 1213675Sdyson * notice, this list of conditions and the following disclaimer in the 1313675Sdyson * documentation and/or other materials provided with the distribution. 1413675Sdyson * 3. Absolutely no warranty of function or purpose is made by the author 1513675Sdyson * John S. Dyson. 1614037Sdyson * 4. Modifications may be freely made to this file if the above conditions 1713675Sdyson * are met. 1813675Sdyson * 1940700Sdg * $Id: sys_pipe.c,v 1.43 1998/10/13 08:24:40 dg Exp $ 2013675Sdyson */ 2113675Sdyson 2213675Sdyson/* 2313675Sdyson * This file contains a high-performance replacement for the socket-based 2413675Sdyson * pipes scheme originally used in FreeBSD/4.4Lite. It does not support 2513675Sdyson * all features of sockets, but does do everything that pipes normally 2613675Sdyson * do. 2713675Sdyson */ 2813675Sdyson 2913907Sdyson/* 3013907Sdyson * This code has two modes of operation, a small write mode and a large 3113907Sdyson * write mode. The small write mode acts like conventional pipes with 3213907Sdyson * a kernel buffer. If the buffer is less than PIPE_MINDIRECT, then the 3313907Sdyson * "normal" pipe buffering is done. If the buffer is between PIPE_MINDIRECT 3413907Sdyson * and PIPE_SIZE in size, it is fully mapped and wired into the kernel, and 3513907Sdyson * the receiving process can copy it directly from the pages in the sending 3613907Sdyson * process. 3713907Sdyson * 3813907Sdyson * If the sending process receives a signal, it is possible that it will 3913913Sdyson * go away, and certainly its address space can change, because control 4013907Sdyson * is returned back to the user-mode side. In that case, the pipe code 4113907Sdyson * arranges to copy the buffer supplied by the user process, to a pageable 4213907Sdyson * kernel buffer, and the receiving process will grab the data from the 4313907Sdyson * pageable kernel buffer. Since signals don't happen all that often, 4413907Sdyson * the copy operation is normally eliminated. 4513907Sdyson * 4613907Sdyson * The constant PIPE_MINDIRECT is chosen to make sure that buffering will 4713907Sdyson * happen for small transfers so that the system will not spend all of 4813913Sdyson * its time context switching. PIPE_SIZE is constrained by the 4913907Sdyson * amount of kernel virtual memory. 5013907Sdyson */ 5113907Sdyson 5213675Sdyson#include <sys/param.h> 5313675Sdyson#include <sys/systm.h> 5413675Sdyson#include <sys/proc.h> 5524131Sbde#include <sys/fcntl.h> 5613675Sdyson#include <sys/file.h> 5713675Sdyson#include <sys/filedesc.h> 5824206Sbde#include <sys/filio.h> 5924206Sbde#include <sys/ttycom.h> 6013675Sdyson#include <sys/stat.h> 6129356Speter#include <sys/poll.h> 6213675Sdyson#include <sys/signalvar.h> 6313675Sdyson#include <sys/sysproto.h> 6413675Sdyson#include <sys/pipe.h> 6534924Sbde#include <sys/uio.h> 6613675Sdyson 6713675Sdyson#include <vm/vm.h> 6813675Sdyson#include <vm/vm_prot.h> 6913675Sdyson#include <vm/vm_param.h> 7022521Sdyson#include <sys/lock.h> 7113675Sdyson#include <vm/vm_object.h> 7213675Sdyson#include <vm/vm_kern.h> 7313675Sdyson#include <vm/vm_extern.h> 7413675Sdyson#include <vm/pmap.h> 7513675Sdyson#include <vm/vm_map.h> 7613907Sdyson#include <vm/vm_page.h> 7727899Sdyson#include <vm/vm_zone.h> 7813675Sdyson 7914037Sdyson/* 8014037Sdyson * Use this define if you want to disable *fancy* VM things. Expect an 8114037Sdyson * approx 30% decrease in transfer rate. This could be useful for 8214037Sdyson * NetBSD or OpenBSD. 8314037Sdyson */ 8414037Sdyson/* #define PIPE_NODIRECT */ 8514037Sdyson 8614037Sdyson/* 8714037Sdyson * interfaces to the outside world 8814037Sdyson */ 8913675Sdysonstatic int pipe_read __P((struct file *fp, struct uio *uio, 9013675Sdyson struct ucred *cred)); 9113675Sdysonstatic int pipe_write __P((struct file *fp, struct uio *uio, 9213675Sdyson struct ucred *cred)); 9313675Sdysonstatic int pipe_close __P((struct file *fp, struct proc *p)); 9429356Speterstatic int pipe_poll __P((struct file *fp, int events, struct ucred *cred, 9529356Speter struct proc *p)); 9636735Sdfrstatic int pipe_ioctl __P((struct file *fp, u_long cmd, caddr_t data, struct proc *p)); 9713675Sdyson 9813675Sdysonstatic struct fileops pipeops = 9929356Speter { pipe_read, pipe_write, pipe_ioctl, pipe_poll, pipe_close }; 10013675Sdyson 10113675Sdyson/* 10213675Sdyson * Default pipe buffer size(s), this can be kind-of large now because pipe 10313675Sdyson * space is pageable. The pipe code will try to maintain locality of 10413675Sdyson * reference for performance reasons, so small amounts of outstanding I/O 10513675Sdyson * will not wipe the cache. 10613675Sdyson */ 10713907Sdyson#define MINPIPESIZE (PIPE_SIZE/3) 10813907Sdyson#define MAXPIPESIZE (2*PIPE_SIZE/3) 10913675Sdyson 11013907Sdyson/* 11113907Sdyson * Maximum amount of kva for pipes -- this is kind-of a soft limit, but 11213907Sdyson * is there so that on large systems, we don't exhaust it. 11313907Sdyson */ 11413907Sdyson#define MAXPIPEKVA (8*1024*1024) 11513907Sdyson 11613907Sdyson/* 11713907Sdyson * Limit for direct transfers, we cannot, of course limit 11813907Sdyson * the amount of kva for pipes in general though. 11913907Sdyson */ 12013907Sdyson#define LIMITPIPEKVA (16*1024*1024) 12117163Sdyson 12217163Sdyson/* 12317163Sdyson * Limit the number of "big" pipes 12417163Sdyson */ 12517163Sdyson#define LIMITBIGPIPES 32 12633181Seivindstatic int nbigpipe; 12717163Sdyson 12817124Sbdestatic int amountpipekva; 12913907Sdyson 13013675Sdysonstatic void pipeclose __P((struct pipe *cpipe)); 13113675Sdysonstatic void pipeinit __P((struct pipe *cpipe)); 13213907Sdysonstatic __inline int pipelock __P((struct pipe *cpipe, int catch)); 13313675Sdysonstatic __inline void pipeunlock __P((struct pipe *cpipe)); 13414122Speterstatic __inline void pipeselwakeup __P((struct pipe *cpipe)); 13514037Sdyson#ifndef PIPE_NODIRECT 13613907Sdysonstatic int pipe_build_write_buffer __P((struct pipe *wpipe, struct uio *uio)); 13713907Sdysonstatic void pipe_destroy_write_buffer __P((struct pipe *wpipe)); 13813907Sdysonstatic int pipe_direct_write __P((struct pipe *wpipe, struct uio *uio)); 13913907Sdysonstatic void pipe_clone_write_buffer __P((struct pipe *wpipe)); 14014037Sdyson#endif 14113907Sdysonstatic void pipespace __P((struct pipe *cpipe)); 14213675Sdyson 14333181Seivindstatic vm_zone_t pipe_zone; 14427899Sdyson 14513675Sdyson/* 14613675Sdyson * The pipe system call for the DTYPE_PIPE type of pipes 14713675Sdyson */ 14813675Sdyson 14913675Sdyson/* ARGSUSED */ 15013675Sdysonint 15130994Sphkpipe(p, uap) 15213675Sdyson struct proc *p; 15313675Sdyson struct pipe_args /* { 15413675Sdyson int dummy; 15513675Sdyson } */ *uap; 15613675Sdyson{ 15713675Sdyson register struct filedesc *fdp = p->p_fd; 15813675Sdyson struct file *rf, *wf; 15913675Sdyson struct pipe *rpipe, *wpipe; 16013675Sdyson int fd, error; 16113675Sdyson 16227899Sdyson if (pipe_zone == NULL) 16327923Sdyson pipe_zone = zinit("PIPE", sizeof (struct pipe), 0, 0, 4); 16427899Sdyson 16527899Sdyson rpipe = zalloc( pipe_zone); 16613675Sdyson pipeinit(rpipe); 16713907Sdyson rpipe->pipe_state |= PIPE_DIRECTOK; 16827899Sdyson wpipe = zalloc( pipe_zone); 16913675Sdyson pipeinit(wpipe); 17013907Sdyson wpipe->pipe_state |= PIPE_DIRECTOK; 17113675Sdyson 17213675Sdyson error = falloc(p, &rf, &fd); 17313675Sdyson if (error) 17413675Sdyson goto free2; 17530994Sphk p->p_retval[0] = fd; 17613675Sdyson rf->f_flag = FREAD | FWRITE; 17713675Sdyson rf->f_type = DTYPE_PIPE; 17813675Sdyson rf->f_ops = &pipeops; 17913675Sdyson rf->f_data = (caddr_t)rpipe; 18013675Sdyson error = falloc(p, &wf, &fd); 18113675Sdyson if (error) 18213675Sdyson goto free3; 18313675Sdyson wf->f_flag = FREAD | FWRITE; 18413675Sdyson wf->f_type = DTYPE_PIPE; 18513675Sdyson wf->f_ops = &pipeops; 18613675Sdyson wf->f_data = (caddr_t)wpipe; 18730994Sphk p->p_retval[1] = fd; 18813675Sdyson 18913675Sdyson rpipe->pipe_peer = wpipe; 19013675Sdyson wpipe->pipe_peer = rpipe; 19113675Sdyson 19213675Sdyson return (0); 19313675Sdysonfree3: 19413675Sdyson ffree(rf); 19530994Sphk fdp->fd_ofiles[p->p_retval[0]] = 0; 19613675Sdysonfree2: 19713675Sdyson (void)pipeclose(wpipe); 19813675Sdyson (void)pipeclose(rpipe); 19913675Sdyson return (error); 20013675Sdyson} 20113675Sdyson 20213909Sdyson/* 20313909Sdyson * Allocate kva for pipe circular buffer, the space is pageable 20413909Sdyson */ 20513675Sdysonstatic void 20613907Sdysonpipespace(cpipe) 20713675Sdyson struct pipe *cpipe; 20813675Sdyson{ 20913688Sdyson int npages, error; 21013675Sdyson 21113907Sdyson npages = round_page(cpipe->pipe_buffer.size)/PAGE_SIZE; 21213675Sdyson /* 21313675Sdyson * Create an object, I don't like the idea of paging to/from 21413675Sdyson * kernel_object. 21514037Sdyson * XXX -- minor change needed here for NetBSD/OpenBSD VM systems. 21613675Sdyson */ 21713675Sdyson cpipe->pipe_buffer.object = vm_object_allocate(OBJT_DEFAULT, npages); 21813688Sdyson cpipe->pipe_buffer.buffer = (caddr_t) vm_map_min(kernel_map); 21913675Sdyson 22013675Sdyson /* 22113675Sdyson * Insert the object into the kernel map, and allocate kva for it. 22213675Sdyson * The map entry is, by default, pageable. 22314037Sdyson * XXX -- minor change needed here for NetBSD/OpenBSD VM systems. 22413675Sdyson */ 22513688Sdyson error = vm_map_find(kernel_map, cpipe->pipe_buffer.object, 0, 22613907Sdyson (vm_offset_t *) &cpipe->pipe_buffer.buffer, 22713907Sdyson cpipe->pipe_buffer.size, 1, 22813688Sdyson VM_PROT_ALL, VM_PROT_ALL, 0); 22913675Sdyson 23013688Sdyson if (error != KERN_SUCCESS) 23113688Sdyson panic("pipeinit: cannot allocate pipe -- out of kvm -- code = %d", error); 23213907Sdyson amountpipekva += cpipe->pipe_buffer.size; 23313907Sdyson} 23413688Sdyson 23513907Sdyson/* 23613907Sdyson * initialize and allocate VM and memory for pipe 23713907Sdyson */ 23813907Sdysonstatic void 23913907Sdysonpipeinit(cpipe) 24013907Sdyson struct pipe *cpipe; 24113907Sdyson{ 24213907Sdyson 24313675Sdyson cpipe->pipe_buffer.in = 0; 24413675Sdyson cpipe->pipe_buffer.out = 0; 24513675Sdyson cpipe->pipe_buffer.cnt = 0; 24613907Sdyson cpipe->pipe_buffer.size = PIPE_SIZE; 24717163Sdyson 24813907Sdyson /* Buffer kva gets dynamically allocated */ 24913907Sdyson cpipe->pipe_buffer.buffer = NULL; 25017124Sbde /* cpipe->pipe_buffer.object = invalid */ 25113675Sdyson 25213675Sdyson cpipe->pipe_state = 0; 25313675Sdyson cpipe->pipe_peer = NULL; 25413675Sdyson cpipe->pipe_busy = 0; 25534901Sphk getnanotime(&cpipe->pipe_ctime); 25624101Sbde cpipe->pipe_atime = cpipe->pipe_ctime; 25724101Sbde cpipe->pipe_mtime = cpipe->pipe_ctime; 25813675Sdyson bzero(&cpipe->pipe_sel, sizeof cpipe->pipe_sel); 25917124Sbde cpipe->pipe_pgid = NO_PID; 26013907Sdyson 26114037Sdyson#ifndef PIPE_NODIRECT 26213907Sdyson /* 26313907Sdyson * pipe data structure initializations to support direct pipe I/O 26413907Sdyson */ 26513907Sdyson cpipe->pipe_map.cnt = 0; 26613907Sdyson cpipe->pipe_map.kva = 0; 26713907Sdyson cpipe->pipe_map.pos = 0; 26813907Sdyson cpipe->pipe_map.npages = 0; 26917124Sbde /* cpipe->pipe_map.ms[] = invalid */ 27014037Sdyson#endif 27113675Sdyson} 27213675Sdyson 27313675Sdyson 27413675Sdyson/* 27513675Sdyson * lock a pipe for I/O, blocking other access 27613675Sdyson */ 27713675Sdysonstatic __inline int 27813907Sdysonpipelock(cpipe, catch) 27913675Sdyson struct pipe *cpipe; 28013907Sdyson int catch; 28113675Sdyson{ 28213776Sdyson int error; 28313675Sdyson while (cpipe->pipe_state & PIPE_LOCK) { 28413675Sdyson cpipe->pipe_state |= PIPE_LWANT; 28514177Sdyson if (error = tsleep( cpipe, 28613907Sdyson catch?(PRIBIO|PCATCH):PRIBIO, "pipelk", 0)) { 28713776Sdyson return error; 28813675Sdyson } 28913675Sdyson } 29013675Sdyson cpipe->pipe_state |= PIPE_LOCK; 29113675Sdyson return 0; 29213675Sdyson} 29313675Sdyson 29413675Sdyson/* 29513675Sdyson * unlock a pipe I/O lock 29613675Sdyson */ 29713675Sdysonstatic __inline void 29813675Sdysonpipeunlock(cpipe) 29913675Sdyson struct pipe *cpipe; 30013675Sdyson{ 30113675Sdyson cpipe->pipe_state &= ~PIPE_LOCK; 30213675Sdyson if (cpipe->pipe_state & PIPE_LWANT) { 30313675Sdyson cpipe->pipe_state &= ~PIPE_LWANT; 30414177Sdyson wakeup(cpipe); 30513675Sdyson } 30613675Sdyson} 30713675Sdyson 30814037Sdysonstatic __inline void 30914037Sdysonpipeselwakeup(cpipe) 31014037Sdyson struct pipe *cpipe; 31114037Sdyson{ 31218863Sdyson struct proc *p; 31318863Sdyson 31414037Sdyson if (cpipe->pipe_state & PIPE_SEL) { 31514037Sdyson cpipe->pipe_state &= ~PIPE_SEL; 31614037Sdyson selwakeup(&cpipe->pipe_sel); 31714037Sdyson } 31818863Sdyson if (cpipe->pipe_state & PIPE_ASYNC) { 31918863Sdyson if (cpipe->pipe_pgid < 0) 32018863Sdyson gsignal(-cpipe->pipe_pgid, SIGIO); 32118863Sdyson else if ((p = pfind(cpipe->pipe_pgid)) != NULL) 32218863Sdyson psignal(p, SIGIO); 32318863Sdyson } 32414037Sdyson} 32514037Sdyson 32613675Sdyson/* ARGSUSED */ 32713675Sdysonstatic int 32813675Sdysonpipe_read(fp, uio, cred) 32913675Sdyson struct file *fp; 33013675Sdyson struct uio *uio; 33113675Sdyson struct ucred *cred; 33213675Sdyson{ 33313675Sdyson 33413675Sdyson struct pipe *rpipe = (struct pipe *) fp->f_data; 33513675Sdyson int error = 0; 33613675Sdyson int nread = 0; 33718863Sdyson u_int size; 33813675Sdyson 33913675Sdyson ++rpipe->pipe_busy; 34013675Sdyson while (uio->uio_resid) { 34113907Sdyson /* 34213907Sdyson * normal pipe buffer receive 34313907Sdyson */ 34413675Sdyson if (rpipe->pipe_buffer.cnt > 0) { 34518863Sdyson size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out; 34613675Sdyson if (size > rpipe->pipe_buffer.cnt) 34713675Sdyson size = rpipe->pipe_buffer.cnt; 34818863Sdyson if (size > (u_int) uio->uio_resid) 34918863Sdyson size = (u_int) uio->uio_resid; 35013907Sdyson if ((error = pipelock(rpipe,1)) == 0) { 35113675Sdyson error = uiomove( &rpipe->pipe_buffer.buffer[rpipe->pipe_buffer.out], 35213675Sdyson size, uio); 35313675Sdyson pipeunlock(rpipe); 35413675Sdyson } 35513675Sdyson if (error) { 35613675Sdyson break; 35713675Sdyson } 35813675Sdyson rpipe->pipe_buffer.out += size; 35913675Sdyson if (rpipe->pipe_buffer.out >= rpipe->pipe_buffer.size) 36013675Sdyson rpipe->pipe_buffer.out = 0; 36113675Sdyson 36213675Sdyson rpipe->pipe_buffer.cnt -= size; 36313675Sdyson nread += size; 36414037Sdyson#ifndef PIPE_NODIRECT 36513907Sdyson /* 36613907Sdyson * Direct copy, bypassing a kernel buffer. 36713907Sdyson */ 36813907Sdyson } else if ((size = rpipe->pipe_map.cnt) && 36913907Sdyson (rpipe->pipe_state & PIPE_DIRECTW)) { 37013907Sdyson caddr_t va; 37118863Sdyson if (size > (u_int) uio->uio_resid) 37218863Sdyson size = (u_int) uio->uio_resid; 37313907Sdyson if ((error = pipelock(rpipe,1)) == 0) { 37413907Sdyson va = (caddr_t) rpipe->pipe_map.kva + rpipe->pipe_map.pos; 37513907Sdyson error = uiomove(va, size, uio); 37613907Sdyson pipeunlock(rpipe); 37713907Sdyson } 37813907Sdyson if (error) 37913907Sdyson break; 38013907Sdyson nread += size; 38113907Sdyson rpipe->pipe_map.pos += size; 38213907Sdyson rpipe->pipe_map.cnt -= size; 38313907Sdyson if (rpipe->pipe_map.cnt == 0) { 38413907Sdyson rpipe->pipe_state &= ~PIPE_DIRECTW; 38513907Sdyson wakeup(rpipe); 38613907Sdyson } 38714037Sdyson#endif 38813675Sdyson } else { 38913675Sdyson /* 39013675Sdyson * detect EOF condition 39113675Sdyson */ 39213675Sdyson if (rpipe->pipe_state & PIPE_EOF) { 39314802Sdyson /* XXX error = ? */ 39413675Sdyson break; 39513675Sdyson } 39613675Sdyson /* 39713675Sdyson * If the "write-side" has been blocked, wake it up now. 39813675Sdyson */ 39913675Sdyson if (rpipe->pipe_state & PIPE_WANTW) { 40013675Sdyson rpipe->pipe_state &= ~PIPE_WANTW; 40113675Sdyson wakeup(rpipe); 40213675Sdyson } 40313774Sdyson if (nread > 0) 40413675Sdyson break; 40516960Sdyson 40616960Sdyson if (fp->f_flag & FNONBLOCK) { 40713774Sdyson error = EAGAIN; 40813774Sdyson break; 40913774Sdyson } 41013675Sdyson 41113675Sdyson /* 41213675Sdyson * If there is no more to read in the pipe, reset 41313913Sdyson * its pointers to the beginning. This improves 41413675Sdyson * cache hit stats. 41513675Sdyson */ 41613675Sdyson 41713907Sdyson if ((error = pipelock(rpipe,1)) == 0) { 41813675Sdyson if (rpipe->pipe_buffer.cnt == 0) { 41913675Sdyson rpipe->pipe_buffer.in = 0; 42013675Sdyson rpipe->pipe_buffer.out = 0; 42113675Sdyson } 42213675Sdyson pipeunlock(rpipe); 42313675Sdyson } else { 42413675Sdyson break; 42513675Sdyson } 42614177Sdyson 42714177Sdyson if (rpipe->pipe_state & PIPE_WANTW) { 42814177Sdyson rpipe->pipe_state &= ~PIPE_WANTW; 42914177Sdyson wakeup(rpipe); 43014177Sdyson } 43114177Sdyson 43213675Sdyson rpipe->pipe_state |= PIPE_WANTR; 43313776Sdyson if (error = tsleep(rpipe, PRIBIO|PCATCH, "piperd", 0)) { 43413675Sdyson break; 43513675Sdyson } 43613675Sdyson } 43713675Sdyson } 43813675Sdyson 43924101Sbde if (error == 0) 44034901Sphk getnanotime(&rpipe->pipe_atime); 44113913Sdyson 44213675Sdyson --rpipe->pipe_busy; 44313675Sdyson if ((rpipe->pipe_busy == 0) && (rpipe->pipe_state & PIPE_WANT)) { 44413675Sdyson rpipe->pipe_state &= ~(PIPE_WANT|PIPE_WANTW); 44513675Sdyson wakeup(rpipe); 44613675Sdyson } else if (rpipe->pipe_buffer.cnt < MINPIPESIZE) { 44713675Sdyson /* 44813675Sdyson * If there is no more to read in the pipe, reset 44913913Sdyson * its pointers to the beginning. This improves 45013675Sdyson * cache hit stats. 45113675Sdyson */ 45217163Sdyson if (rpipe->pipe_buffer.cnt == 0) { 45317163Sdyson if ((error == 0) && (error = pipelock(rpipe,1)) == 0) { 45413675Sdyson rpipe->pipe_buffer.in = 0; 45513675Sdyson rpipe->pipe_buffer.out = 0; 45617163Sdyson pipeunlock(rpipe); 45713675Sdyson } 45813675Sdyson } 45913675Sdyson 46013675Sdyson /* 46113675Sdyson * If the "write-side" has been blocked, wake it up now. 46213675Sdyson */ 46313675Sdyson if (rpipe->pipe_state & PIPE_WANTW) { 46413675Sdyson rpipe->pipe_state &= ~PIPE_WANTW; 46513675Sdyson wakeup(rpipe); 46613675Sdyson } 46713675Sdyson } 46814037Sdyson 46914802Sdyson if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF) 47014037Sdyson pipeselwakeup(rpipe); 47114037Sdyson 47213675Sdyson return error; 47313675Sdyson} 47413675Sdyson 47514037Sdyson#ifndef PIPE_NODIRECT 47613907Sdyson/* 47713907Sdyson * Map the sending processes' buffer into kernel space and wire it. 47813907Sdyson * This is similar to a physical write operation. 47913907Sdyson */ 48013675Sdysonstatic int 48113907Sdysonpipe_build_write_buffer(wpipe, uio) 48213907Sdyson struct pipe *wpipe; 48313675Sdyson struct uio *uio; 48413675Sdyson{ 48518863Sdyson u_int size; 48613907Sdyson int i; 48713907Sdyson vm_offset_t addr, endaddr, paddr; 48813907Sdyson 48918863Sdyson size = (u_int) uio->uio_iov->iov_len; 49013907Sdyson if (size > wpipe->pipe_buffer.size) 49113907Sdyson size = wpipe->pipe_buffer.size; 49213907Sdyson 49340286Sdg endaddr = round_page((vm_offset_t)uio->uio_iov->iov_base + size); 49440286Sdg for(i = 0, addr = trunc_page((vm_offset_t)uio->uio_iov->iov_base); 49513907Sdyson addr < endaddr; 49613907Sdyson addr += PAGE_SIZE, i+=1) { 49713907Sdyson 49813907Sdyson vm_page_t m; 49913907Sdyson 50013909Sdyson vm_fault_quick( (caddr_t) addr, VM_PROT_READ); 50113907Sdyson paddr = pmap_kextract(addr); 50213907Sdyson if (!paddr) { 50313907Sdyson int j; 50413907Sdyson for(j=0;j<i;j++) 50540700Sdg vm_page_unwire(wpipe->pipe_map.ms[j], 1); 50613907Sdyson return EFAULT; 50713907Sdyson } 50813907Sdyson 50913907Sdyson m = PHYS_TO_VM_PAGE(paddr); 51013907Sdyson vm_page_wire(m); 51113907Sdyson wpipe->pipe_map.ms[i] = m; 51213907Sdyson } 51313907Sdyson 51413907Sdyson/* 51513907Sdyson * set up the control block 51613907Sdyson */ 51713907Sdyson wpipe->pipe_map.npages = i; 51813907Sdyson wpipe->pipe_map.pos = ((vm_offset_t) uio->uio_iov->iov_base) & PAGE_MASK; 51913907Sdyson wpipe->pipe_map.cnt = size; 52013907Sdyson 52113907Sdyson/* 52213907Sdyson * and map the buffer 52313907Sdyson */ 52413907Sdyson if (wpipe->pipe_map.kva == 0) { 52513912Sdyson /* 52613912Sdyson * We need to allocate space for an extra page because the 52713912Sdyson * address range might (will) span pages at times. 52813912Sdyson */ 52913907Sdyson wpipe->pipe_map.kva = kmem_alloc_pageable(kernel_map, 53013912Sdyson wpipe->pipe_buffer.size + PAGE_SIZE); 53113912Sdyson amountpipekva += wpipe->pipe_buffer.size + PAGE_SIZE; 53213907Sdyson } 53313907Sdyson pmap_qenter(wpipe->pipe_map.kva, wpipe->pipe_map.ms, 53413907Sdyson wpipe->pipe_map.npages); 53513907Sdyson 53613907Sdyson/* 53713907Sdyson * and update the uio data 53813907Sdyson */ 53913907Sdyson 54013907Sdyson uio->uio_iov->iov_len -= size; 54113907Sdyson uio->uio_iov->iov_base += size; 54213907Sdyson if (uio->uio_iov->iov_len == 0) 54313907Sdyson uio->uio_iov++; 54413907Sdyson uio->uio_resid -= size; 54513907Sdyson uio->uio_offset += size; 54613907Sdyson return 0; 54713907Sdyson} 54813907Sdyson 54913907Sdyson/* 55013907Sdyson * unmap and unwire the process buffer 55113907Sdyson */ 55213907Sdysonstatic void 55313907Sdysonpipe_destroy_write_buffer(wpipe) 55413907Sdysonstruct pipe *wpipe; 55513907Sdyson{ 55613907Sdyson int i; 55717163Sdyson if (wpipe->pipe_map.kva) { 55817163Sdyson pmap_qremove(wpipe->pipe_map.kva, wpipe->pipe_map.npages); 55913907Sdyson 56013907Sdyson if (amountpipekva > MAXPIPEKVA) { 56113907Sdyson vm_offset_t kva = wpipe->pipe_map.kva; 56213907Sdyson wpipe->pipe_map.kva = 0; 56313907Sdyson kmem_free(kernel_map, kva, 56413912Sdyson wpipe->pipe_buffer.size + PAGE_SIZE); 56513912Sdyson amountpipekva -= wpipe->pipe_buffer.size + PAGE_SIZE; 56613907Sdyson } 56713907Sdyson } 56813907Sdyson for (i=0;i<wpipe->pipe_map.npages;i++) 56940700Sdg vm_page_unwire(wpipe->pipe_map.ms[i], 1); 57013907Sdyson} 57113907Sdyson 57213907Sdyson/* 57313907Sdyson * In the case of a signal, the writing process might go away. This 57413907Sdyson * code copies the data into the circular buffer so that the source 57513907Sdyson * pages can be freed without loss of data. 57613907Sdyson */ 57713907Sdysonstatic void 57813907Sdysonpipe_clone_write_buffer(wpipe) 57913907Sdysonstruct pipe *wpipe; 58013907Sdyson{ 58113907Sdyson int size; 58213907Sdyson int pos; 58313907Sdyson 58413907Sdyson size = wpipe->pipe_map.cnt; 58513907Sdyson pos = wpipe->pipe_map.pos; 58613907Sdyson bcopy((caddr_t) wpipe->pipe_map.kva+pos, 58713907Sdyson (caddr_t) wpipe->pipe_buffer.buffer, 58813907Sdyson size); 58913907Sdyson 59013907Sdyson wpipe->pipe_buffer.in = size; 59113907Sdyson wpipe->pipe_buffer.out = 0; 59213907Sdyson wpipe->pipe_buffer.cnt = size; 59313907Sdyson wpipe->pipe_state &= ~PIPE_DIRECTW; 59413907Sdyson 59513907Sdyson pipe_destroy_write_buffer(wpipe); 59613907Sdyson} 59713907Sdyson 59813907Sdyson/* 59913907Sdyson * This implements the pipe buffer write mechanism. Note that only 60013907Sdyson * a direct write OR a normal pipe write can be pending at any given time. 60113907Sdyson * If there are any characters in the pipe buffer, the direct write will 60213907Sdyson * be deferred until the receiving process grabs all of the bytes from 60313907Sdyson * the pipe buffer. Then the direct mapping write is set-up. 60413907Sdyson */ 60513907Sdysonstatic int 60613907Sdysonpipe_direct_write(wpipe, uio) 60713907Sdyson struct pipe *wpipe; 60813907Sdyson struct uio *uio; 60913907Sdyson{ 61013907Sdyson int error; 61113951Sdysonretry: 61213907Sdyson while (wpipe->pipe_state & PIPE_DIRECTW) { 61313951Sdyson if ( wpipe->pipe_state & PIPE_WANTR) { 61413951Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 61513951Sdyson wakeup(wpipe); 61613951Sdyson } 61713992Sdyson wpipe->pipe_state |= PIPE_WANTW; 61813907Sdyson error = tsleep(wpipe, 61913907Sdyson PRIBIO|PCATCH, "pipdww", 0); 62014802Sdyson if (error) 62113907Sdyson goto error1; 62214802Sdyson if (wpipe->pipe_state & PIPE_EOF) { 62314802Sdyson error = EPIPE; 62414802Sdyson goto error1; 62514802Sdyson } 62613907Sdyson } 62713907Sdyson wpipe->pipe_map.cnt = 0; /* transfer not ready yet */ 62813951Sdyson if (wpipe->pipe_buffer.cnt > 0) { 62913951Sdyson if ( wpipe->pipe_state & PIPE_WANTR) { 63013951Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 63113951Sdyson wakeup(wpipe); 63213951Sdyson } 63313951Sdyson 63413992Sdyson wpipe->pipe_state |= PIPE_WANTW; 63513907Sdyson error = tsleep(wpipe, 63613907Sdyson PRIBIO|PCATCH, "pipdwc", 0); 63714802Sdyson if (error) 63813907Sdyson goto error1; 63914802Sdyson if (wpipe->pipe_state & PIPE_EOF) { 64014802Sdyson error = EPIPE; 64114802Sdyson goto error1; 64213907Sdyson } 64313951Sdyson goto retry; 64413907Sdyson } 64513907Sdyson 64613951Sdyson wpipe->pipe_state |= PIPE_DIRECTW; 64713951Sdyson 64813907Sdyson error = pipe_build_write_buffer(wpipe, uio); 64913907Sdyson if (error) { 65013907Sdyson wpipe->pipe_state &= ~PIPE_DIRECTW; 65113907Sdyson goto error1; 65213907Sdyson } 65313907Sdyson 65413907Sdyson error = 0; 65513907Sdyson while (!error && (wpipe->pipe_state & PIPE_DIRECTW)) { 65613907Sdyson if (wpipe->pipe_state & PIPE_EOF) { 65713907Sdyson pipelock(wpipe, 0); 65813907Sdyson pipe_destroy_write_buffer(wpipe); 65913907Sdyson pipeunlock(wpipe); 66014037Sdyson pipeselwakeup(wpipe); 66114802Sdyson error = EPIPE; 66214802Sdyson goto error1; 66313907Sdyson } 66413992Sdyson if (wpipe->pipe_state & PIPE_WANTR) { 66513992Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 66613992Sdyson wakeup(wpipe); 66713992Sdyson } 66814037Sdyson pipeselwakeup(wpipe); 66913907Sdyson error = tsleep(wpipe, PRIBIO|PCATCH, "pipdwt", 0); 67013907Sdyson } 67113907Sdyson 67213907Sdyson pipelock(wpipe,0); 67313907Sdyson if (wpipe->pipe_state & PIPE_DIRECTW) { 67413907Sdyson /* 67513907Sdyson * this bit of trickery substitutes a kernel buffer for 67613907Sdyson * the process that might be going away. 67713907Sdyson */ 67813907Sdyson pipe_clone_write_buffer(wpipe); 67913907Sdyson } else { 68013907Sdyson pipe_destroy_write_buffer(wpipe); 68113907Sdyson } 68213907Sdyson pipeunlock(wpipe); 68313907Sdyson return error; 68413907Sdyson 68513907Sdysonerror1: 68613907Sdyson wakeup(wpipe); 68713907Sdyson return error; 68813907Sdyson} 68914037Sdyson#endif 69013907Sdyson 69116960Sdysonstatic int 69216960Sdysonpipe_write(fp, uio, cred) 69316960Sdyson struct file *fp; 69413907Sdyson struct uio *uio; 69516960Sdyson struct ucred *cred; 69613907Sdyson{ 69713675Sdyson int error = 0; 69813913Sdyson int orig_resid; 69913675Sdyson 70016960Sdyson struct pipe *wpipe, *rpipe; 70116960Sdyson 70216960Sdyson rpipe = (struct pipe *) fp->f_data; 70316960Sdyson wpipe = rpipe->pipe_peer; 70416960Sdyson 70513675Sdyson /* 70613675Sdyson * detect loss of pipe read side, issue SIGPIPE if lost. 70713675Sdyson */ 70816960Sdyson if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) { 70913774Sdyson return EPIPE; 71013675Sdyson } 71113675Sdyson 71217163Sdyson /* 71317163Sdyson * If it is advantageous to resize the pipe buffer, do 71417163Sdyson * so. 71517163Sdyson */ 71617163Sdyson if ((uio->uio_resid > PIPE_SIZE) && 71717163Sdyson (nbigpipe < LIMITBIGPIPES) && 71817163Sdyson (wpipe->pipe_state & PIPE_DIRECTW) == 0 && 71917163Sdyson (wpipe->pipe_buffer.size <= PIPE_SIZE) && 72017163Sdyson (wpipe->pipe_buffer.cnt == 0)) { 72117163Sdyson 72217163Sdyson if (wpipe->pipe_buffer.buffer) { 72317163Sdyson amountpipekva -= wpipe->pipe_buffer.size; 72417163Sdyson kmem_free(kernel_map, 72517163Sdyson (vm_offset_t)wpipe->pipe_buffer.buffer, 72617163Sdyson wpipe->pipe_buffer.size); 72717163Sdyson } 72817163Sdyson 72917163Sdyson#ifndef PIPE_NODIRECT 73017163Sdyson if (wpipe->pipe_map.kva) { 73117163Sdyson amountpipekva -= wpipe->pipe_buffer.size + PAGE_SIZE; 73217163Sdyson kmem_free(kernel_map, 73317163Sdyson wpipe->pipe_map.kva, 73417163Sdyson wpipe->pipe_buffer.size + PAGE_SIZE); 73517163Sdyson } 73617163Sdyson#endif 73717163Sdyson 73817163Sdyson wpipe->pipe_buffer.in = 0; 73917163Sdyson wpipe->pipe_buffer.out = 0; 74017163Sdyson wpipe->pipe_buffer.cnt = 0; 74117163Sdyson wpipe->pipe_buffer.size = BIG_PIPE_SIZE; 74217163Sdyson wpipe->pipe_buffer.buffer = NULL; 74317163Sdyson ++nbigpipe; 74417163Sdyson 74517163Sdyson#ifndef PIPE_NODIRECT 74617163Sdyson wpipe->pipe_map.cnt = 0; 74717163Sdyson wpipe->pipe_map.kva = 0; 74817163Sdyson wpipe->pipe_map.pos = 0; 74917163Sdyson wpipe->pipe_map.npages = 0; 75017163Sdyson#endif 75117163Sdyson 75217163Sdyson } 75317163Sdyson 75417163Sdyson 75513907Sdyson if( wpipe->pipe_buffer.buffer == NULL) { 75613907Sdyson if ((error = pipelock(wpipe,1)) == 0) { 75713907Sdyson pipespace(wpipe); 75813907Sdyson pipeunlock(wpipe); 75913907Sdyson } else { 76013907Sdyson return error; 76113907Sdyson } 76213907Sdyson } 76313907Sdyson 76413675Sdyson ++wpipe->pipe_busy; 76513913Sdyson orig_resid = uio->uio_resid; 76613675Sdyson while (uio->uio_resid) { 76713907Sdyson int space; 76814037Sdyson#ifndef PIPE_NODIRECT 76913907Sdyson /* 77013907Sdyson * If the transfer is large, we can gain performance if 77113907Sdyson * we do process-to-process copies directly. 77216416Sdyson * If the write is non-blocking, we don't use the 77316416Sdyson * direct write mechanism. 77413907Sdyson */ 77517163Sdyson if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) && 77617163Sdyson (fp->f_flag & FNONBLOCK) == 0 && 77717163Sdyson (wpipe->pipe_map.kva || (amountpipekva < LIMITPIPEKVA)) && 77813907Sdyson (uio->uio_iov->iov_len >= PIPE_MINDIRECT)) { 77913907Sdyson error = pipe_direct_write( wpipe, uio); 78013907Sdyson if (error) { 78113907Sdyson break; 78213907Sdyson } 78313907Sdyson continue; 78413907Sdyson } 78514037Sdyson#endif 78613907Sdyson 78713907Sdyson /* 78813907Sdyson * Pipe buffered writes cannot be coincidental with 78913907Sdyson * direct writes. We wait until the currently executing 79013907Sdyson * direct write is completed before we start filling the 79113907Sdyson * pipe buffer. 79213907Sdyson */ 79313907Sdyson retrywrite: 79413907Sdyson while (wpipe->pipe_state & PIPE_DIRECTW) { 79513992Sdyson if (wpipe->pipe_state & PIPE_WANTR) { 79613992Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 79713992Sdyson wakeup(wpipe); 79813992Sdyson } 79913907Sdyson error = tsleep(wpipe, 80013907Sdyson PRIBIO|PCATCH, "pipbww", 0); 80113907Sdyson if (error) 80213907Sdyson break; 80313907Sdyson } 80413907Sdyson 80513907Sdyson space = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt; 80614644Sdyson 80714644Sdyson /* Writes of size <= PIPE_BUF must be atomic. */ 80814644Sdyson /* XXX perhaps they need to be contiguous to be atomic? */ 80913913Sdyson if ((space < uio->uio_resid) && (orig_resid <= PIPE_BUF)) 81013913Sdyson space = 0; 81113907Sdyson 81217163Sdyson if (space > 0 && (wpipe->pipe_buffer.cnt < PIPE_SIZE)) { 81317163Sdyson /* 81417163Sdyson * This set the maximum transfer as a segment of 81517163Sdyson * the buffer. 81617163Sdyson */ 81713675Sdyson int size = wpipe->pipe_buffer.size - wpipe->pipe_buffer.in; 81817163Sdyson /* 81917163Sdyson * space is the size left in the buffer 82017163Sdyson */ 82113675Sdyson if (size > space) 82213675Sdyson size = space; 82317163Sdyson /* 82417163Sdyson * now limit it to the size of the uio transfer 82517163Sdyson */ 82613675Sdyson if (size > uio->uio_resid) 82713675Sdyson size = uio->uio_resid; 82813907Sdyson if ((error = pipelock(wpipe,1)) == 0) { 82913907Sdyson /* 83013907Sdyson * It is possible for a direct write to 83113907Sdyson * slip in on us... handle it here... 83213907Sdyson */ 83313907Sdyson if (wpipe->pipe_state & PIPE_DIRECTW) { 83413907Sdyson pipeunlock(wpipe); 83513907Sdyson goto retrywrite; 83613907Sdyson } 83713675Sdyson error = uiomove( &wpipe->pipe_buffer.buffer[wpipe->pipe_buffer.in], 83813675Sdyson size, uio); 83913675Sdyson pipeunlock(wpipe); 84013675Sdyson } 84113675Sdyson if (error) 84213675Sdyson break; 84313675Sdyson 84413675Sdyson wpipe->pipe_buffer.in += size; 84513675Sdyson if (wpipe->pipe_buffer.in >= wpipe->pipe_buffer.size) 84613675Sdyson wpipe->pipe_buffer.in = 0; 84713675Sdyson 84813675Sdyson wpipe->pipe_buffer.cnt += size; 84913675Sdyson } else { 85013675Sdyson /* 85113675Sdyson * If the "read-side" has been blocked, wake it up now. 85213675Sdyson */ 85313675Sdyson if (wpipe->pipe_state & PIPE_WANTR) { 85413675Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 85513675Sdyson wakeup(wpipe); 85613675Sdyson } 85714037Sdyson 85813675Sdyson /* 85913675Sdyson * don't block on non-blocking I/O 86013675Sdyson */ 86116960Sdyson if (fp->f_flag & FNONBLOCK) { 86213907Sdyson error = EAGAIN; 86313675Sdyson break; 86413675Sdyson } 86513907Sdyson 86614037Sdyson /* 86714037Sdyson * We have no more space and have something to offer, 86829356Speter * wake up select/poll. 86914037Sdyson */ 87014037Sdyson pipeselwakeup(wpipe); 87114037Sdyson 87213675Sdyson wpipe->pipe_state |= PIPE_WANTW; 87313776Sdyson if (error = tsleep(wpipe, (PRIBIO+1)|PCATCH, "pipewr", 0)) { 87413675Sdyson break; 87513675Sdyson } 87613675Sdyson /* 87713675Sdyson * If read side wants to go away, we just issue a signal 87813675Sdyson * to ourselves. 87913675Sdyson */ 88013675Sdyson if (wpipe->pipe_state & PIPE_EOF) { 88113774Sdyson error = EPIPE; 88213907Sdyson break; 88313675Sdyson } 88413675Sdyson } 88513675Sdyson } 88613675Sdyson 88714644Sdyson --wpipe->pipe_busy; 88813675Sdyson if ((wpipe->pipe_busy == 0) && 88913675Sdyson (wpipe->pipe_state & PIPE_WANT)) { 89013675Sdyson wpipe->pipe_state &= ~(PIPE_WANT|PIPE_WANTR); 89113675Sdyson wakeup(wpipe); 89213675Sdyson } else if (wpipe->pipe_buffer.cnt > 0) { 89313675Sdyson /* 89413675Sdyson * If we have put any characters in the buffer, we wake up 89513675Sdyson * the reader. 89613675Sdyson */ 89713675Sdyson if (wpipe->pipe_state & PIPE_WANTR) { 89813675Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 89913675Sdyson wakeup(wpipe); 90013675Sdyson } 90113675Sdyson } 90213909Sdyson 90313909Sdyson /* 90413909Sdyson * Don't return EPIPE if I/O was successful 90513909Sdyson */ 90613907Sdyson if ((wpipe->pipe_buffer.cnt == 0) && 90713907Sdyson (uio->uio_resid == 0) && 90813907Sdyson (error == EPIPE)) 90913907Sdyson error = 0; 91013913Sdyson 91124101Sbde if (error == 0) 91234901Sphk getnanotime(&wpipe->pipe_mtime); 91324101Sbde 91414037Sdyson /* 91514037Sdyson * We have something to offer, 91629356Speter * wake up select/poll. 91714037Sdyson */ 91814177Sdyson if (wpipe->pipe_buffer.cnt) 91914037Sdyson pipeselwakeup(wpipe); 92013907Sdyson 92113675Sdyson return error; 92213675Sdyson} 92313675Sdyson 92413675Sdyson/* 92513675Sdyson * we implement a very minimal set of ioctls for compatibility with sockets. 92613675Sdyson */ 92713675Sdysonint 92813675Sdysonpipe_ioctl(fp, cmd, data, p) 92913675Sdyson struct file *fp; 93036735Sdfr u_long cmd; 93113675Sdyson register caddr_t data; 93213675Sdyson struct proc *p; 93313675Sdyson{ 93413675Sdyson register struct pipe *mpipe = (struct pipe *)fp->f_data; 93513675Sdyson 93613675Sdyson switch (cmd) { 93713675Sdyson 93813675Sdyson case FIONBIO: 93913675Sdyson return (0); 94013675Sdyson 94113675Sdyson case FIOASYNC: 94213675Sdyson if (*(int *)data) { 94313675Sdyson mpipe->pipe_state |= PIPE_ASYNC; 94413675Sdyson } else { 94513675Sdyson mpipe->pipe_state &= ~PIPE_ASYNC; 94613675Sdyson } 94713675Sdyson return (0); 94813675Sdyson 94913675Sdyson case FIONREAD: 95014037Sdyson if (mpipe->pipe_state & PIPE_DIRECTW) 95114037Sdyson *(int *)data = mpipe->pipe_map.cnt; 95214037Sdyson else 95314037Sdyson *(int *)data = mpipe->pipe_buffer.cnt; 95413675Sdyson return (0); 95513675Sdyson 95618863Sdyson case TIOCSPGRP: 95713675Sdyson mpipe->pipe_pgid = *(int *)data; 95813675Sdyson return (0); 95913675Sdyson 96018863Sdyson case TIOCGPGRP: 96113675Sdyson *(int *)data = mpipe->pipe_pgid; 96213675Sdyson return (0); 96313675Sdyson 96413675Sdyson } 96517124Sbde return (ENOTTY); 96613675Sdyson} 96713675Sdyson 96813675Sdysonint 96929356Speterpipe_poll(fp, events, cred, p) 97013675Sdyson struct file *fp; 97129356Speter int events; 97229356Speter struct ucred *cred; 97313675Sdyson struct proc *p; 97413675Sdyson{ 97513675Sdyson register struct pipe *rpipe = (struct pipe *)fp->f_data; 97613675Sdyson struct pipe *wpipe; 97729356Speter int revents = 0; 97813675Sdyson 97913675Sdyson wpipe = rpipe->pipe_peer; 98029356Speter if (events & (POLLIN | POLLRDNORM)) 98129356Speter if ((rpipe->pipe_state & PIPE_DIRECTW) || 98229356Speter (rpipe->pipe_buffer.cnt > 0) || 98329356Speter (rpipe->pipe_state & PIPE_EOF)) 98429356Speter revents |= events & (POLLIN | POLLRDNORM); 98513675Sdyson 98629356Speter if (events & (POLLOUT | POLLWRNORM)) 98729356Speter if (wpipe == NULL || (wpipe->pipe_state & PIPE_EOF) || 98829356Speter ((wpipe->pipe_state & PIPE_DIRECTW) == 0) && 98929356Speter (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF) 99029356Speter revents |= events & (POLLOUT | POLLWRNORM); 99113675Sdyson 99229356Speter if ((rpipe->pipe_state & PIPE_EOF) || 99329356Speter (wpipe == NULL) || 99429356Speter (wpipe->pipe_state & PIPE_EOF)) 99529356Speter revents |= POLLHUP; 99629356Speter 99729356Speter if (revents == 0) { 99829356Speter if (events & (POLLIN | POLLRDNORM)) { 99929356Speter selrecord(p, &rpipe->pipe_sel); 100029356Speter rpipe->pipe_state |= PIPE_SEL; 100113675Sdyson } 100213675Sdyson 100329356Speter if (events & (POLLOUT | POLLWRNORM)) { 100430164Speter selrecord(p, &wpipe->pipe_sel); 100530164Speter wpipe->pipe_state |= PIPE_SEL; 100613907Sdyson } 100713675Sdyson } 100829356Speter 100929356Speter return (revents); 101013675Sdyson} 101113675Sdyson 101213675Sdysonint 101313675Sdysonpipe_stat(pipe, ub) 101413675Sdyson register struct pipe *pipe; 101513675Sdyson register struct stat *ub; 101613675Sdyson{ 101713675Sdyson bzero((caddr_t)ub, sizeof (*ub)); 101817124Sbde ub->st_mode = S_IFIFO; 101913907Sdyson ub->st_blksize = pipe->pipe_buffer.size; 102013675Sdyson ub->st_size = pipe->pipe_buffer.cnt; 102113675Sdyson ub->st_blocks = (ub->st_size + ub->st_blksize - 1) / ub->st_blksize; 102234901Sphk ub->st_atimespec = pipe->pipe_atime; 102334901Sphk ub->st_mtimespec = pipe->pipe_mtime; 102434901Sphk ub->st_ctimespec = pipe->pipe_ctime; 102517124Sbde /* 102617124Sbde * Left as 0: st_dev, st_ino, st_nlink, st_uid, st_gid, st_rdev, 102717124Sbde * st_flags, st_gen. 102817124Sbde * XXX (st_dev, st_ino) should be unique. 102917124Sbde */ 103013675Sdyson return 0; 103113675Sdyson} 103213675Sdyson 103313675Sdyson/* ARGSUSED */ 103413675Sdysonstatic int 103513675Sdysonpipe_close(fp, p) 103613675Sdyson struct file *fp; 103713675Sdyson struct proc *p; 103813675Sdyson{ 103913675Sdyson struct pipe *cpipe = (struct pipe *)fp->f_data; 104016322Sgpalmer 104113675Sdyson pipeclose(cpipe); 104213675Sdyson fp->f_data = NULL; 104313675Sdyson return 0; 104413675Sdyson} 104513675Sdyson 104613675Sdyson/* 104713675Sdyson * shutdown the pipe 104813675Sdyson */ 104913675Sdysonstatic void 105013675Sdysonpipeclose(cpipe) 105113675Sdyson struct pipe *cpipe; 105213675Sdyson{ 105313907Sdyson struct pipe *ppipe; 105413675Sdyson if (cpipe) { 105513907Sdyson 105614037Sdyson pipeselwakeup(cpipe); 105713907Sdyson 105813675Sdyson /* 105913675Sdyson * If the other side is blocked, wake it up saying that 106013675Sdyson * we want to close it down. 106113675Sdyson */ 106213675Sdyson while (cpipe->pipe_busy) { 106313675Sdyson wakeup(cpipe); 106413675Sdyson cpipe->pipe_state |= PIPE_WANT|PIPE_EOF; 106513675Sdyson tsleep(cpipe, PRIBIO, "pipecl", 0); 106613675Sdyson } 106713675Sdyson 106813675Sdyson /* 106913675Sdyson * Disconnect from peer 107013675Sdyson */ 107113907Sdyson if (ppipe = cpipe->pipe_peer) { 107214037Sdyson pipeselwakeup(ppipe); 107313907Sdyson 107413907Sdyson ppipe->pipe_state |= PIPE_EOF; 107513907Sdyson wakeup(ppipe); 107613907Sdyson ppipe->pipe_peer = NULL; 107713675Sdyson } 107813675Sdyson 107913675Sdyson /* 108013675Sdyson * free resources 108113675Sdyson */ 108213907Sdyson if (cpipe->pipe_buffer.buffer) { 108317163Sdyson if (cpipe->pipe_buffer.size > PIPE_SIZE) 108417163Sdyson --nbigpipe; 108513907Sdyson amountpipekva -= cpipe->pipe_buffer.size; 108613907Sdyson kmem_free(kernel_map, 108713907Sdyson (vm_offset_t)cpipe->pipe_buffer.buffer, 108813907Sdyson cpipe->pipe_buffer.size); 108913907Sdyson } 109014037Sdyson#ifndef PIPE_NODIRECT 109113907Sdyson if (cpipe->pipe_map.kva) { 109213912Sdyson amountpipekva -= cpipe->pipe_buffer.size + PAGE_SIZE; 109313907Sdyson kmem_free(kernel_map, 109413907Sdyson cpipe->pipe_map.kva, 109513912Sdyson cpipe->pipe_buffer.size + PAGE_SIZE); 109613907Sdyson } 109714037Sdyson#endif 109827899Sdyson zfree(pipe_zone, cpipe); 109913675Sdyson } 110013675Sdyson} 1101