diff src/pipe.cbc @ 52:214d21c891c7

rename to cbc __ncode is not handled as interfaces
author kono
date Mon, 03 Jun 2019 18:12:44 +0900
parents src/pipe.c@fb3e5a2f76c1
children d5c4016c65b8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pipe.cbc	Mon Jun 03 18:12:44 2019 +0900
@@ -0,0 +1,201 @@
+#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
+
+#define __ncode __code
+#
+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;
+}
+
+__ncode cbc_piperead3(){
+    struct pipe *p = proc->cbc_arg.cbc_console_arg.p;
+    int i = proc->cbc_arg.cbc_console_arg.i;
+    __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next;
+    release(&p->lock);
+
+    goto next(i);
+}
+
+__ncode cbc_piperead2(){
+    int i = proc->cbc_arg.cbc_console_arg.i;
+    int n = proc->cbc_arg.cbc_console_arg.n;
+    struct pipe *p = proc->cbc_arg.cbc_console_arg.p;
+    char *addr = proc->cbc_arg.cbc_console_arg.addr;
+    if (i < n && !(p->nread == p->nwrite)) {
+        addr[i] = p->data[p->nread++ % PIPESIZE];
+        i ++;
+        proc->cbc_arg.cbc_console_arg.i = i;
+        proc->cbc_arg.cbc_console_arg.p = p;
+        proc->cbc_arg.cbc_console_arg.addr = addr;
+        goto cbc_piperead2();
+    }
+    proc->cbc_arg.cbc_console_arg.p = p;
+    goto cbc_wakeup(&p->nwrite, cbc_piperead3);  //DOC: piperead-wakeup
+}
+
+__ncode cbc_piperead1(){
+    struct pipe *p = proc->cbc_arg.cbc_console_arg.p;
+    __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next;
+    if (p->nread == p->nwrite && p->writeopen){
+        if(proc->killed){
+            release(&p->lock);
+            goto next(-1);
+        }
+        proc->cbc_arg.cbc_console_arg.p = p;
+        goto cbc_sleep(&p->nread, &p->lock, cbc_piperead1);        
+    }
+    int i = 0;
+    proc->cbc_arg.cbc_console_arg.i = i;
+    proc->cbc_arg.cbc_console_arg.p = p;
+    goto cbc_piperead2();
+}
+
+__ncode cbc_piperead(struct pipe *p, char *addr, int n, __code (*next)(int ret))
+{
+    acquire(&p->lock);
+    proc->cbc_arg.cbc_console_arg.n = n;
+    proc->cbc_arg.cbc_console_arg.p = p;
+    proc->cbc_arg.cbc_console_arg.addr = addr;
+    proc->cbc_arg.cbc_console_arg.next = next;
+    goto cbc_piperead1();
+}
+
+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;
+}