1c41f1de5Srtm #include "types.h" 2c41f1de5Srtm #include "param.h" 3c41f1de5Srtm #include "x86.h" 4c41f1de5Srtm #include "mmu.h" 5c41f1de5Srtm #include "proc.h" 6c41f1de5Srtm #include "defs.h" 7c41f1de5Srtm #include "fd.h" 84e8f237bSrtm #include "spinlock.h" 9c41f1de5Srtm 10c41f1de5Srtm #define PIPESIZE 512 11c41f1de5Srtm 12c41f1de5Srtm struct pipe { 13c41f1de5Srtm int readopen; // read fd is still open 14c41f1de5Srtm int writeopen; // write fd is still open 15c41f1de5Srtm int writep; // next index to write 16c41f1de5Srtm int readp; // next index to read 174e8f237bSrtm struct spinlock lock; 18c41f1de5Srtm char data[PIPESIZE]; 19c41f1de5Srtm }; 20c41f1de5Srtm 21c41f1de5Srtm int 22c41f1de5Srtm pipe_alloc(struct fd **fd1, struct fd **fd2) 23c41f1de5Srtm { 24c41f1de5Srtm *fd1 = *fd2 = 0; 25c41f1de5Srtm struct pipe *p = 0; 26c41f1de5Srtm 27c41f1de5Srtm if((*fd1 = fd_alloc()) == 0) 28c41f1de5Srtm goto oops; 29c41f1de5Srtm if((*fd2 = fd_alloc()) == 0) 30c41f1de5Srtm goto oops; 31c41f1de5Srtm if((p = (struct pipe *) kalloc(PAGE)) == 0) 32c41f1de5Srtm goto oops; 338b4e2a08Srtm p->readopen = 1; 348b4e2a08Srtm p->writeopen = 1; 358b4e2a08Srtm p->writep = 0; 368b4e2a08Srtm p->readp = 0; 37*5be0039cSrtm initlock(&p->lock, "pipe"); 38c41f1de5Srtm (*fd1)->type = FD_PIPE; 39c41f1de5Srtm (*fd1)->readable = 1; 40c41f1de5Srtm (*fd1)->writeable = 0; 41c41f1de5Srtm (*fd1)->pipe = p; 42c41f1de5Srtm (*fd2)->type = FD_PIPE; 43c41f1de5Srtm (*fd2)->readable = 0; 44c41f1de5Srtm (*fd2)->writeable = 1; 45c41f1de5Srtm (*fd2)->pipe = p; 46c41f1de5Srtm return 0; 47c41f1de5Srtm oops: 48c41f1de5Srtm if(p) 49c41f1de5Srtm kfree((char *) p, PAGE); 50c41f1de5Srtm if(*fd1){ 51c41f1de5Srtm (*fd1)->type = FD_NONE; 52c41f1de5Srtm fd_close(*fd1); 53c41f1de5Srtm } 54c41f1de5Srtm if(*fd2){ 55c41f1de5Srtm (*fd2)->type = FD_NONE; 56c41f1de5Srtm fd_close(*fd2); 57c41f1de5Srtm } 58c41f1de5Srtm return -1; 59c41f1de5Srtm } 60c41f1de5Srtm 61c41f1de5Srtm void 62c41f1de5Srtm pipe_close(struct pipe *p, int writeable) 63c41f1de5Srtm { 64bd228a81Srtm acquire(&p->lock); 65bd228a81Srtm 668b4e2a08Srtm if(writeable){ 67c41f1de5Srtm p->writeopen = 0; 688b4e2a08Srtm wakeup(&p->readp); 698b4e2a08Srtm } else { 70c41f1de5Srtm p->readopen = 0; 718b4e2a08Srtm wakeup(&p->writep); 728b4e2a08Srtm } 73bd228a81Srtm 74bd228a81Srtm release(&p->lock); 75bd228a81Srtm 76c41f1de5Srtm if(p->readopen == 0 && p->writeopen == 0) 77c41f1de5Srtm kfree((char *) p, PAGE); 78c41f1de5Srtm } 79c41f1de5Srtm 80c41f1de5Srtm int 81c41f1de5Srtm pipe_write(struct pipe *p, char *addr, int n) 82c41f1de5Srtm { 83c41f1de5Srtm int i; 84c41f1de5Srtm 854e8f237bSrtm acquire(&p->lock); 864e8f237bSrtm 87c41f1de5Srtm for(i = 0; i < n; i++){ 88c41f1de5Srtm while(((p->writep + 1) % PIPESIZE) == p->readp){ 8946bbd72fSrtm if(p->readopen == 0){ 904e8f237bSrtm release(&p->lock); 9146bbd72fSrtm return -1; 9246bbd72fSrtm } 938b4e2a08Srtm wakeup(&p->readp); 9446bbd72fSrtm sleep(&p->writep, &p->lock); 95c41f1de5Srtm } 96c41f1de5Srtm p->data[p->writep] = addr[i]; 97c41f1de5Srtm p->writep = (p->writep + 1) % PIPESIZE; 98c41f1de5Srtm } 9946bbd72fSrtm 1004e8f237bSrtm release(&p->lock); 1018b4e2a08Srtm wakeup(&p->readp); 102c41f1de5Srtm return i; 103c41f1de5Srtm } 104c41f1de5Srtm 105c41f1de5Srtm int 106c41f1de5Srtm pipe_read(struct pipe *p, char *addr, int n) 107c41f1de5Srtm { 108c41f1de5Srtm int i; 109c41f1de5Srtm 11046bbd72fSrtm acquire(&p->lock); 11146bbd72fSrtm 112c41f1de5Srtm while(p->readp == p->writep){ 11346bbd72fSrtm if(p->writeopen == 0){ 11446bbd72fSrtm release(&p->lock); 115c41f1de5Srtm return 0; 11646bbd72fSrtm } 11746bbd72fSrtm sleep(&p->readp, &p->lock); 118c41f1de5Srtm } 119c41f1de5Srtm 120c41f1de5Srtm for(i = 0; i < n; i++){ 121c41f1de5Srtm if(p->readp == p->writep) 122c41f1de5Srtm break; 123c41f1de5Srtm addr[i] = p->data[p->readp]; 124c41f1de5Srtm p->readp = (p->readp + 1) % PIPESIZE; 125c41f1de5Srtm } 12646bbd72fSrtm 1274e8f237bSrtm release(&p->lock); 1288b4e2a08Srtm wakeup(&p->writep); 129c41f1de5Srtm return i; 130c41f1de5Srtm } 131