xref: /xv6-public/pipe.c (revision 5be0039c)
1c41f1de5Srtm #include "types.h"
2c41f1de5Srtm #include "param.h"
3c41f1de5Srtm #include "x86.h"
4c41f1de5Srtm #include "mmu.h"
5c41f1de5Srtm #include "proc.h"
6c41f1de5Srtm #include "defs.h"
7c41f1de5Srtm #include "fd.h"
84e8f237bSrtm #include "spinlock.h"
9c41f1de5Srtm 
10c41f1de5Srtm #define PIPESIZE 512
11c41f1de5Srtm 
12c41f1de5Srtm struct pipe {
13c41f1de5Srtm   int readopen; // read fd is still open
14c41f1de5Srtm   int writeopen; // write fd is still open
15c41f1de5Srtm   int writep; // next index to write
16c41f1de5Srtm   int readp;  // next index to read
174e8f237bSrtm   struct spinlock lock;
18c41f1de5Srtm   char data[PIPESIZE];
19c41f1de5Srtm };
20c41f1de5Srtm 
21c41f1de5Srtm int
22c41f1de5Srtm pipe_alloc(struct fd **fd1, struct fd **fd2)
23c41f1de5Srtm {
24c41f1de5Srtm   *fd1 = *fd2 = 0;
25c41f1de5Srtm   struct pipe *p = 0;
26c41f1de5Srtm 
27c41f1de5Srtm   if((*fd1 = fd_alloc()) == 0)
28c41f1de5Srtm     goto oops;
29c41f1de5Srtm   if((*fd2 = fd_alloc()) == 0)
30c41f1de5Srtm     goto oops;
31c41f1de5Srtm   if((p = (struct pipe *) kalloc(PAGE)) == 0)
32c41f1de5Srtm     goto oops;
338b4e2a08Srtm   p->readopen = 1;
348b4e2a08Srtm   p->writeopen = 1;
358b4e2a08Srtm   p->writep = 0;
368b4e2a08Srtm   p->readp = 0;
37*5be0039cSrtm   initlock(&p->lock, "pipe");
38c41f1de5Srtm   (*fd1)->type = FD_PIPE;
39c41f1de5Srtm   (*fd1)->readable = 1;
40c41f1de5Srtm   (*fd1)->writeable = 0;
41c41f1de5Srtm   (*fd1)->pipe = p;
42c41f1de5Srtm   (*fd2)->type = FD_PIPE;
43c41f1de5Srtm   (*fd2)->readable = 0;
44c41f1de5Srtm   (*fd2)->writeable = 1;
45c41f1de5Srtm   (*fd2)->pipe = p;
46c41f1de5Srtm   return 0;
47c41f1de5Srtm  oops:
48c41f1de5Srtm   if(p)
49c41f1de5Srtm     kfree((char *) p, PAGE);
50c41f1de5Srtm   if(*fd1){
51c41f1de5Srtm     (*fd1)->type = FD_NONE;
52c41f1de5Srtm     fd_close(*fd1);
53c41f1de5Srtm   }
54c41f1de5Srtm   if(*fd2){
55c41f1de5Srtm     (*fd2)->type = FD_NONE;
56c41f1de5Srtm     fd_close(*fd2);
57c41f1de5Srtm   }
58c41f1de5Srtm   return -1;
59c41f1de5Srtm }
60c41f1de5Srtm 
61c41f1de5Srtm void
62c41f1de5Srtm pipe_close(struct pipe *p, int writeable)
63c41f1de5Srtm {
64bd228a81Srtm   acquire(&p->lock);
65bd228a81Srtm 
668b4e2a08Srtm   if(writeable){
67c41f1de5Srtm     p->writeopen = 0;
688b4e2a08Srtm     wakeup(&p->readp);
698b4e2a08Srtm   } else {
70c41f1de5Srtm     p->readopen = 0;
718b4e2a08Srtm     wakeup(&p->writep);
728b4e2a08Srtm   }
73bd228a81Srtm 
74bd228a81Srtm   release(&p->lock);
75bd228a81Srtm 
76c41f1de5Srtm   if(p->readopen == 0 && p->writeopen == 0)
77c41f1de5Srtm     kfree((char *) p, PAGE);
78c41f1de5Srtm }
79c41f1de5Srtm 
80c41f1de5Srtm int
81c41f1de5Srtm pipe_write(struct pipe *p, char *addr, int n)
82c41f1de5Srtm {
83c41f1de5Srtm   int i;
84c41f1de5Srtm 
854e8f237bSrtm   acquire(&p->lock);
864e8f237bSrtm 
87c41f1de5Srtm   for(i = 0; i < n; i++){
88c41f1de5Srtm     while(((p->writep + 1) % PIPESIZE) == p->readp){
8946bbd72fSrtm       if(p->readopen == 0){
904e8f237bSrtm         release(&p->lock);
9146bbd72fSrtm         return -1;
9246bbd72fSrtm       }
938b4e2a08Srtm       wakeup(&p->readp);
9446bbd72fSrtm       sleep(&p->writep, &p->lock);
95c41f1de5Srtm     }
96c41f1de5Srtm     p->data[p->writep] = addr[i];
97c41f1de5Srtm     p->writep = (p->writep + 1) % PIPESIZE;
98c41f1de5Srtm   }
9946bbd72fSrtm 
1004e8f237bSrtm   release(&p->lock);
1018b4e2a08Srtm   wakeup(&p->readp);
102c41f1de5Srtm   return i;
103c41f1de5Srtm }
104c41f1de5Srtm 
105c41f1de5Srtm int
106c41f1de5Srtm pipe_read(struct pipe *p, char *addr, int n)
107c41f1de5Srtm {
108c41f1de5Srtm   int i;
109c41f1de5Srtm 
11046bbd72fSrtm   acquire(&p->lock);
11146bbd72fSrtm 
112c41f1de5Srtm   while(p->readp == p->writep){
11346bbd72fSrtm     if(p->writeopen == 0){
11446bbd72fSrtm       release(&p->lock);
115c41f1de5Srtm       return 0;
11646bbd72fSrtm     }
11746bbd72fSrtm     sleep(&p->readp, &p->lock);
118c41f1de5Srtm   }
119c41f1de5Srtm 
120c41f1de5Srtm   for(i = 0; i < n; i++){
121c41f1de5Srtm     if(p->readp == p->writep)
122c41f1de5Srtm       break;
123c41f1de5Srtm     addr[i] = p->data[p->readp];
124c41f1de5Srtm     p->readp = (p->readp + 1) % PIPESIZE;
125c41f1de5Srtm   }
12646bbd72fSrtm 
1274e8f237bSrtm   release(&p->lock);
1288b4e2a08Srtm   wakeup(&p->writep);
129c41f1de5Srtm   return i;
130c41f1de5Srtm }
131