#include "../../context.h" #interface "file.h" // ---- // typedef struct pipe impl file { // #define PIPESIZE 512 // 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 // } pipe; // ---- file* createpipe(struct Context* cbc_context) { struct file* file = new file(); struct pipe* pipe = new pipe(); file->file = (union Data*)pipe; pipe->lock = 0; pipe->spinlock = 0; pipe->data = 0; pipe->nread = 0; pipe->nwrite = 0; pipe->readopen = 0; pipe->writeopen = 0; file->off = 0; file->st = NULL; file->addr = NULL; file->n = 0; file->stat = C_statpipe; 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 closepipe(struct pipe* file,int fd,__code next(...)) { proc->ofile[fd] = 0; goto cbc_fileclose(f,next); } __code cbc_fileclose(struct file* file, __code next(...)) { struct file ff; acquire(*ftable.loc) if (f->ref < 1) { goto cbc_context->kernel_error->panic("file close"); } goto cbc_fileclose2(f,ff,next); } __code cbc_fileclose2(struct file* file, struct file* ff,__code next(...)) { if (--f->ref > 0) { release(&ftable.lock); goto cbc_context->return(); } goto cbc_fileclose3(f,ff,next); } __code cbc_fileclose3(struct file* file, struct file* ff,__code next(...)) { *ff = *f; f->ref = 0; f->type = FD_NONE; relsease(&ftable.lock); goto cbc_pipe_close(ff.pipe,ff.writable,next); } __code cbc_pipe_close(struct pipe* p, int writable, __code next(...)) { acquire(&p->lock); if (writable) { goto cbc_pipe_close_writeopen(p,next); } goto cbc_pipe_close_readopen(p,next); } __code cbc_pipe_close_writeopen(struct pipe* p, __code next(...)) { p->writeopen = 0; goto cbc_wakeup(&p->nread,p,cbc_pipe_release,next); } __code cbc_pipe_close_readopen(struct pipe* p, __code next(...)) { p->writeopen = 0; goto cbc_->wakeup(&p->nwrite,p,cbc_pipe_release,next); }