xref: /xv6-public/pipe.c (revision c41f1de5)
1 #include "types.h"
2 #include "param.h"
3 #include "x86.h"
4 #include "mmu.h"
5 #include "proc.h"
6 #include "defs.h"
7 #include "fd.h"
8 
9 #define PIPESIZE 512
10 
11 struct pipe {
12   int readopen; // read fd is still open
13   int writeopen; // write fd is still open
14   int writep; // next index to write
15   int readp;  // next index to read
16   char data[PIPESIZE];
17 };
18 
19 int
20 pipe_alloc(struct fd **fd1, struct fd **fd2)
21 {
22   *fd1 = *fd2 = 0;
23   struct pipe *p = 0;
24 
25   if((*fd1 = fd_alloc()) == 0)
26     goto oops;
27   if((*fd2 = fd_alloc()) == 0)
28     goto oops;
29   if((p = (struct pipe *) kalloc(PAGE)) == 0)
30     goto oops;
31   (*fd1)->type = FD_PIPE;
32   (*fd1)->readable = 1;
33   (*fd1)->writeable = 0;
34   (*fd1)->pipe = p;
35   (*fd2)->type = FD_PIPE;
36   (*fd2)->readable = 0;
37   (*fd2)->writeable = 1;
38   (*fd2)->pipe = p;
39   return 0;
40  oops:
41   if(p)
42     kfree((char *) p, PAGE);
43   if(*fd1){
44     (*fd1)->type = FD_NONE;
45     fd_close(*fd1);
46   }
47   if(*fd2){
48     (*fd2)->type = FD_NONE;
49     fd_close(*fd2);
50   }
51   return -1;
52 }
53 
54 void
55 pipe_close(struct pipe *p, int writeable)
56 {
57   if(writeable)
58     p->writeopen = 0;
59   else
60     p->readopen = 0;
61   if(p->readopen == 0 && p->writeopen == 0)
62     kfree((char *) p, PAGE);
63 }
64 
65 int
66 pipe_write(struct pipe *p, char *addr, int n)
67 {
68   int i;
69 
70   for(i = 0; i < n; i++){
71     while(((p->writep + 1) % PIPESIZE) == p->readp){
72       if(p->readopen == 0)
73         return -1;
74       sleep(&p->writep);
75     }
76     p->data[p->writep] = addr[i];
77     p->writep = (p->writep + 1) % PIPESIZE;
78   }
79   return i;
80 }
81 
82 int
83 pipe_read(struct pipe *p, char *addr, int n)
84 {
85   int i;
86 
87   while(p->readp == p->writep){
88     if(p->writeopen == 0)
89       return 0;
90     sleep(&p->readp);
91   }
92 
93   for(i = 0; i < n; i++){
94     if(p->readp == p->writep)
95       break;
96     addr[i] = p->data[p->readp];
97     p->readp = (p->readp + 1) % PIPESIZE;
98   }
99   return i;
100 }
101