root/kernel/pipe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pipealloc
  2. pipeclose
  3. pipewrite
  4. piperead

   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"
  10 
  11 #define PIPESIZE 512
  12 
  13 struct pipe {
  14   struct spinlock lock;
  15   char data[PIPESIZE];
  16   uint nread;     // number of bytes read
  17   uint nwrite;    // number of bytes written
  18   int readopen;   // read fd is still open
  19   int writeopen;  // write fd is still open
  20 };
  21 
  22 int
  23 pipealloc(struct file **f0, struct file **f1)
  24 {
  25   struct pipe *pi;
  26 
  27   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;
  47 
  48  bad:
  49   if(pi)
  50     kfree((char*)pi);
  51   if(*f0)
  52     fileclose(*f0);
  53   if(*f1)
  54     fileclose(*f1);
  55   return -1;
  56 }
  57 
  58 void
  59 pipeclose(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   } else
  73     release(&pi->lock);
  74 }
  75 
  76 int
  77 pipewrite(struct pipe *pi, uint64 addr, int n)
  78 {
  79   int i = 0;
  80   struct proc *pr = myproc();
  81 
  82   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-full
  89       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);
 101 
 102   return i;
 103 }
 104 
 105 int
 106 piperead(struct pipe *pi, uint64 addr, int n)
 107 {
 108   int i;
 109   struct proc *pr = myproc();
 110   char ch;
 111 
 112   acquire(&pi->lock);
 113   while(pi->nread == pi->nwrite && pi->writeopen){  //DOC: pipe-empty
 114     if(killed(pr)){
 115       release(&pi->lock);
 116       return -1;
 117     }
 118     sleep(&pi->nread, &pi->lock); //DOC: piperead-sleep
 119   }
 120   for(i = 0; i < n; i++){  //DOC: piperead-copy
 121     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       break;
 126   }
 127   wakeup(&pi->nwrite);  //DOC: piperead-wakeup
 128   release(&pi->lock);
 129   return i;
 130 }

/* [<][>][^][v][top][bottom][index][help] */