1 #include "types.h" 2 #include "defs.h" 3 #include "param.h" 4 #include "mmu.h" 5 #include "proc.h" 6 #include "fs.h" 7 #include "spinlock.h" 8 #include "sleeplock.h" 9 #include "file.h" 10 11 #define PIPESIZE 512 12 13 struct pipe { 14 struct spinlock lock; 15 char data[PIPESIZE]; 16 uint nread; // number of bytes read 17 uint nwrite; // number of bytes written 18 int readopen; // read fd is still open 19 int writeopen; // write fd is still open 20 }; 21 22 int 23 pipealloc(struct file **f0, struct file **f1) 24 { 25 struct pipe *p; 26 27 p = 0; 28 *f0 = *f1 = 0; 29 if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) 30 goto bad; 31 if((p = (struct pipe*)kalloc()) == 0) 32 goto bad; 33 p->readopen = 1; 34 p->writeopen = 1; 35 p->nwrite = 0; 36 p->nread = 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 48 //PAGEBREAK: 20 49 bad: 50 if(p) 51 kfree((char*)p); 52 if(*f0) 53 fileclose(*f0); 54 if(*f1) 55 fileclose(*f1); 56 return -1; 57 } 58 59 void 60 pipeclose(struct pipe *p, int writable) 61 { 62 acquire(&p->lock); 63 if(writable){ 64 p->writeopen = 0; 65 wakeup(&p->nread); 66 } else { 67 p->readopen = 0; 68 wakeup(&p->nwrite); 69 } 70 if(p->readopen == 0 && p->writeopen == 0){ 71 release(&p->lock); 72 kfree((char*)p); 73 } else 74 release(&p->lock); 75 } 76 77 //PAGEBREAK: 40 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->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full 86 if(p->readopen == 0 || proc->killed){ 87 release(&p->lock); 88 return -1; 89 } 90 wakeup(&p->nread); 91 sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep 92 } 93 p->data[p->nwrite++ % PIPESIZE] = addr[i]; 94 } 95 wakeup(&p->nread); //DOC: pipewrite-wakeup1 96 release(&p->lock); 97 return n; 98 } 99 100 int 101 piperead(struct pipe *p, char *addr, int n) 102 { 103 int i; 104 105 acquire(&p->lock); 106 while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty 107 if(proc->killed){ 108 release(&p->lock); 109 return -1; 110 } 111 sleep(&p->nread, &p->lock); //DOC: piperead-sleep 112 } 113 for(i = 0; i < n; i++){ //DOC: piperead-copy 114 if(p->nread == p->nwrite) 115 break; 116 addr[i] = p->data[p->nread++ % PIPESIZE]; 117 } 118 wakeup(&p->nwrite); //DOC: piperead-wakeup 119 release(&p->lock); 120 return i; 121 } 122