Mercurial > hg > Members > tobaru > CbC_xv6
diff src/pipe.cbc @ 52:214d21c891c7
rename to cbc
__ncode is not handled as interfaces
author | kono |
---|---|
date | Mon, 03 Jun 2019 18:12:44 +0900 |
parents | src/pipe.c@fb3e5a2f76c1 |
children | d5c4016c65b8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pipe.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -0,0 +1,201 @@ +#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 + +#define __ncode __code +# +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; +} + +__ncode cbc_piperead3(){ + struct pipe *p = proc->cbc_arg.cbc_console_arg.p; + int i = proc->cbc_arg.cbc_console_arg.i; + __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; + release(&p->lock); + + goto next(i); +} + +__ncode cbc_piperead2(){ + int i = proc->cbc_arg.cbc_console_arg.i; + int n = proc->cbc_arg.cbc_console_arg.n; + struct pipe *p = proc->cbc_arg.cbc_console_arg.p; + char *addr = proc->cbc_arg.cbc_console_arg.addr; + if (i < n && !(p->nread == p->nwrite)) { + addr[i] = p->data[p->nread++ % PIPESIZE]; + i ++; + proc->cbc_arg.cbc_console_arg.i = i; + proc->cbc_arg.cbc_console_arg.p = p; + proc->cbc_arg.cbc_console_arg.addr = addr; + goto cbc_piperead2(); + } + proc->cbc_arg.cbc_console_arg.p = p; + goto cbc_wakeup(&p->nwrite, cbc_piperead3); //DOC: piperead-wakeup +} + +__ncode cbc_piperead1(){ + struct pipe *p = proc->cbc_arg.cbc_console_arg.p; + __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; + if (p->nread == p->nwrite && p->writeopen){ + if(proc->killed){ + release(&p->lock); + goto next(-1); + } + proc->cbc_arg.cbc_console_arg.p = p; + goto cbc_sleep(&p->nread, &p->lock, cbc_piperead1); + } + int i = 0; + proc->cbc_arg.cbc_console_arg.i = i; + proc->cbc_arg.cbc_console_arg.p = p; + goto cbc_piperead2(); +} + +__ncode cbc_piperead(struct pipe *p, char *addr, int n, __code (*next)(int ret)) +{ + acquire(&p->lock); + proc->cbc_arg.cbc_console_arg.n = n; + proc->cbc_arg.cbc_console_arg.p = p; + proc->cbc_arg.cbc_console_arg.addr = addr; + proc->cbc_arg.cbc_console_arg.next = next; + goto cbc_piperead1(); +} + +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; +}