summaryrefslogtreecommitdiff
path: root/pipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'pipe.c')
-rw-r--r--pipe.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/pipe.c b/pipe.c
new file mode 100644
index 0000000..9a81e0b
--- /dev/null
+++ b/pipe.c
@@ -0,0 +1,100 @@
+#include "types.h"
+#include "param.h"
+#include "x86.h"
+#include "mmu.h"
+#include "proc.h"
+#include "defs.h"
+#include "fd.h"
+
+#define PIPESIZE 512
+
+struct pipe {
+ int readopen; // read fd is still open
+ int writeopen; // write fd is still open
+ int writep; // next index to write
+ int readp; // next index to read
+ char data[PIPESIZE];
+};
+
+int
+pipe_alloc(struct fd **fd1, struct fd **fd2)
+{
+ *fd1 = *fd2 = 0;
+ struct pipe *p = 0;
+
+ if((*fd1 = fd_alloc()) == 0)
+ goto oops;
+ if((*fd2 = fd_alloc()) == 0)
+ goto oops;
+ if((p = (struct pipe *) kalloc(PAGE)) == 0)
+ goto oops;
+ (*fd1)->type = FD_PIPE;
+ (*fd1)->readable = 1;
+ (*fd1)->writeable = 0;
+ (*fd1)->pipe = p;
+ (*fd2)->type = FD_PIPE;
+ (*fd2)->readable = 0;
+ (*fd2)->writeable = 1;
+ (*fd2)->pipe = p;
+ return 0;
+ oops:
+ if(p)
+ kfree((char *) p, PAGE);
+ if(*fd1){
+ (*fd1)->type = FD_NONE;
+ fd_close(*fd1);
+ }
+ if(*fd2){
+ (*fd2)->type = FD_NONE;
+ fd_close(*fd2);
+ }
+ return -1;
+}
+
+void
+pipe_close(struct pipe *p, int writeable)
+{
+ if(writeable)
+ p->writeopen = 0;
+ else
+ p->readopen = 0;
+ if(p->readopen == 0 && p->writeopen == 0)
+ kfree((char *) p, PAGE);
+}
+
+int
+pipe_write(struct pipe *p, char *addr, int n)
+{
+ int i;
+
+ for(i = 0; i < n; i++){
+ while(((p->writep + 1) % PIPESIZE) == p->readp){
+ if(p->readopen == 0)
+ return -1;
+ sleep(&p->writep);
+ }
+ p->data[p->writep] = addr[i];
+ p->writep = (p->writep + 1) % PIPESIZE;
+ }
+ return i;
+}
+
+int
+pipe_read(struct pipe *p, char *addr, int n)
+{
+ int i;
+
+ while(p->readp == p->writep){
+ if(p->writeopen == 0)
+ return 0;
+ sleep(&p->readp);
+ }
+
+ for(i = 0; i < n; i++){
+ if(p->readp == p->writep)
+ break;
+ addr[i] = p->data[p->readp];
+ p->readp = (p->readp + 1) % PIPESIZE;
+ }
+ return i;
+}