diff options
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; +} |