view src/impl/file_impl_pipe.cbc @ 198:6e28bd30e8a7

fix
author menikon <e165723@ie.u-ryukyu.ac.jp>
date Wed, 22 Jan 2020 20:28:26 +0900
parents 000e247dc51d
children 14aa35b56347
line wrap: on
line source

#include "../../context.h"
#interface "file.h"

// ----
// typedef struct pipe<Impl, Isa> impl file {
//     #define PIPESIZE 512
//     union Data* file;
//     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          ref;   // reference count
//     char         readable;
//     char         writable;
//     unsigned int off;
//
//     // interface field
//     int n;
//     char* addr;
//
//     // private code gear
//     __code piperead1(Impl* pipe, char* addr, int n, __code next(...));
//     __code piperead2(Impl* pipe, char* addr, int n, __code next(...));
//     __code cbc_pipeclose(Impl* pipe, Isa* file, __code next(...));
//     __code cbc_pipeclose2(Impl* pipe, Isa* file, Isa* ff,  __code next(...));
//     __code cbc_pipeclose3(Impl* pipe, Isa* file, Isa* ff,  __code next(...));
//     __code cbc_pipeclose4(Impl* pipe, int writable, __code next(...));
//     __code cbc_pipe_close_writeopen(Impl* pipe, __code next(...));
//     __code cbc_pipe_close_readopen(Impl* pipe, __code next(...));
// } pipe;
// ----

file* createpipe(struct Context* cbc_context) {
    struct file* file  = new file();
    struct pipe* pipe = new pipe();
    file->file = (union Data*)pipe;
    pipe->file = (union Data*)file;
    pipe->lock = 0;
    pipe->spinlock  = 0;
    pipe->data  = 0;
    pipe->nread  = 0;
    pipe->nwrite  = 0;
    pipe->readopen  = 0;
    pipe->writeopen  = 0;
    pipe->ref  = 0;
    pipe->readable  = 0;
    pipe->writable  = 0;
    pipe->off = 0;
    pipe->int  = 0;
    pipe->n  = 0;
    pipe->addr = NULL;
    file->st = NULL;
    file->addr = NULL;
    file->n  = 0;
    file->fd  = 0;
    pipe->piperead1 = C_piperead1pipe;
    pipe->piperead2 = C_piperead2pipe;
    pipe->cbc_pipeclose = C_cbc_pipeclosepipe;
    pipe->cbc_pipeclose2 = C_cbc_pipeclose2pipe;
    pipe->cbc_pipeclose3 = C_cbc_pipeclose3pipe;
    pipe->cbc_pipeclose4 = C_cbc_pipeclose4pipe;
    pipe->cbc_pipe_close_writeopen = C_cbc_pipe_close_writeopenpipe;
    pipe->cbc_pipe_close_readopen = C_cbc_pipe_close_readopenpipe;
    file->read = C_readpipe;
    file->write = C_writepipe;
    file->close = C_closepipe;
    return file;
}


__code statpipe(struct pipe* file, struct stat* st, __code next(...)) { //:skip

    goto next(...);
}

__code readpipe(struct pipe* file, char* addr, int n, __code next(...)) {
    acquire(&p->lock);
    goto cbc_piperead1(file,addr,n,next);
}

__code piperead1(struct pipe* p, char* addr, int n, __code next(...)) {
    if (p->nread == p->nwrite && p->writeopen){
        goto cbc_piperead2(p,addr,n,next);
    }
    n = 0;
    goto cbc_piperead3(p,addr,n,next);
}

__code piperead2(struct pipe* p, char* addr, int n, __code next(...)) {
    if(proc->killed){
        release(&p->lock);
        goto cbc_context->error();
    }
    goto cbc_sleep(p,&p->nread, &p->lock, next,cbc_piperead1);
}


__code cbc_sleep(struct pipe* p, unit* nread, struct spinlock* lock, __code next(...), __code pread(...)){ //:skip
    if(proc == 0) {
        goto cbc_context->panic("sleep");
    }

    if(lk == 0) {
        goto cbc_context->panic("sleep without lk");
    }

    if(lk != &ptable.lock){  //DOC: sleeplock0
        acquire(&ptable.lock);  //DOC: sleeplock1
        release(lk);
    }
    goto cbc_sched(cbc_sleep1);
}

__code cbc_sched_stub(struct pipe* p, unit* nread, struct spinlock* lock, __code next(...), __code pread(...)){ //:skip
    proc->chan = chan;
    proc->state = SLEEPING;
    proc->lk = lk;
    proc->cbc_next = next1;
}

__code writepipe(struct pipe* file, char* addr, int n, __code next(...)) {

    goto next(...);
}

__code pipeclose(struct pipe* file,int fd,__code next(...)) {
    proc->ofile[fd] = 0;
    goto file->cbc_pipeclose(file->file, next);
}


__code cbc_pipeclose(struct pipe* pipe, struct file* file, __code next(...)) {
    struct file ff;
    acquire(*ftable.loc)

    if (f->ref < 1) {
        goto cbc_context->kernel_error->panic("file close");
    }
    goto pipe->cbc_pipeclose2(f,ff,next);
}

__code cbc_pipeclose2(struct pipe* pipe,struct file* file, struct file* ff,__code next(...)) {
    if (--f->ref > 0) {
        release(&ftable.lock);
        goto cbc_context->return();
    }
    goto pipe->cbc_pipeclose3(f,ff,next);
}

__code cbc_pipeclose3(struct pipe* pipe,struct file* file, struct file* ff,__code next(...)) {
    *ff = *f;
    f->ref = 0;
    f->type = FD_NONE;
    relsease(&ftable.lock);
    struct pipe* p = ff.pipe;
    int writable = ff.writable;
    
    goto pipe->cbc_pipeclose4(p,writable,next);
}

__code cbc_pipeclose4(struct pipe* pipe, int writable, __code next(...)) {
    acquire(&pipe->lock);
    if (writable) {
        goto pipe->cbc_pipe_close_writeopen(next);
    }
    goto pipe->cbc_pipe_close_readopen(next);
}


__code cbc_pipe_close_writeopen(struct pipe* pipe, __code next(...)) {
    pipe->writeopen = 0;
    goto cbc_wakeup(&pipe->nread,pipe,cbc_pipe_release,next);
}

__code cbc_pipe_close_readopen(struct pipe* pipe, __code next(...)) {
    pipe->readopen = 0;
    goto cbc_context->wakeup(&pipe->nwrite,pipe,cbc_pipe_release,next);
}