5 static ssize_t
devpipe_read(struct Fd
*fd
, void *buf
, size_t n
);
6 static ssize_t
devpipe_write(struct Fd
*fd
, const void *buf
, size_t n
);
7 static int devpipe_stat(struct Fd
*fd
, struct Stat
*stat
);
8 static int devpipe_close(struct Fd
*fd
);
13 /* .dev_name = */ "pipe",
14 /* .dev_read = */ devpipe_read
,
15 /* .dev_write = */ devpipe_write
,
16 /* .dev_close = */ devpipe_close
,
17 /* .dev_stat = */ devpipe_stat
,
21 #define PIPEBUFSIZ 32 // small to provoke races
24 off_t p_rpos
; // read position
25 off_t p_wpos
; // write position
26 uint8_t p_buf
[PIPEBUFSIZ
]; // data buffer
36 // allocate the file descriptor table entries
37 if ((r
= fd_find_unused(&fd0
)) < 0
38 || (r
= sys_page_alloc(0, fd0
, PTE_P
|PTE_W
|PTE_U
|PTE_SHARE
)) < 0)
41 if ((r
= fd_find_unused(&fd1
)) < 0
42 || (r
= sys_page_alloc(0, fd1
, PTE_P
|PTE_W
|PTE_U
|PTE_SHARE
)) < 0)
45 // allocate the pipe structure as first data page in both
47 if ((r
= sys_page_alloc(0, va
, PTE_P
|PTE_W
|PTE_U
|PTE_SHARE
)) < 0)
49 if ((r
= sys_page_map(0, va
, 0, fd2data(fd1
), PTE_P
|PTE_W
|PTE_U
|PTE_SHARE
)) < 0)
52 // set up fd structures
53 fd0
->fd_dev_id
= devpipe
.dev_id
;
54 fd0
->fd_omode
= O_RDONLY
;
56 fd1
->fd_dev_id
= devpipe
.dev_id
;
57 fd1
->fd_omode
= O_WRONLY
;
60 cprintf("[%08x] pipecreate %08x\n", thisenv
->env_id
, vpt
[PGNUM(va
)]);
67 sys_page_unmap(0, va
);
69 sys_page_unmap(0, fd1
);
71 sys_page_unmap(0, fd0
);
77 _pipeisclosed(struct Fd
*fd
, struct Pipe
*p
)
79 // Check pageref(fd) and pageref(p),
80 // returning 1 if they're the same, 0 otherwise.
82 // The logic here is that pageref(p) is the total
83 // number of readers *and* writers, whereas pageref(fd)
84 // is the number of file descriptors like fd (readers if fd is
85 // a reader, writers if fd is a writer).
87 // If the number of file descriptors like fd is equal
88 // to the total number of readers and writers, then
89 // everybody left is what fd is. So the other end of
90 // the pipe is closed.
92 // LAB 5: Your code here.
94 panic("_pipeisclosed not implemented");
99 pipeisclosed(int fdnum
)
105 if ((r
= fd_lookup(fdnum
, &fd
, true)) < 0)
107 p
= (struct Pipe
*) fd2data(fd
);
108 return _pipeisclosed(fd
, p
);
112 devpipe_read(struct Fd
*fd
, void *vbuf
, size_t n
)
114 struct Pipe
*p
= (struct Pipe
*) fd2data(fd
);
115 uint8_t *buf
= (uint8_t *) vbuf
;
118 for (i
= 0; i
< n
; i
++) {
119 while (p
->p_rpos
== p
->p_wpos
) {
120 // The pipe is currently empty.
121 // If any data has been read, return it.
122 // Otherwise, check for EOF; if not EOF, yield
126 else if (_pipeisclosed(fd
, p
))
132 buf
[i
] = p
->p_buf
[p
->p_rpos
% PIPEBUFSIZ
];
133 // The increment must come AFTER we write to the buffer,
134 // or the C compiler might update the pointer before writing
135 // to the buffer! In fact, we need a memory barrier here---
136 // on some machines a memory barrier instruction.
137 asm volatile("" : : : "memory");
145 devpipe_write(struct Fd
*fd
, const void *vbuf
, size_t n
)
147 // Write a loop that transfers one byte at a time.
148 // Your code should be patterned on pipe_read above.
149 // Unlike in read, it is not okay to write only some of the data:
150 // if the pipe fills and you've only copied some of the data,
151 // wait for the pipe to empty and then keep copying.
152 // If the pipe is full and closed, return the number of characters
153 // written. Use _pipeisclosed to check whether the pipe is closed.
155 // LAB 5: Your code here.
157 panic("devpipe_write not implemented");
162 devpipe_stat(struct Fd
*fd
, struct Stat
*stat
)
164 struct Pipe
*p
= (struct Pipe
*) fd2data(fd
);
165 strcpy(stat
->st_name
, "<pipe>");
166 stat
->st_size
= p
->p_wpos
- p
->p_rpos
;
167 stat
->st_ftype
= FTYPE_REG
;
168 stat
->st_dev
= &devpipe
;
173 devpipe_close(struct Fd
*fd
)
175 (void) sys_page_unmap(0, fd
);
176 return sys_page_unmap(0, fd2data(fd
));