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 *f0 = *f1 = 0; 25 struct pipe *p = 0; 26 27 if((*f0 = filealloc()) == 0) 28 goto oops; 29 if((*f1 = filealloc()) == 0) 30 goto oops; 31 if((p = (struct pipe*) kalloc(PAGE)) == 0) 32 goto oops; 33 p->readopen = 1; 34 p->writeopen = 1; 35 p->writep = 0; 36 p->readp = 0; 37 initlock(&p->lock, "pipe"); 38 (*f0)->type = FD_PIPE; 39 (*f0)->readable = 1; 40 (*f0)->writable = 0; 41 (*f0)->pipe = p; 42 (*f1)->type = FD_PIPE; 43 (*f1)->readable = 0; 44 (*f1)->writable = 1; 45 (*f1)->pipe = p; 46 return 0; 47 oops: 48 if(p) 49 kfree((char*) p, PAGE); 50 if(*f0){ 51 (*f0)->type = FD_NONE; 52 fileclose(*f0); 53 } 54 if(*f1){ 55 (*f1)->type = FD_NONE; 56 fileclose(*f1); 57 } 58 return -1; 59 } 60 61 void 62 pipe_close(struct pipe *p, int writable) 63 { 64 acquire(&p->lock); 65 66 if(writable){ 67 p->writeopen = 0; 68 wakeup(&p->readp); 69 } else { 70 p->readopen = 0; 71 wakeup(&p->writep); 72 } 73 74 release(&p->lock); 75 76 if(p->readopen == 0 && p->writeopen == 0) 77 kfree((char*) p, PAGE); 78 } 79 80 int 81 pipe_write(struct pipe *p, char *addr, int n) 82 { 83 int i; 84 85 acquire(&p->lock); 86 87 for(i = 0; i < n; i++){ 88 while(((p->writep + 1) % PIPESIZE) == p->readp){ 89 if(p->readopen == 0 || curproc[cpu()]->killed){ 90 release(&p->lock); 91 return -1; 92 } 93 wakeup(&p->readp); 94 sleep(&p->writep, &p->lock); 95 } 96 p->data[p->writep] = addr[i]; 97 p->writep = (p->writep + 1) % PIPESIZE; 98 } 99 100 release(&p->lock); 101 wakeup(&p->readp); 102 return i; 103 } 104 105 int 106 pipe_read(struct pipe *p, char *addr, int n) 107 { 108 int i; 109 110 acquire(&p->lock); 111 112 while(p->readp == p->writep){ 113 if(p->writeopen == 0 || curproc[cpu()]->killed){ 114 release(&p->lock); 115 return 0; 116 } 117 sleep(&p->readp, &p->lock); 118 } 119 120 for(i = 0; i < n; i++){ 121 if(p->readp == p->writep) 122 break; 123 addr[i] = p->data[p->readp]; 124 p->readp = (p->readp + 1) % PIPESIZE; 125 } 126 127 release(&p->lock); 128 wakeup(&p->writep); 129 return i; 130 } 131