kernel/pipe.c
134 lines
1#include "types.h"2#include "riscv.h"3#include "defs.h"4#include "param.h"5#include "spinlock.h"6#include "proc.h"7#include "fs.h"8#include "sleeplock.h"9#include "file.h"1011#define PIPESIZE 5121213struct pipe {14 struct spinlock lock;15 char data[PIPESIZE];16 uint nread; // number of bytes read17 uint nwrite; // number of bytes written18 int readopen; // read fd is still open19 int writeopen; // write fd is still open20};2122int23pipealloc(struct file **f0, struct file **f1)24{25 struct pipe *pi;2627 pi = 0;28 *f0 = *f1 = 0;29 if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)30 goto bad;31 if((pi = (struct pipe*)kalloc()) == 0)32 goto bad;33 pi->readopen = 1;34 pi->writeopen = 1;35 pi->nwrite = 0;36 pi->nread = 0;37 initlock(&pi->lock, "pipe");38 (*f0)->type = FD_PIPE;39 (*f0)->readable = 1;40 (*f0)->writable = 0;41 (*f0)->pipe = pi;42 (*f1)->type = FD_PIPE;43 (*f1)->readable = 0;44 (*f1)->writable = 1;45 (*f1)->pipe = pi;46 return 0;4748 bad:49 if(pi)50 kfree((char*)pi);51 if(*f0)52 fileclose(*f0);53 if(*f1)54 fileclose(*f1);55 return -1;56}5758void59pipeclose(struct pipe *pi, int writable)60{61 acquire(&pi->lock);62 if(writable){63 pi->writeopen = 0;64 wakeup(&pi->nread);65 } else {66 pi->readopen = 0;67 wakeup(&pi->nwrite);68 }69 if(pi->readopen == 0 && pi->writeopen == 0){70 release(&pi->lock);71 kfree((char*)pi);72 } else73 release(&pi->lock);74}7576int77pipewrite(struct pipe *pi, uint64 addr, int n)78{79 int i = 0;80 struct proc *pr = myproc();8182 acquire(&pi->lock);83 while(i < n){84 if(pi->readopen == 0 || killed(pr)){85 release(&pi->lock);86 return -1;87 }88 if(pi->nwrite == pi->nread + PIPESIZE){ //DOC: pipewrite-full89 wakeup(&pi->nread);90 sleep(&pi->nwrite, &pi->lock);91 } else {92 char ch;93 if(copyin(pr->pagetable, &ch, addr + i, 1) == -1)94 break;95 pi->data[pi->nwrite++ % PIPESIZE] = ch;96 i++;97 }98 }99 wakeup(&pi->nread);100 release(&pi->lock);101102 return i;103}104105int106piperead(struct pipe *pi, uint64 addr, int n)107{108 int i;109 struct proc *pr = myproc();110 char ch;111112 acquire(&pi->lock);113 while(pi->nread == pi->nwrite && pi->writeopen){ //DOC: pipe-empty114 if(killed(pr)){115 release(&pi->lock);116 return -1;117 }118 sleep(&pi->nread, &pi->lock); //DOC: piperead-sleep119 }120 for(i = 0; i < n; i++){ //DOC: piperead-copy121 if(pi->nread == pi->nwrite)122 break;123 ch = pi->data[pi->nread % PIPESIZE];124 if(copyout(pr->pagetable, addr + i, &ch, 1) == -1) {125 if(i == 0)126 i = -1;127 break;128 }129 pi->nread++;130 }131 wakeup(&pi->nwrite); //DOC: piperead-wakeup132 release(&pi->lock);133 return i;134}135