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_prepare(&pi->nwrite);
  91       release(&pi->lock);
  92       sleep();
  93       acquire(&pi->lock);
  94     } else {
  95       char ch;
  96       if (copyin(pr->pagetable, pr->sz, &ch, addr + i, 1) == -1) {
  97         if (i == 0)
  98           i = -1;
  99         break;
 100       }
 101       pi->data[pi->nwrite++ % PIPESIZE] = ch;
 102       i++;
 103     }
 104   }
 105   wakeup(&pi->nread);
 106   release(&pi->lock);
 107 
 108   return i;
 109 }
 110 
 111 int
 112 piperead(struct pipe *pi, uint64 addr, int n)
 113 {
 114   int i;
 115   struct proc *pr = myproc();
 116   char ch;
 117 
 118   acquire(&pi->lock);
 119   while (pi->nread == pi->nwrite && pi->writeopen) { //DOC: pipe-empty
 120     if (killed(pr)) {
 121       release(&pi->lock);
 122       return -1;
 123     }
 124     sleep_prepare(&pi->nread); //DOC: piperead-sleep
 125     release(&pi->lock);
 126     sleep();
 127     acquire(&pi->lock);
 128   }
 129   for (i = 0; i < n; i++) { //DOC: piperead-copy
 130     if (pi->nread == pi->nwrite)
 131       break;
 132     ch = pi->data[pi->nread % PIPESIZE];
 133     if (copyout(pr->pagetable, pr->sz, addr + i, &ch, 1) == -1) {
 134       if (i == 0)
 135         i = -1;
 136       break;
 137     }
 138     pi->nread++;
 139   }
 140   wakeup(&pi->nwrite); //DOC: piperead-wakeup
 141   release(&pi->lock);
 142   return i;
 143 }

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