1c41f1de5Srtm #include "types.h"
2558ab49fSrsc #include "defs.h"
3c41f1de5Srtm #include "param.h"
4c41f1de5Srtm #include "mmu.h"
5c41f1de5Srtm #include "proc.h"
60aef8914SRuss Cox #include "fs.h"
71ddfbbb1SFrans Kaashoek #include "spinlock.h"
8dec637bcSFrans Kaashoek #include "sleeplock.h"
9dec637bcSFrans Kaashoek #include "file.h"
10c41f1de5Srtm
11c41f1de5Srtm #define PIPESIZE 512
12c41f1de5Srtm
13c41f1de5Srtm struct pipe {
144e8f237bSrtm struct spinlock lock;
15c41f1de5Srtm char data[PIPESIZE];
1600e57115SRuss Cox uint nread; // number of bytes read
1700e57115SRuss Cox uint nwrite; // number of bytes written
1800e57115SRuss Cox int readopen; // read fd is still open
1900e57115SRuss Cox int writeopen; // write fd is still open
20c41f1de5Srtm };
21c41f1de5Srtm
22c41f1de5Srtm int
pipealloc(struct file ** f0,struct file ** f1)237834cca6Srsc pipealloc(struct file **f0, struct file **f1)
24c41f1de5Srtm {
253bbbaca1Srsc struct pipe *p;
26c41f1de5Srtm
273bbbaca1Srsc p = 0;
283bbbaca1Srsc *f0 = *f1 = 0;
293ce16470Srsc if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
303ce16470Srsc goto bad;
317d7dc933SRobert Morris if((p = (struct pipe*)kalloc()) == 0)
323ce16470Srsc goto bad;
338b4e2a08Srtm p->readopen = 1;
348b4e2a08Srtm p->writeopen = 1;
3500e57115SRuss Cox p->nwrite = 0;
3600e57115SRuss Cox p->nread = 0;
375be0039cSrtm initlock(&p->lock, "pipe");
382cbb4b18Srsc (*f0)->type = FD_PIPE;
392cbb4b18Srsc (*f0)->readable = 1;
402cbb4b18Srsc (*f0)->writable = 0;
412cbb4b18Srsc (*f0)->pipe = p;
422cbb4b18Srsc (*f1)->type = FD_PIPE;
432cbb4b18Srsc (*f1)->readable = 0;
442cbb4b18Srsc (*f1)->writable = 1;
452cbb4b18Srsc (*f1)->pipe = p;
46c41f1de5Srtm return 0;
47f1f8dd91Srsc
486eed1ee9Srsc //PAGEBREAK: 20
493ce16470Srsc bad:
50c41f1de5Srtm if(p)
517d7dc933SRobert Morris kfree((char*)p);
52f3685aa3Srsc if(*f0)
532cbb4b18Srsc fileclose(*f0);
54f3685aa3Srsc if(*f1)
552cbb4b18Srsc fileclose(*f1);
56c41f1de5Srtm return -1;
57c41f1de5Srtm }
58c41f1de5Srtm
59c41f1de5Srtm void
pipeclose(struct pipe * p,int writable)607834cca6Srsc pipeclose(struct pipe *p, int writable)
61c41f1de5Srtm {
62bd228a81Srtm acquire(&p->lock);
63d4c64e5dSrsc if(writable){
64c41f1de5Srtm p->writeopen = 0;
6500e57115SRuss Cox wakeup(&p->nread);
668b4e2a08Srtm } else {
67c41f1de5Srtm p->readopen = 0;
6800e57115SRuss Cox wakeup(&p->nwrite);
698b4e2a08Srtm }
70e670a483Skolya if(p->readopen == 0 && p->writeopen == 0){
71bd228a81Srtm release(&p->lock);
727d7dc933SRobert Morris kfree((char*)p);
73e670a483Skolya } else
74e670a483Skolya release(&p->lock);
75c41f1de5Srtm }
76c41f1de5Srtm
770aef8914SRuss Cox //PAGEBREAK: 40
78c41f1de5Srtm int
pipewrite(struct pipe * p,char * addr,int n)797834cca6Srsc pipewrite(struct pipe *p, char *addr, int n)
80c41f1de5Srtm {
81c41f1de5Srtm int i;
82c41f1de5Srtm
834e8f237bSrtm acquire(&p->lock);
84c41f1de5Srtm for(i = 0; i < n; i++){
8500e57115SRuss Cox while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full
86*abf847a0SFrans Kaashoek if(p->readopen == 0 || myproc()->killed){
874e8f237bSrtm release(&p->lock);
8846bbd72fSrtm return -1;
8946bbd72fSrtm }
9000e57115SRuss Cox wakeup(&p->nread);
9100e57115SRuss Cox sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep
92c41f1de5Srtm }
9300e57115SRuss Cox p->data[p->nwrite++ % PIPESIZE] = addr[i];
94c41f1de5Srtm }
9500e57115SRuss Cox wakeup(&p->nread); //DOC: pipewrite-wakeup1
96ea6e3709Srsc release(&p->lock);
9700e57115SRuss Cox return n;
98c41f1de5Srtm }
99c41f1de5Srtm
100c41f1de5Srtm int
piperead(struct pipe * p,char * addr,int n)1017834cca6Srsc piperead(struct pipe *p, char *addr, int n)
102c41f1de5Srtm {
103c41f1de5Srtm int i;
104c41f1de5Srtm
10546bbd72fSrtm acquire(&p->lock);
10600e57115SRuss Cox while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty
107*abf847a0SFrans Kaashoek if(myproc()->killed){
10846bbd72fSrtm release(&p->lock);
1093ce16470Srsc return -1;
11046bbd72fSrtm }
11100e57115SRuss Cox sleep(&p->nread, &p->lock); //DOC: piperead-sleep
112c41f1de5Srtm }
11300e57115SRuss Cox for(i = 0; i < n; i++){ //DOC: piperead-copy
11400e57115SRuss Cox if(p->nread == p->nwrite)
115c41f1de5Srtm break;
11600e57115SRuss Cox addr[i] = p->data[p->nread++ % PIPESIZE];
117c41f1de5Srtm }
11800e57115SRuss Cox wakeup(&p->nwrite); //DOC: piperead-wakeup
119ea6e3709Srsc release(&p->lock);
120c41f1de5Srtm return i;
121c41f1de5Srtm }
122