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