diff src/pipe.c @ 0:83c23a36980d

Init
author Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
date Fri, 26 May 2017 23:11:05 +0900
parents
children ad1d3b268e2d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pipe.c	Fri May 26 23:11:05 2017 +0900
@@ -0,0 +1,146 @@
+#include "types.h"
+#include "defs.h"
+#include "param.h"
+#include "mmu.h"
+#include "proc.h"
+#include "fs.h"
+#include "file.h"
+#include "spinlock.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 = kmalloc (get_order(sizeof(*p)))) == 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 (p, get_order(sizeof*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 (p, get_order(sizeof(*p)));
+
+    } else {
+        release(&p->lock);
+    }
+}
+
+//PAGEBREAK: 40
+int pipewrite(struct pipe *p, char *addr, int n)
+{
+    int i;
+
+    acquire(&p->lock);
+
+    for(i = 0; i < n; i++){
+        while(p->nwrite == p->nread + PIPESIZE){  //DOC: pipewrite-full
+            if(p->readopen == 0 /*|| proc->killed*/){
+                release(&p->lock);
+                return -1;
+            }
+
+            wakeup(&p->nread);
+            sleep(&p->nwrite, &p->lock);  //DOC: pipewrite-sleep
+        }
+
+        p->data[p->nwrite++ % PIPESIZE] = addr[i];
+    }
+
+    wakeup(&p->nread);  //DOC: pipewrite-wakeup1
+    release(&p->lock);
+    return n;
+}
+
+int piperead(struct pipe *p, char *addr, int n)
+{
+    int i;
+
+    acquire(&p->lock);
+
+    while(p->nread == p->nwrite && p->writeopen){  //DOC: pipe-empty
+        if(proc->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;
+        }
+
+        addr[i] = p->data[p->nread++ % PIPESIZE];
+    }
+
+    wakeup(&p->nwrite);  //DOC: piperead-wakeup
+    release(&p->lock);
+
+    return i;
+}