diff options
author | rtm <rtm> | 2006-06-27 14:35:53 +0000 |
---|---|---|
committer | rtm <rtm> | 2006-06-27 14:35:53 +0000 |
commit | c41f1de5d41a527a3fa2d1e94215766130eac456 (patch) | |
tree | 86f6a467be8b42aec42a05299789f39ace9cc5e2 /pipe.c | |
parent | b61c2547b8b489cab16984c0940a1cb6593a2a3d (diff) | |
download | xv6-labs-c41f1de5d41a527a3fa2d1e94215766130eac456.tar.gz xv6-labs-c41f1de5d41a527a3fa2d1e94215766130eac456.tar.bz2 xv6-labs-c41f1de5d41a527a3fa2d1e94215766130eac456.zip |
file descriptors
pipes
Diffstat (limited to 'pipe.c')
-rw-r--r-- | pipe.c | 100 |
1 files changed, 100 insertions, 0 deletions
@@ -0,0 +1,100 @@ +#include "types.h" +#include "param.h" +#include "x86.h" +#include "mmu.h" +#include "proc.h" +#include "defs.h" +#include "fd.h" + +#define PIPESIZE 512 + +struct pipe { + int readopen; // read fd is still open + int writeopen; // write fd is still open + int writep; // next index to write + int readp; // next index to read + char data[PIPESIZE]; +}; + +int +pipe_alloc(struct fd **fd1, struct fd **fd2) +{ + *fd1 = *fd2 = 0; + struct pipe *p = 0; + + if((*fd1 = fd_alloc()) == 0) + goto oops; + if((*fd2 = fd_alloc()) == 0) + goto oops; + if((p = (struct pipe *) kalloc(PAGE)) == 0) + goto oops; + (*fd1)->type = FD_PIPE; + (*fd1)->readable = 1; + (*fd1)->writeable = 0; + (*fd1)->pipe = p; + (*fd2)->type = FD_PIPE; + (*fd2)->readable = 0; + (*fd2)->writeable = 1; + (*fd2)->pipe = p; + return 0; + oops: + if(p) + kfree((char *) p, PAGE); + if(*fd1){ + (*fd1)->type = FD_NONE; + fd_close(*fd1); + } + if(*fd2){ + (*fd2)->type = FD_NONE; + fd_close(*fd2); + } + return -1; +} + +void +pipe_close(struct pipe *p, int writeable) +{ + if(writeable) + p->writeopen = 0; + else + p->readopen = 0; + if(p->readopen == 0 && p->writeopen == 0) + kfree((char *) p, PAGE); +} + +int +pipe_write(struct pipe *p, char *addr, int n) +{ + int i; + + for(i = 0; i < n; i++){ + while(((p->writep + 1) % PIPESIZE) == p->readp){ + if(p->readopen == 0) + return -1; + sleep(&p->writep); + } + p->data[p->writep] = addr[i]; + p->writep = (p->writep + 1) % PIPESIZE; + } + return i; +} + +int +pipe_read(struct pipe *p, char *addr, int n) +{ + int i; + + while(p->readp == p->writep){ + if(p->writeopen == 0) + return 0; + sleep(&p->readp); + } + + for(i = 0; i < n; i++){ + if(p->readp == p->writep) + break; + addr[i] = p->data[p->readp]; + p->readp = (p->readp + 1) % PIPESIZE; + } + return i; +} |