This source file includes following definitions.
- pipealloc
- pipeclose
- pipewrite
- piperead
1 #include "types.h"
2 #include "defs.h"
3 #include "param.h"
4 #include "mmu.h"
5 #include "proc.h"
6 #include "fs.h"
7 #include "spinlock.h"
8 #include "sleeplock.h"
9 #include "file.h"
10
11 #define PIPESIZE 512
12
13 struct pipe {
14 struct spinlock lock;
15 char data[PIPESIZE];
16 uint nread;
17 uint nwrite;
18 int readopen;
19 int writeopen;
20 };
21
22 int
23 pipealloc(struct file **f0, struct file **f1)
24 {
25 struct pipe *p;
26
27 p = 0;
28 *f0 = *f1 = 0;
29 if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
30 goto bad;
31 if((p = (struct pipe*)kalloc()) == 0)
32 goto bad;
33 p->readopen = 1;
34 p->writeopen = 1;
35 p->nwrite = 0;
36 p->nread = 0;
37 initlock(&p->lock, "pipe");
38 (*f0)->type = FD_PIPE;
39 (*f0)->readable = 1;
40 (*f0)->writable = 0;
41 (*f0)->pipe = p;
42 (*f1)->type = FD_PIPE;
43 (*f1)->readable = 0;
44 (*f1)->writable = 1;
45 (*f1)->pipe = p;
46 return 0;
47
48
49 bad:
50 if(p)
51 kfree((char*)p);
52 if(*f0)
53 fileclose(*f0);
54 if(*f1)
55 fileclose(*f1);
56 return -1;
57 }
58
59 void
60 pipeclose(struct pipe *p, int writable)
61 {
62 acquire(&p->lock);
63 if(writable){
64 p->writeopen = 0;
65 wakeup(&p->nread);
66 } else {
67 p->readopen = 0;
68 wakeup(&p->nwrite);
69 }
70 if(p->readopen == 0 && p->writeopen == 0){
71 release(&p->lock);
72 kfree((char*)p);
73 } else
74 release(&p->lock);
75 }
76
77
78 int
79 pipewrite(struct pipe *p, char *addr, int n)
80 {
81 int i;
82
83 acquire(&p->lock);
84 for(i = 0; i < n; i++){
85 while(p->nwrite == p->nread + PIPESIZE){
86 if(p->readopen == 0 || myproc()->killed){
87 release(&p->lock);
88 return -1;
89 }
90 wakeup(&p->nread);
91 sleep(&p->nwrite, &p->lock);
92 }
93 p->data[p->nwrite++ % PIPESIZE] = addr[i];
94 }
95 wakeup(&p->nread);
96 release(&p->lock);
97 return n;
98 }
99
100 int
101 piperead(struct pipe *p, char *addr, int n)
102 {
103 int i;
104
105 acquire(&p->lock);
106 while(p->nread == p->nwrite && p->writeopen){
107 if(myproc()->killed){
108 release(&p->lock);
109 return -1;
110 }
111 sleep(&p->nread, &p->lock);
112 }
113 for(i = 0; i < n; i++){
114 if(p->nread == p->nwrite)
115 break;
116 addr[i] = p->data[p->nread++ % PIPESIZE];
117 }
118 wakeup(&p->nwrite);
119 release(&p->lock);
120 return i;
121 }