Mercurial > hg > Members > anatofuz > CbC_xv6
diff src/pipe.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children | ad1d3b268e2d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pipe.c Fri May 26 23:11:05 2017 +0900 @@ -0,0 +1,146 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "mmu.h" +#include "proc.h" +#include "fs.h" +#include "file.h" +#include "spinlock.h" + +#define PIPESIZE 512 + +struct pipe { + struct spinlock lock; + char data[PIPESIZE]; + uint nread; // number of bytes read + uint nwrite; // number of bytes written + int readopen; // read fd is still open + int writeopen; // write fd is still open +}; + +int pipealloc(struct file **f0, struct file **f1) +{ + struct pipe *p; + + p = 0; + *f0 = *f1 = 0; + + if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) { + goto bad; + } + + if((p = kmalloc (get_order(sizeof(*p)))) == 0) { + goto bad; + } + + p->readopen = 1; + p->writeopen = 1; + p->nwrite = 0; + p->nread = 0; + + initlock(&p->lock, "pipe"); + + (*f0)->type = FD_PIPE; + (*f0)->readable = 1; + (*f0)->writable = 0; + (*f0)->pipe = p; + (*f1)->type = FD_PIPE; + (*f1)->readable = 0; + (*f1)->writable = 1; + (*f1)->pipe = p; + + return 0; + + //PAGEBREAK: 20 + bad: + if(p) { + kfree (p, get_order(sizeof*p)); + } + + if(*f0) { + fileclose(*f0); + } + + if(*f1) { + fileclose(*f1); + } + + return -1; +} + +void pipeclose(struct pipe *p, int writable) +{ + acquire(&p->lock); + + if(writable){ + p->writeopen = 0; + wakeup(&p->nread); + + } else { + p->readopen = 0; + wakeup(&p->nwrite); + } + + if(p->readopen == 0 && p->writeopen == 0){ + release(&p->lock); + kfree (p, get_order(sizeof(*p))); + + } else { + release(&p->lock); + } +} + +//PAGEBREAK: 40 +int pipewrite(struct pipe *p, char *addr, int n) +{ + int i; + + acquire(&p->lock); + + for(i = 0; i < n; i++){ + while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full + if(p->readopen == 0 /*|| proc->killed*/){ + release(&p->lock); + return -1; + } + + wakeup(&p->nread); + sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep + } + + p->data[p->nwrite++ % PIPESIZE] = addr[i]; + } + + wakeup(&p->nread); //DOC: pipewrite-wakeup1 + release(&p->lock); + return n; +} + +int piperead(struct pipe *p, char *addr, int n) +{ + int i; + + acquire(&p->lock); + + while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty + if(proc->killed){ + release(&p->lock); + return -1; + } + + sleep(&p->nread, &p->lock); //DOC: piperead-sleep*/ + } + + for(i = 0; i < n; i++){ //DOC: piperead-copy + if(p->nread == p->nwrite) { + break; + } + + addr[i] = p->data[p->nread++ % PIPESIZE]; + } + + wakeup(&p->nwrite); //DOC: piperead-wakeup + release(&p->lock); + + return i; +}