sys_pipe.c revision 24206
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 * 1924206Sbde * $Id: sys_pipe.c,v 1.26 1997/03/23 03:36:24 bde Exp $ 2013675Sdyson */ 2113675Sdyson 2213675Sdyson#ifndef OLD_PIPE 2313675Sdyson 2413675Sdyson/* 2513675Sdyson * This file contains a high-performance replacement for the socket-based 2613675Sdyson * pipes scheme originally used in FreeBSD/4.4Lite. It does not support 2713675Sdyson * all features of sockets, but does do everything that pipes normally 2813675Sdyson * do. 2913675Sdyson */ 3013675Sdyson 3113907Sdyson/* 3213907Sdyson * This code has two modes of operation, a small write mode and a large 3313907Sdyson * write mode. The small write mode acts like conventional pipes with 3413907Sdyson * a kernel buffer. If the buffer is less than PIPE_MINDIRECT, then the 3513907Sdyson * "normal" pipe buffering is done. If the buffer is between PIPE_MINDIRECT 3613907Sdyson * and PIPE_SIZE in size, it is fully mapped and wired into the kernel, and 3713907Sdyson * the receiving process can copy it directly from the pages in the sending 3813907Sdyson * process. 3913907Sdyson * 4013907Sdyson * If the sending process receives a signal, it is possible that it will 4113913Sdyson * go away, and certainly its address space can change, because control 4213907Sdyson * is returned back to the user-mode side. In that case, the pipe code 4313907Sdyson * arranges to copy the buffer supplied by the user process, to a pageable 4413907Sdyson * kernel buffer, and the receiving process will grab the data from the 4513907Sdyson * pageable kernel buffer. Since signals don't happen all that often, 4613907Sdyson * the copy operation is normally eliminated. 4713907Sdyson * 4813907Sdyson * The constant PIPE_MINDIRECT is chosen to make sure that buffering will 4913907Sdyson * happen for small transfers so that the system will not spend all of 5013913Sdyson * its time context switching. PIPE_SIZE is constrained by the 5113907Sdyson * amount of kernel virtual memory. 5213907Sdyson */ 5313907Sdyson 5413675Sdyson#include <sys/param.h> 5513675Sdyson#include <sys/systm.h> 5613675Sdyson#include <sys/proc.h> 5724131Sbde#include <sys/fcntl.h> 5813675Sdyson#include <sys/file.h> 5913675Sdyson#include <sys/protosw.h> 6013675Sdyson#include <sys/stat.h> 6113675Sdyson#include <sys/filedesc.h> 6213675Sdyson#include <sys/malloc.h> 6324206Sbde#include <sys/filio.h> 6424206Sbde#include <sys/ttycom.h> 6513675Sdyson#include <sys/stat.h> 6613675Sdyson#include <sys/select.h> 6713675Sdyson#include <sys/signalvar.h> 6813675Sdyson#include <sys/errno.h> 6913675Sdyson#include <sys/queue.h> 7013675Sdyson#include <sys/vmmeter.h> 7113675Sdyson#include <sys/kernel.h> 7213675Sdyson#include <sys/sysproto.h> 7313675Sdyson#include <sys/pipe.h> 7413675Sdyson 7513675Sdyson#include <vm/vm.h> 7613675Sdyson#include <vm/vm_prot.h> 7713675Sdyson#include <vm/vm_param.h> 7822521Sdyson#include <sys/lock.h> 7913675Sdyson#include <vm/vm_object.h> 8013675Sdyson#include <vm/vm_kern.h> 8113675Sdyson#include <vm/vm_extern.h> 8213675Sdyson#include <vm/pmap.h> 8313675Sdyson#include <vm/vm_map.h> 8413907Sdyson#include <vm/vm_page.h> 8513675Sdyson 8614037Sdyson/* 8714037Sdyson * Use this define if you want to disable *fancy* VM things. Expect an 8814037Sdyson * approx 30% decrease in transfer rate. This could be useful for 8914037Sdyson * NetBSD or OpenBSD. 9014037Sdyson */ 9114037Sdyson/* #define PIPE_NODIRECT */ 9214037Sdyson 9314037Sdyson/* 9414037Sdyson * interfaces to the outside world 9514037Sdyson */ 9613675Sdysonstatic int pipe_read __P((struct file *fp, struct uio *uio, 9713675Sdyson struct ucred *cred)); 9813675Sdysonstatic int pipe_write __P((struct file *fp, struct uio *uio, 9913675Sdyson struct ucred *cred)); 10013675Sdysonstatic int pipe_close __P((struct file *fp, struct proc *p)); 10113675Sdysonstatic int pipe_select __P((struct file *fp, int which, struct proc *p)); 10213675Sdysonstatic int pipe_ioctl __P((struct file *fp, int cmd, caddr_t data, struct proc *p)); 10313675Sdyson 10413675Sdysonstatic struct fileops pipeops = 10513675Sdyson { pipe_read, pipe_write, pipe_ioctl, pipe_select, pipe_close }; 10613675Sdyson 10713675Sdyson/* 10813675Sdyson * Default pipe buffer size(s), this can be kind-of large now because pipe 10913675Sdyson * space is pageable. The pipe code will try to maintain locality of 11013675Sdyson * reference for performance reasons, so small amounts of outstanding I/O 11113675Sdyson * will not wipe the cache. 11213675Sdyson */ 11313907Sdyson#define MINPIPESIZE (PIPE_SIZE/3) 11413907Sdyson#define MAXPIPESIZE (2*PIPE_SIZE/3) 11513675Sdyson 11613907Sdyson/* 11713907Sdyson * Maximum amount of kva for pipes -- this is kind-of a soft limit, but 11813907Sdyson * is there so that on large systems, we don't exhaust it. 11913907Sdyson */ 12013907Sdyson#define MAXPIPEKVA (8*1024*1024) 12113907Sdyson 12213907Sdyson/* 12313907Sdyson * Limit for direct transfers, we cannot, of course limit 12413907Sdyson * the amount of kva for pipes in general though. 12513907Sdyson */ 12613907Sdyson#define LIMITPIPEKVA (16*1024*1024) 12717163Sdyson 12817163Sdyson/* 12917163Sdyson * Limit the number of "big" pipes 13017163Sdyson */ 13117163Sdyson#define LIMITBIGPIPES 32 13217163Sdysonint nbigpipe; 13317163Sdyson 13417124Sbdestatic int amountpipekva; 13513907Sdyson 13613675Sdysonstatic void pipeclose __P((struct pipe *cpipe)); 13713675Sdysonstatic void pipeinit __P((struct pipe *cpipe)); 13813907Sdysonstatic __inline int pipelock __P((struct pipe *cpipe, int catch)); 13913675Sdysonstatic __inline void pipeunlock __P((struct pipe *cpipe)); 14014122Speterstatic __inline void pipeselwakeup __P((struct pipe *cpipe)); 14114037Sdyson#ifndef PIPE_NODIRECT 14213907Sdysonstatic int pipe_build_write_buffer __P((struct pipe *wpipe, struct uio *uio)); 14313907Sdysonstatic void pipe_destroy_write_buffer __P((struct pipe *wpipe)); 14413907Sdysonstatic int pipe_direct_write __P((struct pipe *wpipe, struct uio *uio)); 14513907Sdysonstatic void pipe_clone_write_buffer __P((struct pipe *wpipe)); 14614037Sdyson#endif 14713907Sdysonstatic void pipespace __P((struct pipe *cpipe)); 14813675Sdyson 14913675Sdyson/* 15013675Sdyson * The pipe system call for the DTYPE_PIPE type of pipes 15113675Sdyson */ 15213675Sdyson 15313675Sdyson/* ARGSUSED */ 15413675Sdysonint 15513675Sdysonpipe(p, uap, retval) 15613675Sdyson struct proc *p; 15713675Sdyson struct pipe_args /* { 15813675Sdyson int dummy; 15913675Sdyson } */ *uap; 16013675Sdyson int retval[]; 16113675Sdyson{ 16213675Sdyson register struct filedesc *fdp = p->p_fd; 16313675Sdyson struct file *rf, *wf; 16413675Sdyson struct pipe *rpipe, *wpipe; 16513675Sdyson int fd, error; 16613675Sdyson 16713675Sdyson rpipe = malloc( sizeof (*rpipe), M_TEMP, M_WAITOK); 16813675Sdyson pipeinit(rpipe); 16913907Sdyson rpipe->pipe_state |= PIPE_DIRECTOK; 17013675Sdyson wpipe = malloc( sizeof (*wpipe), M_TEMP, M_WAITOK); 17113675Sdyson pipeinit(wpipe); 17213907Sdyson wpipe->pipe_state |= PIPE_DIRECTOK; 17313675Sdyson 17413675Sdyson error = falloc(p, &rf, &fd); 17513675Sdyson if (error) 17613675Sdyson goto free2; 17713675Sdyson retval[0] = fd; 17813675Sdyson rf->f_flag = FREAD | FWRITE; 17913675Sdyson rf->f_type = DTYPE_PIPE; 18013675Sdyson rf->f_ops = &pipeops; 18113675Sdyson rf->f_data = (caddr_t)rpipe; 18213675Sdyson error = falloc(p, &wf, &fd); 18313675Sdyson if (error) 18413675Sdyson goto free3; 18513675Sdyson wf->f_flag = FREAD | FWRITE; 18613675Sdyson wf->f_type = DTYPE_PIPE; 18713675Sdyson wf->f_ops = &pipeops; 18813675Sdyson wf->f_data = (caddr_t)wpipe; 18913675Sdyson retval[1] = fd; 19013675Sdyson 19113675Sdyson rpipe->pipe_peer = wpipe; 19213675Sdyson wpipe->pipe_peer = rpipe; 19313675Sdyson 19413675Sdyson return (0); 19513675Sdysonfree3: 19613675Sdyson ffree(rf); 19713675Sdyson fdp->fd_ofiles[retval[0]] = 0; 19813675Sdysonfree2: 19913675Sdyson (void)pipeclose(wpipe); 20013675Sdyson (void)pipeclose(rpipe); 20113675Sdyson return (error); 20213675Sdyson} 20313675Sdyson 20413909Sdyson/* 20513909Sdyson * Allocate kva for pipe circular buffer, the space is pageable 20613909Sdyson */ 20713675Sdysonstatic void 20813907Sdysonpipespace(cpipe) 20913675Sdyson struct pipe *cpipe; 21013675Sdyson{ 21113688Sdyson int npages, error; 21213675Sdyson 21313907Sdyson npages = round_page(cpipe->pipe_buffer.size)/PAGE_SIZE; 21413675Sdyson /* 21513675Sdyson * Create an object, I don't like the idea of paging to/from 21613675Sdyson * kernel_object. 21714037Sdyson * XXX -- minor change needed here for NetBSD/OpenBSD VM systems. 21813675Sdyson */ 21913675Sdyson cpipe->pipe_buffer.object = vm_object_allocate(OBJT_DEFAULT, npages); 22013688Sdyson cpipe->pipe_buffer.buffer = (caddr_t) vm_map_min(kernel_map); 22113675Sdyson 22213675Sdyson /* 22313675Sdyson * Insert the object into the kernel map, and allocate kva for it. 22413675Sdyson * The map entry is, by default, pageable. 22514037Sdyson * XXX -- minor change needed here for NetBSD/OpenBSD VM systems. 22613675Sdyson */ 22713688Sdyson error = vm_map_find(kernel_map, cpipe->pipe_buffer.object, 0, 22813907Sdyson (vm_offset_t *) &cpipe->pipe_buffer.buffer, 22913907Sdyson cpipe->pipe_buffer.size, 1, 23013688Sdyson VM_PROT_ALL, VM_PROT_ALL, 0); 23113675Sdyson 23213688Sdyson if (error != KERN_SUCCESS) 23313688Sdyson panic("pipeinit: cannot allocate pipe -- out of kvm -- code = %d", error); 23413907Sdyson amountpipekva += cpipe->pipe_buffer.size; 23513907Sdyson} 23613688Sdyson 23713907Sdyson/* 23813907Sdyson * initialize and allocate VM and memory for pipe 23913907Sdyson */ 24013907Sdysonstatic void 24113907Sdysonpipeinit(cpipe) 24213907Sdyson struct pipe *cpipe; 24313907Sdyson{ 24413913Sdyson int s; 24513907Sdyson 24613675Sdyson cpipe->pipe_buffer.in = 0; 24713675Sdyson cpipe->pipe_buffer.out = 0; 24813675Sdyson cpipe->pipe_buffer.cnt = 0; 24913907Sdyson cpipe->pipe_buffer.size = PIPE_SIZE; 25017163Sdyson 25113907Sdyson /* Buffer kva gets dynamically allocated */ 25213907Sdyson cpipe->pipe_buffer.buffer = NULL; 25317124Sbde /* cpipe->pipe_buffer.object = invalid */ 25413675Sdyson 25513675Sdyson cpipe->pipe_state = 0; 25613675Sdyson cpipe->pipe_peer = NULL; 25713675Sdyson cpipe->pipe_busy = 0; 25824101Sbde gettime(&cpipe->pipe_ctime); 25924101Sbde cpipe->pipe_atime = cpipe->pipe_ctime; 26024101Sbde cpipe->pipe_mtime = cpipe->pipe_ctime; 26113675Sdyson bzero(&cpipe->pipe_sel, sizeof cpipe->pipe_sel); 26217124Sbde cpipe->pipe_pgid = NO_PID; 26313907Sdyson 26414037Sdyson#ifndef PIPE_NODIRECT 26513907Sdyson /* 26613907Sdyson * pipe data structure initializations to support direct pipe I/O 26713907Sdyson */ 26813907Sdyson cpipe->pipe_map.cnt = 0; 26913907Sdyson cpipe->pipe_map.kva = 0; 27013907Sdyson cpipe->pipe_map.pos = 0; 27113907Sdyson cpipe->pipe_map.npages = 0; 27217124Sbde /* cpipe->pipe_map.ms[] = invalid */ 27314037Sdyson#endif 27413675Sdyson} 27513675Sdyson 27613675Sdyson 27713675Sdyson/* 27813675Sdyson * lock a pipe for I/O, blocking other access 27913675Sdyson */ 28013675Sdysonstatic __inline int 28113907Sdysonpipelock(cpipe, catch) 28213675Sdyson struct pipe *cpipe; 28313907Sdyson int catch; 28413675Sdyson{ 28513776Sdyson int error; 28613675Sdyson while (cpipe->pipe_state & PIPE_LOCK) { 28713675Sdyson cpipe->pipe_state |= PIPE_LWANT; 28814177Sdyson if (error = tsleep( cpipe, 28913907Sdyson catch?(PRIBIO|PCATCH):PRIBIO, "pipelk", 0)) { 29013776Sdyson return error; 29113675Sdyson } 29213675Sdyson } 29313675Sdyson cpipe->pipe_state |= PIPE_LOCK; 29413675Sdyson return 0; 29513675Sdyson} 29613675Sdyson 29713675Sdyson/* 29813675Sdyson * unlock a pipe I/O lock 29913675Sdyson */ 30013675Sdysonstatic __inline void 30113675Sdysonpipeunlock(cpipe) 30213675Sdyson struct pipe *cpipe; 30313675Sdyson{ 30413675Sdyson cpipe->pipe_state &= ~PIPE_LOCK; 30513675Sdyson if (cpipe->pipe_state & PIPE_LWANT) { 30613675Sdyson cpipe->pipe_state &= ~PIPE_LWANT; 30714177Sdyson wakeup(cpipe); 30813675Sdyson } 30913675Sdyson} 31013675Sdyson 31114037Sdysonstatic __inline void 31214037Sdysonpipeselwakeup(cpipe) 31314037Sdyson struct pipe *cpipe; 31414037Sdyson{ 31518863Sdyson struct proc *p; 31618863Sdyson 31714037Sdyson if (cpipe->pipe_state & PIPE_SEL) { 31814037Sdyson cpipe->pipe_state &= ~PIPE_SEL; 31914037Sdyson selwakeup(&cpipe->pipe_sel); 32014037Sdyson } 32118863Sdyson if (cpipe->pipe_state & PIPE_ASYNC) { 32218863Sdyson if (cpipe->pipe_pgid < 0) 32318863Sdyson gsignal(-cpipe->pipe_pgid, SIGIO); 32418863Sdyson else if ((p = pfind(cpipe->pipe_pgid)) != NULL) 32518863Sdyson psignal(p, SIGIO); 32618863Sdyson } 32714037Sdyson} 32814037Sdyson 32913675Sdyson/* ARGSUSED */ 33013675Sdysonstatic int 33113675Sdysonpipe_read(fp, uio, cred) 33213675Sdyson struct file *fp; 33313675Sdyson struct uio *uio; 33413675Sdyson struct ucred *cred; 33513675Sdyson{ 33613675Sdyson 33713675Sdyson struct pipe *rpipe = (struct pipe *) fp->f_data; 33813675Sdyson int error = 0; 33913675Sdyson int nread = 0; 34018863Sdyson u_int size; 34113675Sdyson 34213675Sdyson ++rpipe->pipe_busy; 34313675Sdyson while (uio->uio_resid) { 34413907Sdyson /* 34513907Sdyson * normal pipe buffer receive 34613907Sdyson */ 34713675Sdyson if (rpipe->pipe_buffer.cnt > 0) { 34818863Sdyson size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out; 34913675Sdyson if (size > rpipe->pipe_buffer.cnt) 35013675Sdyson size = rpipe->pipe_buffer.cnt; 35118863Sdyson if (size > (u_int) uio->uio_resid) 35218863Sdyson size = (u_int) uio->uio_resid; 35313907Sdyson if ((error = pipelock(rpipe,1)) == 0) { 35413675Sdyson error = uiomove( &rpipe->pipe_buffer.buffer[rpipe->pipe_buffer.out], 35513675Sdyson size, uio); 35613675Sdyson pipeunlock(rpipe); 35713675Sdyson } 35813675Sdyson if (error) { 35913675Sdyson break; 36013675Sdyson } 36113675Sdyson rpipe->pipe_buffer.out += size; 36213675Sdyson if (rpipe->pipe_buffer.out >= rpipe->pipe_buffer.size) 36313675Sdyson rpipe->pipe_buffer.out = 0; 36413675Sdyson 36513675Sdyson rpipe->pipe_buffer.cnt -= size; 36613675Sdyson nread += size; 36714037Sdyson#ifndef PIPE_NODIRECT 36813907Sdyson /* 36913907Sdyson * Direct copy, bypassing a kernel buffer. 37013907Sdyson */ 37113907Sdyson } else if ((size = rpipe->pipe_map.cnt) && 37213907Sdyson (rpipe->pipe_state & PIPE_DIRECTW)) { 37313907Sdyson caddr_t va; 37418863Sdyson if (size > (u_int) uio->uio_resid) 37518863Sdyson size = (u_int) uio->uio_resid; 37613907Sdyson if ((error = pipelock(rpipe,1)) == 0) { 37713907Sdyson va = (caddr_t) rpipe->pipe_map.kva + rpipe->pipe_map.pos; 37813907Sdyson error = uiomove(va, size, uio); 37913907Sdyson pipeunlock(rpipe); 38013907Sdyson } 38113907Sdyson if (error) 38213907Sdyson break; 38313907Sdyson nread += size; 38413907Sdyson rpipe->pipe_map.pos += size; 38513907Sdyson rpipe->pipe_map.cnt -= size; 38613907Sdyson if (rpipe->pipe_map.cnt == 0) { 38713907Sdyson rpipe->pipe_state &= ~PIPE_DIRECTW; 38813907Sdyson wakeup(rpipe); 38913907Sdyson } 39014037Sdyson#endif 39113675Sdyson } else { 39213675Sdyson /* 39313675Sdyson * detect EOF condition 39413675Sdyson */ 39513675Sdyson if (rpipe->pipe_state & PIPE_EOF) { 39614802Sdyson /* XXX error = ? */ 39713675Sdyson break; 39813675Sdyson } 39913675Sdyson /* 40013675Sdyson * If the "write-side" has been blocked, wake it up now. 40113675Sdyson */ 40213675Sdyson if (rpipe->pipe_state & PIPE_WANTW) { 40313675Sdyson rpipe->pipe_state &= ~PIPE_WANTW; 40413675Sdyson wakeup(rpipe); 40513675Sdyson } 40613774Sdyson if (nread > 0) 40713675Sdyson break; 40816960Sdyson 40916960Sdyson if (fp->f_flag & FNONBLOCK) { 41013774Sdyson error = EAGAIN; 41113774Sdyson break; 41213774Sdyson } 41313675Sdyson 41413675Sdyson /* 41513675Sdyson * If there is no more to read in the pipe, reset 41613913Sdyson * its pointers to the beginning. This improves 41713675Sdyson * cache hit stats. 41813675Sdyson */ 41913675Sdyson 42013907Sdyson if ((error = pipelock(rpipe,1)) == 0) { 42113675Sdyson if (rpipe->pipe_buffer.cnt == 0) { 42213675Sdyson rpipe->pipe_buffer.in = 0; 42313675Sdyson rpipe->pipe_buffer.out = 0; 42413675Sdyson } 42513675Sdyson pipeunlock(rpipe); 42613675Sdyson } else { 42713675Sdyson break; 42813675Sdyson } 42914177Sdyson 43014177Sdyson if (rpipe->pipe_state & PIPE_WANTW) { 43114177Sdyson rpipe->pipe_state &= ~PIPE_WANTW; 43214177Sdyson wakeup(rpipe); 43314177Sdyson } 43414177Sdyson 43513675Sdyson rpipe->pipe_state |= PIPE_WANTR; 43613776Sdyson if (error = tsleep(rpipe, PRIBIO|PCATCH, "piperd", 0)) { 43713675Sdyson break; 43813675Sdyson } 43913675Sdyson } 44013675Sdyson } 44113675Sdyson 44224101Sbde if (error == 0) 44324101Sbde gettime(&rpipe->pipe_atime); 44413913Sdyson 44513675Sdyson --rpipe->pipe_busy; 44613675Sdyson if ((rpipe->pipe_busy == 0) && (rpipe->pipe_state & PIPE_WANT)) { 44713675Sdyson rpipe->pipe_state &= ~(PIPE_WANT|PIPE_WANTW); 44813675Sdyson wakeup(rpipe); 44913675Sdyson } else if (rpipe->pipe_buffer.cnt < MINPIPESIZE) { 45013675Sdyson /* 45113675Sdyson * If there is no more to read in the pipe, reset 45213913Sdyson * its pointers to the beginning. This improves 45313675Sdyson * cache hit stats. 45413675Sdyson */ 45517163Sdyson if (rpipe->pipe_buffer.cnt == 0) { 45617163Sdyson if ((error == 0) && (error = pipelock(rpipe,1)) == 0) { 45713675Sdyson rpipe->pipe_buffer.in = 0; 45813675Sdyson rpipe->pipe_buffer.out = 0; 45917163Sdyson pipeunlock(rpipe); 46013675Sdyson } 46113675Sdyson } 46213675Sdyson 46313675Sdyson /* 46413675Sdyson * If the "write-side" has been blocked, wake it up now. 46513675Sdyson */ 46613675Sdyson if (rpipe->pipe_state & PIPE_WANTW) { 46713675Sdyson rpipe->pipe_state &= ~PIPE_WANTW; 46813675Sdyson wakeup(rpipe); 46913675Sdyson } 47013675Sdyson } 47114037Sdyson 47214802Sdyson if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF) 47314037Sdyson pipeselwakeup(rpipe); 47414037Sdyson 47513675Sdyson return error; 47613675Sdyson} 47713675Sdyson 47814037Sdyson#ifndef PIPE_NODIRECT 47913907Sdyson/* 48013907Sdyson * Map the sending processes' buffer into kernel space and wire it. 48113907Sdyson * This is similar to a physical write operation. 48213907Sdyson */ 48313675Sdysonstatic int 48413907Sdysonpipe_build_write_buffer(wpipe, uio) 48513907Sdyson struct pipe *wpipe; 48613675Sdyson struct uio *uio; 48713675Sdyson{ 48818863Sdyson u_int size; 48913907Sdyson int i; 49013907Sdyson vm_offset_t addr, endaddr, paddr; 49113907Sdyson 49218863Sdyson size = (u_int) uio->uio_iov->iov_len; 49313907Sdyson if (size > wpipe->pipe_buffer.size) 49413907Sdyson size = wpipe->pipe_buffer.size; 49513907Sdyson 49613907Sdyson endaddr = round_page(uio->uio_iov->iov_base + size); 49713907Sdyson for(i = 0, addr = trunc_page(uio->uio_iov->iov_base); 49813907Sdyson addr < endaddr; 49913907Sdyson addr += PAGE_SIZE, i+=1) { 50013907Sdyson 50113907Sdyson vm_page_t m; 50213907Sdyson 50313909Sdyson vm_fault_quick( (caddr_t) addr, VM_PROT_READ); 50413907Sdyson paddr = pmap_kextract(addr); 50513907Sdyson if (!paddr) { 50613907Sdyson int j; 50713907Sdyson for(j=0;j<i;j++) 50813907Sdyson vm_page_unwire(wpipe->pipe_map.ms[j]); 50913907Sdyson return EFAULT; 51013907Sdyson } 51113907Sdyson 51213907Sdyson m = PHYS_TO_VM_PAGE(paddr); 51313907Sdyson vm_page_wire(m); 51413907Sdyson wpipe->pipe_map.ms[i] = m; 51513907Sdyson } 51613907Sdyson 51713907Sdyson/* 51813907Sdyson * set up the control block 51913907Sdyson */ 52013907Sdyson wpipe->pipe_map.npages = i; 52113907Sdyson wpipe->pipe_map.pos = ((vm_offset_t) uio->uio_iov->iov_base) & PAGE_MASK; 52213907Sdyson wpipe->pipe_map.cnt = size; 52313907Sdyson 52413907Sdyson/* 52513907Sdyson * and map the buffer 52613907Sdyson */ 52713907Sdyson if (wpipe->pipe_map.kva == 0) { 52813912Sdyson /* 52913912Sdyson * We need to allocate space for an extra page because the 53013912Sdyson * address range might (will) span pages at times. 53113912Sdyson */ 53213907Sdyson wpipe->pipe_map.kva = kmem_alloc_pageable(kernel_map, 53313912Sdyson wpipe->pipe_buffer.size + PAGE_SIZE); 53413912Sdyson amountpipekva += wpipe->pipe_buffer.size + PAGE_SIZE; 53513907Sdyson } 53613907Sdyson pmap_qenter(wpipe->pipe_map.kva, wpipe->pipe_map.ms, 53713907Sdyson wpipe->pipe_map.npages); 53813907Sdyson 53913907Sdyson/* 54013907Sdyson * and update the uio data 54113907Sdyson */ 54213907Sdyson 54313907Sdyson uio->uio_iov->iov_len -= size; 54413907Sdyson uio->uio_iov->iov_base += size; 54513907Sdyson if (uio->uio_iov->iov_len == 0) 54613907Sdyson uio->uio_iov++; 54713907Sdyson uio->uio_resid -= size; 54813907Sdyson uio->uio_offset += size; 54913907Sdyson return 0; 55013907Sdyson} 55113907Sdyson 55213907Sdyson/* 55313907Sdyson * unmap and unwire the process buffer 55413907Sdyson */ 55513907Sdysonstatic void 55613907Sdysonpipe_destroy_write_buffer(wpipe) 55713907Sdysonstruct pipe *wpipe; 55813907Sdyson{ 55913907Sdyson int i; 56017163Sdyson if (wpipe->pipe_map.kva) { 56117163Sdyson pmap_qremove(wpipe->pipe_map.kva, wpipe->pipe_map.npages); 56213907Sdyson 56313907Sdyson if (amountpipekva > MAXPIPEKVA) { 56413907Sdyson vm_offset_t kva = wpipe->pipe_map.kva; 56513907Sdyson wpipe->pipe_map.kva = 0; 56613907Sdyson kmem_free(kernel_map, kva, 56713912Sdyson wpipe->pipe_buffer.size + PAGE_SIZE); 56813912Sdyson amountpipekva -= wpipe->pipe_buffer.size + PAGE_SIZE; 56913907Sdyson } 57013907Sdyson } 57113907Sdyson for (i=0;i<wpipe->pipe_map.npages;i++) 57213907Sdyson vm_page_unwire(wpipe->pipe_map.ms[i]); 57313907Sdyson} 57413907Sdyson 57513907Sdyson/* 57613907Sdyson * In the case of a signal, the writing process might go away. This 57713907Sdyson * code copies the data into the circular buffer so that the source 57813907Sdyson * pages can be freed without loss of data. 57913907Sdyson */ 58013907Sdysonstatic void 58113907Sdysonpipe_clone_write_buffer(wpipe) 58213907Sdysonstruct pipe *wpipe; 58313907Sdyson{ 58413907Sdyson int size; 58513907Sdyson int pos; 58613907Sdyson 58713907Sdyson size = wpipe->pipe_map.cnt; 58813907Sdyson pos = wpipe->pipe_map.pos; 58913907Sdyson bcopy((caddr_t) wpipe->pipe_map.kva+pos, 59013907Sdyson (caddr_t) wpipe->pipe_buffer.buffer, 59113907Sdyson size); 59213907Sdyson 59313907Sdyson wpipe->pipe_buffer.in = size; 59413907Sdyson wpipe->pipe_buffer.out = 0; 59513907Sdyson wpipe->pipe_buffer.cnt = size; 59613907Sdyson wpipe->pipe_state &= ~PIPE_DIRECTW; 59713907Sdyson 59813907Sdyson pipe_destroy_write_buffer(wpipe); 59913907Sdyson} 60013907Sdyson 60113907Sdyson/* 60213907Sdyson * This implements the pipe buffer write mechanism. Note that only 60313907Sdyson * a direct write OR a normal pipe write can be pending at any given time. 60413907Sdyson * If there are any characters in the pipe buffer, the direct write will 60513907Sdyson * be deferred until the receiving process grabs all of the bytes from 60613907Sdyson * the pipe buffer. Then the direct mapping write is set-up. 60713907Sdyson */ 60813907Sdysonstatic int 60913907Sdysonpipe_direct_write(wpipe, uio) 61013907Sdyson struct pipe *wpipe; 61113907Sdyson struct uio *uio; 61213907Sdyson{ 61313907Sdyson int error; 61413951Sdysonretry: 61513907Sdyson while (wpipe->pipe_state & PIPE_DIRECTW) { 61613951Sdyson if ( wpipe->pipe_state & PIPE_WANTR) { 61713951Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 61813951Sdyson wakeup(wpipe); 61913951Sdyson } 62013992Sdyson wpipe->pipe_state |= PIPE_WANTW; 62113907Sdyson error = tsleep(wpipe, 62213907Sdyson PRIBIO|PCATCH, "pipdww", 0); 62314802Sdyson if (error) 62413907Sdyson goto error1; 62514802Sdyson if (wpipe->pipe_state & PIPE_EOF) { 62614802Sdyson error = EPIPE; 62714802Sdyson goto error1; 62814802Sdyson } 62913907Sdyson } 63013907Sdyson wpipe->pipe_map.cnt = 0; /* transfer not ready yet */ 63113951Sdyson if (wpipe->pipe_buffer.cnt > 0) { 63213951Sdyson if ( wpipe->pipe_state & PIPE_WANTR) { 63313951Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 63413951Sdyson wakeup(wpipe); 63513951Sdyson } 63613951Sdyson 63713992Sdyson wpipe->pipe_state |= PIPE_WANTW; 63813907Sdyson error = tsleep(wpipe, 63913907Sdyson PRIBIO|PCATCH, "pipdwc", 0); 64014802Sdyson if (error) 64113907Sdyson goto error1; 64214802Sdyson if (wpipe->pipe_state & PIPE_EOF) { 64314802Sdyson error = EPIPE; 64414802Sdyson goto error1; 64513907Sdyson } 64613951Sdyson goto retry; 64713907Sdyson } 64813907Sdyson 64913951Sdyson wpipe->pipe_state |= PIPE_DIRECTW; 65013951Sdyson 65113907Sdyson error = pipe_build_write_buffer(wpipe, uio); 65213907Sdyson if (error) { 65313907Sdyson wpipe->pipe_state &= ~PIPE_DIRECTW; 65413907Sdyson goto error1; 65513907Sdyson } 65613907Sdyson 65713907Sdyson error = 0; 65813907Sdyson while (!error && (wpipe->pipe_state & PIPE_DIRECTW)) { 65913907Sdyson if (wpipe->pipe_state & PIPE_EOF) { 66013907Sdyson pipelock(wpipe, 0); 66113907Sdyson pipe_destroy_write_buffer(wpipe); 66213907Sdyson pipeunlock(wpipe); 66314037Sdyson pipeselwakeup(wpipe); 66414802Sdyson error = EPIPE; 66514802Sdyson goto error1; 66613907Sdyson } 66713992Sdyson if (wpipe->pipe_state & PIPE_WANTR) { 66813992Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 66913992Sdyson wakeup(wpipe); 67013992Sdyson } 67114037Sdyson pipeselwakeup(wpipe); 67213907Sdyson error = tsleep(wpipe, PRIBIO|PCATCH, "pipdwt", 0); 67313907Sdyson } 67413907Sdyson 67513907Sdyson pipelock(wpipe,0); 67613907Sdyson if (wpipe->pipe_state & PIPE_DIRECTW) { 67713907Sdyson /* 67813907Sdyson * this bit of trickery substitutes a kernel buffer for 67913907Sdyson * the process that might be going away. 68013907Sdyson */ 68113907Sdyson pipe_clone_write_buffer(wpipe); 68213907Sdyson } else { 68313907Sdyson pipe_destroy_write_buffer(wpipe); 68413907Sdyson } 68513907Sdyson pipeunlock(wpipe); 68613907Sdyson return error; 68713907Sdyson 68813907Sdysonerror1: 68913907Sdyson wakeup(wpipe); 69013907Sdyson return error; 69113907Sdyson} 69214037Sdyson#endif 69313907Sdyson 69416960Sdysonstatic int 69516960Sdysonpipe_write(fp, uio, cred) 69616960Sdyson struct file *fp; 69713907Sdyson struct uio *uio; 69816960Sdyson struct ucred *cred; 69913907Sdyson{ 70013675Sdyson int error = 0; 70113913Sdyson int orig_resid; 70213675Sdyson 70316960Sdyson struct pipe *wpipe, *rpipe; 70416960Sdyson 70516960Sdyson rpipe = (struct pipe *) fp->f_data; 70616960Sdyson wpipe = rpipe->pipe_peer; 70716960Sdyson 70813675Sdyson /* 70913675Sdyson * detect loss of pipe read side, issue SIGPIPE if lost. 71013675Sdyson */ 71116960Sdyson if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) { 71213774Sdyson return EPIPE; 71313675Sdyson } 71413675Sdyson 71517163Sdyson /* 71617163Sdyson * If it is advantageous to resize the pipe buffer, do 71717163Sdyson * so. 71817163Sdyson */ 71917163Sdyson if ((uio->uio_resid > PIPE_SIZE) && 72017163Sdyson (nbigpipe < LIMITBIGPIPES) && 72117163Sdyson (wpipe->pipe_state & PIPE_DIRECTW) == 0 && 72217163Sdyson (wpipe->pipe_buffer.size <= PIPE_SIZE) && 72317163Sdyson (wpipe->pipe_buffer.cnt == 0)) { 72417163Sdyson 72517163Sdyson if (wpipe->pipe_buffer.buffer) { 72617163Sdyson amountpipekva -= wpipe->pipe_buffer.size; 72717163Sdyson kmem_free(kernel_map, 72817163Sdyson (vm_offset_t)wpipe->pipe_buffer.buffer, 72917163Sdyson wpipe->pipe_buffer.size); 73017163Sdyson } 73117163Sdyson 73217163Sdyson#ifndef PIPE_NODIRECT 73317163Sdyson if (wpipe->pipe_map.kva) { 73417163Sdyson amountpipekva -= wpipe->pipe_buffer.size + PAGE_SIZE; 73517163Sdyson kmem_free(kernel_map, 73617163Sdyson wpipe->pipe_map.kva, 73717163Sdyson wpipe->pipe_buffer.size + PAGE_SIZE); 73817163Sdyson } 73917163Sdyson#endif 74017163Sdyson 74117163Sdyson wpipe->pipe_buffer.in = 0; 74217163Sdyson wpipe->pipe_buffer.out = 0; 74317163Sdyson wpipe->pipe_buffer.cnt = 0; 74417163Sdyson wpipe->pipe_buffer.size = BIG_PIPE_SIZE; 74517163Sdyson wpipe->pipe_buffer.buffer = NULL; 74617163Sdyson ++nbigpipe; 74717163Sdyson 74817163Sdyson#ifndef PIPE_NODIRECT 74917163Sdyson wpipe->pipe_map.cnt = 0; 75017163Sdyson wpipe->pipe_map.kva = 0; 75117163Sdyson wpipe->pipe_map.pos = 0; 75217163Sdyson wpipe->pipe_map.npages = 0; 75317163Sdyson#endif 75417163Sdyson 75517163Sdyson } 75617163Sdyson 75717163Sdyson 75813907Sdyson if( wpipe->pipe_buffer.buffer == NULL) { 75913907Sdyson if ((error = pipelock(wpipe,1)) == 0) { 76013907Sdyson pipespace(wpipe); 76113907Sdyson pipeunlock(wpipe); 76213907Sdyson } else { 76313907Sdyson return error; 76413907Sdyson } 76513907Sdyson } 76613907Sdyson 76713675Sdyson ++wpipe->pipe_busy; 76813913Sdyson orig_resid = uio->uio_resid; 76913675Sdyson while (uio->uio_resid) { 77013907Sdyson int space; 77114037Sdyson#ifndef PIPE_NODIRECT 77213907Sdyson /* 77313907Sdyson * If the transfer is large, we can gain performance if 77413907Sdyson * we do process-to-process copies directly. 77516416Sdyson * If the write is non-blocking, we don't use the 77616416Sdyson * direct write mechanism. 77713907Sdyson */ 77817163Sdyson if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) && 77917163Sdyson (fp->f_flag & FNONBLOCK) == 0 && 78017163Sdyson (wpipe->pipe_map.kva || (amountpipekva < LIMITPIPEKVA)) && 78113907Sdyson (uio->uio_iov->iov_len >= PIPE_MINDIRECT)) { 78213907Sdyson error = pipe_direct_write( wpipe, uio); 78313907Sdyson if (error) { 78413907Sdyson break; 78513907Sdyson } 78613907Sdyson continue; 78713907Sdyson } 78814037Sdyson#endif 78913907Sdyson 79013907Sdyson /* 79113907Sdyson * Pipe buffered writes cannot be coincidental with 79213907Sdyson * direct writes. We wait until the currently executing 79313907Sdyson * direct write is completed before we start filling the 79413907Sdyson * pipe buffer. 79513907Sdyson */ 79613907Sdyson retrywrite: 79713907Sdyson while (wpipe->pipe_state & PIPE_DIRECTW) { 79813992Sdyson if (wpipe->pipe_state & PIPE_WANTR) { 79913992Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 80013992Sdyson wakeup(wpipe); 80113992Sdyson } 80213907Sdyson error = tsleep(wpipe, 80313907Sdyson PRIBIO|PCATCH, "pipbww", 0); 80413907Sdyson if (error) 80513907Sdyson break; 80613907Sdyson } 80713907Sdyson 80813907Sdyson space = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt; 80914644Sdyson 81014644Sdyson /* Writes of size <= PIPE_BUF must be atomic. */ 81114644Sdyson /* XXX perhaps they need to be contiguous to be atomic? */ 81213913Sdyson if ((space < uio->uio_resid) && (orig_resid <= PIPE_BUF)) 81313913Sdyson space = 0; 81413907Sdyson 81517163Sdyson if (space > 0 && (wpipe->pipe_buffer.cnt < PIPE_SIZE)) { 81617163Sdyson /* 81717163Sdyson * This set the maximum transfer as a segment of 81817163Sdyson * the buffer. 81917163Sdyson */ 82013675Sdyson int size = wpipe->pipe_buffer.size - wpipe->pipe_buffer.in; 82117163Sdyson /* 82217163Sdyson * space is the size left in the buffer 82317163Sdyson */ 82413675Sdyson if (size > space) 82513675Sdyson size = space; 82617163Sdyson /* 82717163Sdyson * now limit it to the size of the uio transfer 82817163Sdyson */ 82913675Sdyson if (size > uio->uio_resid) 83013675Sdyson size = uio->uio_resid; 83113907Sdyson if ((error = pipelock(wpipe,1)) == 0) { 83213907Sdyson /* 83313907Sdyson * It is possible for a direct write to 83413907Sdyson * slip in on us... handle it here... 83513907Sdyson */ 83613907Sdyson if (wpipe->pipe_state & PIPE_DIRECTW) { 83713907Sdyson pipeunlock(wpipe); 83813907Sdyson goto retrywrite; 83913907Sdyson } 84013675Sdyson error = uiomove( &wpipe->pipe_buffer.buffer[wpipe->pipe_buffer.in], 84113675Sdyson size, uio); 84213675Sdyson pipeunlock(wpipe); 84313675Sdyson } 84413675Sdyson if (error) 84513675Sdyson break; 84613675Sdyson 84713675Sdyson wpipe->pipe_buffer.in += size; 84813675Sdyson if (wpipe->pipe_buffer.in >= wpipe->pipe_buffer.size) 84913675Sdyson wpipe->pipe_buffer.in = 0; 85013675Sdyson 85113675Sdyson wpipe->pipe_buffer.cnt += size; 85213675Sdyson } else { 85313675Sdyson /* 85413675Sdyson * If the "read-side" has been blocked, wake it up now. 85513675Sdyson */ 85613675Sdyson if (wpipe->pipe_state & PIPE_WANTR) { 85713675Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 85813675Sdyson wakeup(wpipe); 85913675Sdyson } 86014037Sdyson 86113675Sdyson /* 86213675Sdyson * don't block on non-blocking I/O 86313675Sdyson */ 86416960Sdyson if (fp->f_flag & FNONBLOCK) { 86513907Sdyson error = EAGAIN; 86613675Sdyson break; 86713675Sdyson } 86813907Sdyson 86914037Sdyson /* 87014037Sdyson * We have no more space and have something to offer, 87114037Sdyson * wake up selects. 87214037Sdyson */ 87314037Sdyson pipeselwakeup(wpipe); 87414037Sdyson 87513675Sdyson wpipe->pipe_state |= PIPE_WANTW; 87613776Sdyson if (error = tsleep(wpipe, (PRIBIO+1)|PCATCH, "pipewr", 0)) { 87713675Sdyson break; 87813675Sdyson } 87913675Sdyson /* 88013675Sdyson * If read side wants to go away, we just issue a signal 88113675Sdyson * to ourselves. 88213675Sdyson */ 88313675Sdyson if (wpipe->pipe_state & PIPE_EOF) { 88413774Sdyson error = EPIPE; 88513907Sdyson break; 88613675Sdyson } 88713675Sdyson } 88813675Sdyson } 88913675Sdyson 89014644Sdyson --wpipe->pipe_busy; 89113675Sdyson if ((wpipe->pipe_busy == 0) && 89213675Sdyson (wpipe->pipe_state & PIPE_WANT)) { 89313675Sdyson wpipe->pipe_state &= ~(PIPE_WANT|PIPE_WANTR); 89413675Sdyson wakeup(wpipe); 89513675Sdyson } else if (wpipe->pipe_buffer.cnt > 0) { 89613675Sdyson /* 89713675Sdyson * If we have put any characters in the buffer, we wake up 89813675Sdyson * the reader. 89913675Sdyson */ 90013675Sdyson if (wpipe->pipe_state & PIPE_WANTR) { 90113675Sdyson wpipe->pipe_state &= ~PIPE_WANTR; 90213675Sdyson wakeup(wpipe); 90313675Sdyson } 90413675Sdyson } 90513909Sdyson 90613909Sdyson /* 90713909Sdyson * Don't return EPIPE if I/O was successful 90813909Sdyson */ 90913907Sdyson if ((wpipe->pipe_buffer.cnt == 0) && 91013907Sdyson (uio->uio_resid == 0) && 91113907Sdyson (error == EPIPE)) 91213907Sdyson error = 0; 91313913Sdyson 91424101Sbde if (error == 0) 91524101Sbde gettime(&wpipe->pipe_mtime); 91624101Sbde 91714037Sdyson /* 91814037Sdyson * We have something to offer, 91914037Sdyson * wake up select. 92014037Sdyson */ 92114177Sdyson if (wpipe->pipe_buffer.cnt) 92214037Sdyson pipeselwakeup(wpipe); 92313907Sdyson 92413675Sdyson return error; 92513675Sdyson} 92613675Sdyson 92713675Sdyson/* 92813675Sdyson * we implement a very minimal set of ioctls for compatibility with sockets. 92913675Sdyson */ 93013675Sdysonint 93113675Sdysonpipe_ioctl(fp, cmd, data, p) 93213675Sdyson struct file *fp; 93313675Sdyson int cmd; 93413675Sdyson register caddr_t data; 93513675Sdyson struct proc *p; 93613675Sdyson{ 93713675Sdyson register struct pipe *mpipe = (struct pipe *)fp->f_data; 93813675Sdyson 93913675Sdyson switch (cmd) { 94013675Sdyson 94113675Sdyson case FIONBIO: 94213675Sdyson return (0); 94313675Sdyson 94413675Sdyson case FIOASYNC: 94513675Sdyson if (*(int *)data) { 94613675Sdyson mpipe->pipe_state |= PIPE_ASYNC; 94713675Sdyson } else { 94813675Sdyson mpipe->pipe_state &= ~PIPE_ASYNC; 94913675Sdyson } 95013675Sdyson return (0); 95113675Sdyson 95213675Sdyson case FIONREAD: 95314037Sdyson if (mpipe->pipe_state & PIPE_DIRECTW) 95414037Sdyson *(int *)data = mpipe->pipe_map.cnt; 95514037Sdyson else 95614037Sdyson *(int *)data = mpipe->pipe_buffer.cnt; 95713675Sdyson return (0); 95813675Sdyson 95918863Sdyson case TIOCSPGRP: 96013675Sdyson mpipe->pipe_pgid = *(int *)data; 96113675Sdyson return (0); 96213675Sdyson 96318863Sdyson case TIOCGPGRP: 96413675Sdyson *(int *)data = mpipe->pipe_pgid; 96513675Sdyson return (0); 96613675Sdyson 96713675Sdyson } 96817124Sbde return (ENOTTY); 96913675Sdyson} 97013675Sdyson 97113675Sdysonint 97213675Sdysonpipe_select(fp, which, p) 97313675Sdyson struct file *fp; 97413675Sdyson int which; 97513675Sdyson struct proc *p; 97613675Sdyson{ 97713675Sdyson register struct pipe *rpipe = (struct pipe *)fp->f_data; 97813675Sdyson struct pipe *wpipe; 97913675Sdyson 98013675Sdyson wpipe = rpipe->pipe_peer; 98113675Sdyson switch (which) { 98213675Sdyson 98313675Sdyson case FREAD: 98414177Sdyson if ( (rpipe->pipe_state & PIPE_DIRECTW) || 98514177Sdyson (rpipe->pipe_buffer.cnt > 0) || 98613907Sdyson (rpipe->pipe_state & PIPE_EOF)) { 98713675Sdyson return (1); 98813675Sdyson } 98913675Sdyson selrecord(p, &rpipe->pipe_sel); 99013675Sdyson rpipe->pipe_state |= PIPE_SEL; 99113675Sdyson break; 99213675Sdyson 99313675Sdyson case FWRITE: 99413907Sdyson if ((wpipe == NULL) || 99513907Sdyson (wpipe->pipe_state & PIPE_EOF) || 99614177Sdyson (((wpipe->pipe_state & PIPE_DIRECTW) == 0) && 99714177Sdyson (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF)) { 99813675Sdyson return (1); 99913675Sdyson } 100013675Sdyson selrecord(p, &wpipe->pipe_sel); 100113675Sdyson wpipe->pipe_state |= PIPE_SEL; 100213675Sdyson break; 100313675Sdyson 100413675Sdyson case 0: 100513907Sdyson if ((rpipe->pipe_state & PIPE_EOF) || 100613907Sdyson (wpipe == NULL) || 100713907Sdyson (wpipe->pipe_state & PIPE_EOF)) { 100813907Sdyson return (1); 100913907Sdyson } 101013907Sdyson 101113675Sdyson selrecord(p, &rpipe->pipe_sel); 101213675Sdyson rpipe->pipe_state |= PIPE_SEL; 101313675Sdyson break; 101413675Sdyson } 101513675Sdyson return (0); 101613675Sdyson} 101713675Sdyson 101813675Sdysonint 101913675Sdysonpipe_stat(pipe, ub) 102013675Sdyson register struct pipe *pipe; 102113675Sdyson register struct stat *ub; 102213675Sdyson{ 102313675Sdyson bzero((caddr_t)ub, sizeof (*ub)); 102417124Sbde ub->st_mode = S_IFIFO; 102513907Sdyson ub->st_blksize = pipe->pipe_buffer.size; 102613675Sdyson ub->st_size = pipe->pipe_buffer.cnt; 102713675Sdyson ub->st_blocks = (ub->st_size + ub->st_blksize - 1) / ub->st_blksize; 102813675Sdyson TIMEVAL_TO_TIMESPEC(&pipe->pipe_atime, &ub->st_atimespec); 102913675Sdyson TIMEVAL_TO_TIMESPEC(&pipe->pipe_mtime, &ub->st_mtimespec); 103013675Sdyson TIMEVAL_TO_TIMESPEC(&pipe->pipe_ctime, &ub->st_ctimespec); 103117124Sbde /* 103217124Sbde * Left as 0: st_dev, st_ino, st_nlink, st_uid, st_gid, st_rdev, 103317124Sbde * st_flags, st_gen. 103417124Sbde * XXX (st_dev, st_ino) should be unique. 103517124Sbde */ 103613675Sdyson return 0; 103713675Sdyson} 103813675Sdyson 103913675Sdyson/* ARGSUSED */ 104013675Sdysonstatic int 104113675Sdysonpipe_close(fp, p) 104213675Sdyson struct file *fp; 104313675Sdyson struct proc *p; 104413675Sdyson{ 104513675Sdyson struct pipe *cpipe = (struct pipe *)fp->f_data; 104616322Sgpalmer 104713675Sdyson pipeclose(cpipe); 104813675Sdyson fp->f_data = NULL; 104913675Sdyson return 0; 105013675Sdyson} 105113675Sdyson 105213675Sdyson/* 105313675Sdyson * shutdown the pipe 105413675Sdyson */ 105513675Sdysonstatic void 105613675Sdysonpipeclose(cpipe) 105713675Sdyson struct pipe *cpipe; 105813675Sdyson{ 105913907Sdyson struct pipe *ppipe; 106013675Sdyson if (cpipe) { 106113907Sdyson 106214037Sdyson pipeselwakeup(cpipe); 106313907Sdyson 106413675Sdyson /* 106513675Sdyson * If the other side is blocked, wake it up saying that 106613675Sdyson * we want to close it down. 106713675Sdyson */ 106813675Sdyson while (cpipe->pipe_busy) { 106913675Sdyson wakeup(cpipe); 107013675Sdyson cpipe->pipe_state |= PIPE_WANT|PIPE_EOF; 107113675Sdyson tsleep(cpipe, PRIBIO, "pipecl", 0); 107213675Sdyson } 107313675Sdyson 107413675Sdyson /* 107513675Sdyson * Disconnect from peer 107613675Sdyson */ 107713907Sdyson if (ppipe = cpipe->pipe_peer) { 107814037Sdyson pipeselwakeup(ppipe); 107913907Sdyson 108013907Sdyson ppipe->pipe_state |= PIPE_EOF; 108113907Sdyson wakeup(ppipe); 108213907Sdyson ppipe->pipe_peer = NULL; 108313675Sdyson } 108413675Sdyson 108513675Sdyson /* 108613675Sdyson * free resources 108713675Sdyson */ 108813907Sdyson if (cpipe->pipe_buffer.buffer) { 108917163Sdyson if (cpipe->pipe_buffer.size > PIPE_SIZE) 109017163Sdyson --nbigpipe; 109113907Sdyson amountpipekva -= cpipe->pipe_buffer.size; 109213907Sdyson kmem_free(kernel_map, 109313907Sdyson (vm_offset_t)cpipe->pipe_buffer.buffer, 109413907Sdyson cpipe->pipe_buffer.size); 109513907Sdyson } 109614037Sdyson#ifndef PIPE_NODIRECT 109713907Sdyson if (cpipe->pipe_map.kva) { 109813912Sdyson amountpipekva -= cpipe->pipe_buffer.size + PAGE_SIZE; 109913907Sdyson kmem_free(kernel_map, 110013907Sdyson cpipe->pipe_map.kva, 110113912Sdyson cpipe->pipe_buffer.size + PAGE_SIZE); 110213907Sdyson } 110314037Sdyson#endif 110413675Sdyson free(cpipe, M_TEMP); 110513675Sdyson } 110613675Sdyson} 110713675Sdyson#endif 1108