xref: /xv6-public/pipe.c (revision 00e57115)
1c41f1de5Srtm #include "types.h"
2558ab49fSrsc #include "defs.h"
3c41f1de5Srtm #include "param.h"
4c41f1de5Srtm #include "mmu.h"
5c41f1de5Srtm #include "proc.h"
69936bffaSrsc #include "file.h"
74e8f237bSrtm #include "spinlock.h"
8c41f1de5Srtm 
9c41f1de5Srtm #define PIPESIZE 512
10c41f1de5Srtm 
11c41f1de5Srtm struct pipe {
124e8f237bSrtm   struct spinlock lock;
13c41f1de5Srtm   char data[PIPESIZE];
14*00e57115SRuss Cox   uint nread;     // number of bytes read
15*00e57115SRuss Cox   uint nwrite;    // number of bytes written
16*00e57115SRuss Cox   int readopen;   // read fd is still open
17*00e57115SRuss Cox   int writeopen;  // write fd is still open
18c41f1de5Srtm };
19c41f1de5Srtm 
20c41f1de5Srtm int
217834cca6Srsc pipealloc(struct file **f0, struct file **f1)
22c41f1de5Srtm {
233bbbaca1Srsc   struct pipe *p;
24c41f1de5Srtm 
253bbbaca1Srsc   p = 0;
263bbbaca1Srsc   *f0 = *f1 = 0;
273ce16470Srsc   if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
283ce16470Srsc     goto bad;
29c41f1de5Srtm   if((p = (struct pipe*)kalloc(PAGE)) == 0)
303ce16470Srsc     goto bad;
318b4e2a08Srtm   p->readopen = 1;
328b4e2a08Srtm   p->writeopen = 1;
33*00e57115SRuss Cox   p->nwrite = 0;
34*00e57115SRuss Cox   p->nread = 0;
355be0039cSrtm   initlock(&p->lock, "pipe");
362cbb4b18Srsc   (*f0)->type = FD_PIPE;
372cbb4b18Srsc   (*f0)->readable = 1;
382cbb4b18Srsc   (*f0)->writable = 0;
392cbb4b18Srsc   (*f0)->pipe = p;
402cbb4b18Srsc   (*f1)->type = FD_PIPE;
412cbb4b18Srsc   (*f1)->readable = 0;
422cbb4b18Srsc   (*f1)->writable = 1;
432cbb4b18Srsc   (*f1)->pipe = p;
44c41f1de5Srtm   return 0;
45f1f8dd91Srsc 
466eed1ee9Srsc //PAGEBREAK: 20
473ce16470Srsc  bad:
48c41f1de5Srtm   if(p)
49c41f1de5Srtm     kfree((char*)p, PAGE);
50f3685aa3Srsc   if(*f0)
512cbb4b18Srsc     fileclose(*f0);
52f3685aa3Srsc   if(*f1)
532cbb4b18Srsc     fileclose(*f1);
54c41f1de5Srtm   return -1;
55c41f1de5Srtm }
56c41f1de5Srtm 
57c41f1de5Srtm void
587834cca6Srsc pipeclose(struct pipe *p, int writable)
59c41f1de5Srtm {
60bd228a81Srtm   acquire(&p->lock);
61d4c64e5dSrsc   if(writable){
62c41f1de5Srtm     p->writeopen = 0;
63*00e57115SRuss Cox     wakeup(&p->nread);
648b4e2a08Srtm   } else {
65c41f1de5Srtm     p->readopen = 0;
66*00e57115SRuss Cox     wakeup(&p->nwrite);
678b4e2a08Srtm   }
68e670a483Skolya   if(p->readopen == 0 && p->writeopen == 0) {
69bd228a81Srtm     release(&p->lock);
70c41f1de5Srtm     kfree((char*)p, PAGE);
71e670a483Skolya   } else
72e670a483Skolya     release(&p->lock);
73c41f1de5Srtm }
74c41f1de5Srtm 
756eed1ee9Srsc //PAGEBREAK: 30
76c41f1de5Srtm int
777834cca6Srsc pipewrite(struct pipe *p, char *addr, int n)
78c41f1de5Srtm {
79c41f1de5Srtm   int i;
80c41f1de5Srtm 
814e8f237bSrtm   acquire(&p->lock);
82c41f1de5Srtm   for(i = 0; i < n; i++){
83*00e57115SRuss Cox     while(p->nwrite == p->nread + PIPESIZE) {  //DOC: pipewrite-full
84b6095304Srsc       if(p->readopen == 0 || cp->killed){
854e8f237bSrtm         release(&p->lock);
8646bbd72fSrtm         return -1;
8746bbd72fSrtm       }
88*00e57115SRuss Cox       wakeup(&p->nread);
89*00e57115SRuss Cox       sleep(&p->nwrite, &p->lock);  //DOC: pipewrite-sleep
90c41f1de5Srtm     }
91*00e57115SRuss Cox     p->data[p->nwrite++ % PIPESIZE] = addr[i];
92c41f1de5Srtm   }
93*00e57115SRuss Cox   wakeup(&p->nread);  //DOC: pipewrite-wakeup1
94ea6e3709Srsc   release(&p->lock);
95*00e57115SRuss Cox   return n;
96c41f1de5Srtm }
97c41f1de5Srtm 
98c41f1de5Srtm int
997834cca6Srsc piperead(struct pipe *p, char *addr, int n)
100c41f1de5Srtm {
101c41f1de5Srtm   int i;
102c41f1de5Srtm 
10346bbd72fSrtm   acquire(&p->lock);
104*00e57115SRuss Cox   while(p->nread == p->nwrite && p->writeopen){  //DOC: pipe-empty
1053ce16470Srsc     if(cp->killed){
10646bbd72fSrtm       release(&p->lock);
1073ce16470Srsc       return -1;
10846bbd72fSrtm     }
109*00e57115SRuss Cox     sleep(&p->nread, &p->lock); //DOC: piperead-sleep
110c41f1de5Srtm   }
111*00e57115SRuss Cox   for(i = 0; i < n; i++){  //DOC: piperead-copy
112*00e57115SRuss Cox     if(p->nread == p->nwrite)
113c41f1de5Srtm       break;
114*00e57115SRuss Cox     addr[i] = p->data[p->nread++ % PIPESIZE];
115c41f1de5Srtm   }
116*00e57115SRuss Cox   wakeup(&p->nwrite);  //DOC: piperead-wakeup
117ea6e3709Srsc   release(&p->lock);
118c41f1de5Srtm   return i;
119c41f1de5Srtm }
120