1 #include "types.h" 2 #include "param.h" 3 #include "x86.h" 4 #include "mmu.h" 5 #include "proc.h" 6 #include "defs.h" 7 #include "file.h" 8 #include "spinlock.h" 9 10 #define PIPESIZE 512 11 12 struct pipe { 13 int readopen; // read fd is still open 14 int writeopen; // write fd is still open 15 int writep; // next index to write 16 int readp; // next index to read 17 struct spinlock lock; 18 char data[PIPESIZE]; 19 }; 20 21 int 22 pipe_alloc(struct file **f0, struct file **f1) 23 { 24 struct pipe *p; 25 26 p = 0; 27 *f0 = *f1 = 0; 28 if((*f0 = filealloc()) == 0) 29 goto oops; 30 if((*f1 = filealloc()) == 0) 31 goto oops; 32 if((p = (struct pipe*) kalloc(PAGE)) == 0) 33 goto oops; 34 p->readopen = 1; 35 p->writeopen = 1; 36 p->writep = 0; 37 p->readp = 0; 38 initlock(&p->lock, "pipe"); 39 (*f0)->type = FD_PIPE; 40 (*f0)->readable = 1; 41 (*f0)->writable = 0; 42 (*f0)->pipe = p; 43 (*f1)->type = FD_PIPE; 44 (*f1)->readable = 0; 45 (*f1)->writable = 1; 46 (*f1)->pipe = p; 47 return 0; 48 49 oops: 50 if(p) 51 kfree((char*) p, PAGE); 52 if(*f0){ 53 (*f0)->type = FD_NONE; 54 fileclose(*f0); 55 } 56 if(*f1){ 57 (*f1)->type = FD_NONE; 58 fileclose(*f1); 59 } 60 return -1; 61 } 62 63 void 64 pipe_close(struct pipe *p, int writable) 65 { 66 acquire(&p->lock); 67 68 if(writable){ 69 p->writeopen = 0; 70 wakeup(&p->readp); 71 } else { 72 p->readopen = 0; 73 wakeup(&p->writep); 74 } 75 76 release(&p->lock); 77 78 if(p->readopen == 0 && p->writeopen == 0) 79 kfree((char*) p, PAGE); 80 } 81 82 //PAGEBREAK: 20 83 int 84 pipe_write(struct pipe *p, char *addr, int n) 85 { 86 int i; 87 88 acquire(&p->lock); 89 90 for(i = 0; i < n; i++){ 91 while(((p->writep + 1) % PIPESIZE) == p->readp){ 92 if(p->readopen == 0 || cp->killed){ 93 release(&p->lock); 94 return -1; 95 } 96 wakeup(&p->readp); 97 sleep(&p->writep, &p->lock); 98 } 99 p->data[p->writep] = addr[i]; 100 p->writep = (p->writep + 1) % PIPESIZE; 101 } 102 103 release(&p->lock); 104 wakeup(&p->readp); 105 return i; 106 } 107 108 int 109 pipe_read(struct pipe *p, char *addr, int n) 110 { 111 int i; 112 113 acquire(&p->lock); 114 115 while(p->readp == p->writep){ 116 if(p->writeopen == 0 || cp->killed){ 117 release(&p->lock); 118 return 0; 119 } 120 sleep(&p->readp, &p->lock); 121 } 122 for(i = 0; i < n; i++){ 123 if(p->readp == p->writep) 124 break; 125 addr[i] = p->data[p->readp]; 126 p->readp = (p->readp + 1) % PIPESIZE; 127 } 128 129 release(&p->lock); 130 wakeup(&p->writep); 131 return i; 132 } 133