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