5 static int pipeclose(struct Fd
*fd
);
6 static ssize_t
piperead(struct Fd
*fd
, void *buf
, size_t n
, off_t offset
);
7 static int pipestat(struct Fd
*fd
, struct Stat
*stat
);
8 static ssize_t
pipewrite(struct Fd
*fd
, const void *buf
, size_t n
, off_t offset
);
15 .dev_write
= pipewrite
,
16 .dev_close
= pipeclose
,
20 #define PIPEBUFSIZ 32 // small to provoke races
23 off_t p_rpos
; // read position
24 off_t p_wpos
; // write position
25 uint8_t p_buf
[PIPEBUFSIZ
]; // data buffer
35 // allocate the file descriptor table entries
36 if ((r
= fd_alloc(&fd0
)) < 0
37 || (r
= sys_page_alloc(0, fd0
, PTE_P
|PTE_W
|PTE_U
|PTE_SHARE
)) < 0)
40 if ((r
= fd_alloc(&fd1
)) < 0
41 || (r
= sys_page_alloc(0, fd1
, PTE_P
|PTE_W
|PTE_U
|PTE_SHARE
)) < 0)
44 // allocate the pipe structure as first data page in both
46 if ((r
= sys_page_alloc(0, va
, PTE_P
|PTE_W
|PTE_U
|PTE_SHARE
)) < 0)
48 if ((r
= sys_page_map(0, va
, 0, fd2data(fd1
), PTE_P
|PTE_W
|PTE_U
|PTE_SHARE
)) < 0)
51 // set up fd structures
52 fd0
->fd_dev_id
= devpipe
.dev_id
;
53 fd0
->fd_omode
= O_RDONLY
;
55 fd1
->fd_dev_id
= devpipe
.dev_id
;
56 fd1
->fd_omode
= O_WRONLY
;
59 cprintf("[%08x] pipecreate %08x\n", env
->env_id
, vpt
[VPN(va
)]);
66 sys_page_unmap(0, va
);
68 sys_page_unmap(0, fd1
);
70 sys_page_unmap(0, fd0
);
76 _pipeisclosed(struct Fd
*fd
, struct Pipe
*p
)
80 // Check pageref(fd) and pageref(p),
81 // returning 1 if they're the same, 0 otherwise.
83 // The logic here is that pageref(p) is the total
84 // number of readers *and* writers, whereas pageref(fd)
85 // is the number of file descriptors like fd (readers if fd is
86 // a reader, writers if fd is a writer).
88 // If the number of file descriptors like fd is equal
89 // to the total number of readers and writers, then
90 // everybody left is what fd is. So the other end of
91 // the pipe is closed.
93 if (pageref(fd
) == pageref(p
))
99 pipeisclosed(int fdnum
)
105 if ((r
= fd_lookup(fdnum
, &fd
)) < 0)
107 p
= (struct Pipe
*) fd2data(fd
);
108 return _pipeisclosed(fd
, p
);
112 piperead(struct Fd
*fd
, void *vbuf
, size_t n
, off_t offset
)
114 // Your code here. See the lab text for a description of
115 // what piperead needs to do. Write a loop that
116 // transfers one byte at a time. If you decide you need
117 // to yield (because the pipe is empty), only yield if
118 // you have not yet copied any bytes. (If you have copied
119 // some bytes, return what you have instead of yielding.)
120 // If the pipe is empty and closed and you didn't copy any data out,
122 // Use _pipeisclosed to check whether the pipe is closed.
130 p
= (struct Pipe
*)fd2data(fd
);
132 for (i
= 0; i
< n
; i
++) {
133 while (p
->p_rpos
>= p
->p_wpos
) {
134 // copied some bytes, then just return
138 // i.e. have not yet copied any bytes
139 if (_pipeisclosed(fd
, p
))
143 buf
[i
] = p
->p_buf
[p
->p_rpos
% PIPEBUFSIZ
];
150 pipewrite(struct Fd
*fd
, const void *vbuf
, size_t n
, off_t offset
)
152 // Your code here. See the lab text for a description of what
153 // pipewrite needs to do. Write a loop that transfers one byte
154 // at a time. Unlike in read, it is not okay to write only some
155 // of the data. If the pipe fills and you've only copied some of
156 // the data, wait for the pipe to empty and then keep copying.
157 // If the pipe is full and closed, return 0.
158 // Use _pipeisclosed to check whether the pipe is closed.
166 p
= (struct Pipe
*)fd2data(fd
);
168 for (i
= 0; i
< n
; i
++) {
169 while (p
->p_wpos
- p
->p_rpos
>= PIPEBUFSIZ
) {
170 if (_pipeisclosed(fd
, p
))
174 p
->p_buf
[p
->p_wpos
% PIPEBUFSIZ
] = buf
[i
];
181 pipestat(struct Fd
*fd
, struct Stat
*stat
)
183 struct Pipe
*p
= (struct Pipe
*) fd2data(fd
);
184 strcpy(stat
->st_name
, "<pipe>");
185 stat
->st_size
= p
->p_wpos
- p
->p_rpos
;
187 stat
->st_dev
= &devpipe
;
192 pipeclose(struct Fd
*fd
)
198 if ((r
= sys_page_unmap(0, fd
)) < 0)
200 return sys_page_unmap(0, p
);