xref: /xv6-public/pipe.c (revision abf847a0)
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