summaryrefslogtreecommitdiff
path: root/kernel/pipe.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-06-11 09:57:14 -0400
committerRobert Morris <[email protected]>2019-06-11 09:57:14 -0400
commit5753553213df8f9de851adb68377db43faecb91f (patch)
tree3b629ff54897fca414146677532cb459a2ed11ba /kernel/pipe.c
parent91ba81110acd3163f7de3580b677eece0c57f5e7 (diff)
downloadxv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.gz
xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.bz2
xv6-labs-5753553213df8f9de851adb68377db43faecb91f.zip
separate source into kernel/ user/ mkfs/
Diffstat (limited to 'kernel/pipe.c')
-rw-r--r--kernel/pipe.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/kernel/pipe.c b/kernel/pipe.c
new file mode 100644
index 0000000..31bf0cc
--- /dev/null
+++ b/kernel/pipe.c
@@ -0,0 +1,129 @@
+#include "types.h"
+#include "riscv.h"
+#include "defs.h"
+#include "param.h"
+#include "proc.h"
+#include "fs.h"
+#include "spinlock.h"
+#include "sleeplock.h"
+#include "file.h"
+
+#define PIPESIZE 512
+
+struct pipe {
+ struct spinlock lock;
+ char data[PIPESIZE];
+ uint nread; // number of bytes read
+ uint nwrite; // number of bytes written
+ int readopen; // read fd is still open
+ int writeopen; // write fd is still open
+};
+
+int
+pipealloc(struct file **f0, struct file **f1)
+{
+ struct pipe *p;
+
+ p = 0;
+ *f0 = *f1 = 0;
+ if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
+ goto bad;
+ if((p = (struct pipe*)kalloc()) == 0)
+ goto bad;
+ p->readopen = 1;
+ p->writeopen = 1;
+ p->nwrite = 0;
+ p->nread = 0;
+ initlock(&p->lock, "pipe");
+ (*f0)->type = FD_PIPE;
+ (*f0)->readable = 1;
+ (*f0)->writable = 0;
+ (*f0)->pipe = p;
+ (*f1)->type = FD_PIPE;
+ (*f1)->readable = 0;
+ (*f1)->writable = 1;
+ (*f1)->pipe = p;
+ return 0;
+
+//PAGEBREAK: 20
+ bad:
+ if(p)
+ kfree((char*)p);
+ if(*f0)
+ fileclose(*f0);
+ if(*f1)
+ fileclose(*f1);
+ return -1;
+}
+
+void
+pipeclose(struct pipe *p, int writable)
+{
+ acquire(&p->lock);
+ if(writable){
+ p->writeopen = 0;
+ wakeup(&p->nread);
+ } else {
+ p->readopen = 0;
+ wakeup(&p->nwrite);
+ }
+ if(p->readopen == 0 && p->writeopen == 0){
+ release(&p->lock);
+ kfree((char*)p);
+ } else
+ release(&p->lock);
+}
+
+//PAGEBREAK: 40
+int
+pipewrite(struct pipe *p, uint64 addr, int n)
+{
+ int i;
+ char ch;
+ struct proc *pr = myproc();
+
+ acquire(&p->lock);
+ for(i = 0; i < n; i++){
+ while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full
+ if(p->readopen == 0 || myproc()->killed){
+ release(&p->lock);
+ return -1;
+ }
+ wakeup(&p->nread);
+ sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep
+ }
+ if(copyin(pr->pagetable, &ch, addr + i, 1) == -1)
+ break;
+ p->data[p->nwrite++ % PIPESIZE] = ch;
+ }
+ wakeup(&p->nread); //DOC: pipewrite-wakeup1
+ release(&p->lock);
+ return n;
+}
+
+int
+piperead(struct pipe *p, uint64 addr, int n)
+{
+ int i;
+ struct proc *pr = myproc();
+ char ch;
+
+ acquire(&p->lock);
+ while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty
+ if(myproc()->killed){
+ release(&p->lock);
+ return -1;
+ }
+ sleep(&p->nread, &p->lock); //DOC: piperead-sleep
+ }
+ for(i = 0; i < n; i++){ //DOC: piperead-copy
+ if(p->nread == p->nwrite)
+ break;
+ ch = p->data[p->nread++ % PIPESIZE];
+ if(copyout(pr->pagetable, addr + i, &ch, 1) == -1)
+ break;
+ }
+ wakeup(&p->nwrite); //DOC: piperead-wakeup
+ release(&p->lock);
+ return i;
+}