123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- #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 = (struct pipe*)kalloc()) == 0)
- goto bad;
- memset(p, 0, PGSIZE);
- 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((char*)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((char*)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 || curr_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(curr_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;
- }
|