xref: /xv6-public/pipe.c (revision 6eed1ee9)
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 {
12c41f1de5Srtm   int readopen;   // read fd is still open
13c41f1de5Srtm   int writeopen;  // write fd is still open
14c41f1de5Srtm   int writep;     // next index to write
15c41f1de5Srtm   int readp;      // next index to read
164e8f237bSrtm   struct spinlock lock;
17c41f1de5Srtm   char data[PIPESIZE];
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;
338b4e2a08Srtm   p->writep = 0;
348b4e2a08Srtm   p->readp = 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 
46*6eed1ee9Srsc //PAGEBREAK: 20
473ce16470Srsc  bad:
48c41f1de5Srtm   if(p)
49c41f1de5Srtm     kfree((char*)p, PAGE);
502cbb4b18Srsc   if(*f0){
512cbb4b18Srsc     (*f0)->type = FD_NONE;
522cbb4b18Srsc     fileclose(*f0);
53c41f1de5Srtm   }
542cbb4b18Srsc   if(*f1){
552cbb4b18Srsc     (*f1)->type = FD_NONE;
562cbb4b18Srsc     fileclose(*f1);
57c41f1de5Srtm   }
58c41f1de5Srtm   return -1;
59c41f1de5Srtm }
60c41f1de5Srtm 
61c41f1de5Srtm void
627834cca6Srsc pipeclose(struct pipe *p, int writable)
63c41f1de5Srtm {
64bd228a81Srtm   acquire(&p->lock);
65d4c64e5dSrsc   if(writable){
66c41f1de5Srtm     p->writeopen = 0;
678b4e2a08Srtm     wakeup(&p->readp);
688b4e2a08Srtm   } else {
69c41f1de5Srtm     p->readopen = 0;
708b4e2a08Srtm     wakeup(&p->writep);
718b4e2a08Srtm   }
72bd228a81Srtm   release(&p->lock);
73bd228a81Srtm 
74c41f1de5Srtm   if(p->readopen == 0 && p->writeopen == 0)
75c41f1de5Srtm     kfree((char*)p, PAGE);
76c41f1de5Srtm }
77c41f1de5Srtm 
78*6eed1ee9Srsc //PAGEBREAK: 30
79c41f1de5Srtm int
807834cca6Srsc pipewrite(struct pipe *p, char *addr, int n)
81c41f1de5Srtm {
82c41f1de5Srtm   int i;
83c41f1de5Srtm 
844e8f237bSrtm   acquire(&p->lock);
85c41f1de5Srtm   for(i = 0; i < n; i++){
86c41f1de5Srtm     while(((p->writep + 1) % PIPESIZE) == p->readp){
87b6095304Srsc       if(p->readopen == 0 || cp->killed){
884e8f237bSrtm         release(&p->lock);
8946bbd72fSrtm         return -1;
9046bbd72fSrtm       }
918b4e2a08Srtm       wakeup(&p->readp);
9246bbd72fSrtm       sleep(&p->writep, &p->lock);
93c41f1de5Srtm     }
94c41f1de5Srtm     p->data[p->writep] = addr[i];
95c41f1de5Srtm     p->writep = (p->writep + 1) % PIPESIZE;
96c41f1de5Srtm   }
978b4e2a08Srtm   wakeup(&p->readp);
98ea6e3709Srsc   release(&p->lock);
99c41f1de5Srtm   return i;
100c41f1de5Srtm }
101c41f1de5Srtm 
102c41f1de5Srtm int
1037834cca6Srsc piperead(struct pipe *p, char *addr, int n)
104c41f1de5Srtm {
105c41f1de5Srtm   int i;
106c41f1de5Srtm 
10746bbd72fSrtm   acquire(&p->lock);
1083ce16470Srsc   while(p->readp == p->writep && p->writeopen){
1093ce16470Srsc     if(cp->killed){
11046bbd72fSrtm       release(&p->lock);
1113ce16470Srsc       return -1;
11246bbd72fSrtm     }
11346bbd72fSrtm     sleep(&p->readp, &p->lock);
114c41f1de5Srtm   }
115c41f1de5Srtm   for(i = 0; i < n; i++){
116c41f1de5Srtm     if(p->readp == p->writep)
117c41f1de5Srtm       break;
118c41f1de5Srtm     addr[i] = p->data[p->readp];
119c41f1de5Srtm     p->readp = (p->readp + 1) % PIPESIZE;
120c41f1de5Srtm   }
1218b4e2a08Srtm   wakeup(&p->writep);
122ea6e3709Srsc   release(&p->lock);
123c41f1de5Srtm   return i;
124c41f1de5Srtm }
125