root/pipe.c

/* [previous][next][first][last][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 "defs.h"
   3 #include "param.h"
   4 #include "mmu.h"
   5 #include "proc.h"
   6 #include "fs.h"
   7 #include "spinlock.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)
     /* [previous][next][first][last][top][bottom][index][help]  */
  24 {
  25   struct pipe *p;
  26 
  27   p = 0;
  28   *f0 = *f1 = 0;
  29   if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
  30     goto bad;
  31   if((p = (struct pipe*)kalloc()) == 0)
  32     goto bad;
  33   p->readopen = 1;
  34   p->writeopen = 1;
  35   p->nwrite = 0;
  36   p->nread = 0;
  37   initlock(&p->lock, "pipe");
  38   (*f0)->type = FD_PIPE;
  39   (*f0)->readable = 1;
  40   (*f0)->writable = 0;
  41   (*f0)->pipe = p;
  42   (*f1)->type = FD_PIPE;
  43   (*f1)->readable = 0;
  44   (*f1)->writable = 1;
  45   (*f1)->pipe = p;
  46   return 0;
  47 
  48 //PAGEBREAK: 20
  49  bad:
  50   if(p)
  51     kfree((char*)p);
  52   if(*f0)
  53     fileclose(*f0);
  54   if(*f1)
  55     fileclose(*f1);
  56   return -1;
  57 }
  58 
  59 void
  60 pipeclose(struct pipe *p, int writable)
     /* [previous][next][first][last][top][bottom][index][help]  */
  61 {
  62   acquire(&p->lock);
  63   if(writable){
  64     p->writeopen = 0;
  65     wakeup(&p->nread);
  66   } else {
  67     p->readopen = 0;
  68     wakeup(&p->nwrite);
  69   }
  70   if(p->readopen == 0 && p->writeopen == 0){
  71     release(&p->lock);
  72     kfree((char*)p);
  73   } else
  74     release(&p->lock);
  75 }
  76 
  77 //PAGEBREAK: 40
  78 int
  79 pipewrite(struct pipe *p, char *addr, int n)
     /* [previous][next][first][last][top][bottom][index][help]  */
  80 {
  81   int i;
  82 
  83   acquire(&p->lock);
  84   for(i = 0; i < n; i++){
  85     while(p->nwrite == p->nread + PIPESIZE){  //DOC: pipewrite-full
  86       if(p->readopen == 0 || myproc()->killed){
  87         release(&p->lock);
  88         return -1;
  89       }
  90       wakeup(&p->nread);
  91       sleep(&p->nwrite, &p->lock);  //DOC: pipewrite-sleep
  92     }
  93     p->data[p->nwrite++ % PIPESIZE] = addr[i];
  94   }
  95   wakeup(&p->nread);  //DOC: pipewrite-wakeup1
  96   release(&p->lock);
  97   return n;
  98 }
  99 
 100 int
 101 piperead(struct pipe *p, char *addr, int n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 102 {
 103   int i;
 104 
 105   acquire(&p->lock);
 106   while(p->nread == p->nwrite && p->writeopen){  //DOC: pipe-empty
 107     if(myproc()->killed){
 108       release(&p->lock);
 109       return -1;
 110     }
 111     sleep(&p->nread, &p->lock); //DOC: piperead-sleep
 112   }
 113   for(i = 0; i < n; i++){  //DOC: piperead-copy
 114     if(p->nread == p->nwrite)
 115       break;
 116     addr[i] = p->data[p->nread++ % PIPESIZE];
 117   }
 118   wakeup(&p->nwrite);  //DOC: piperead-wakeup
 119   release(&p->lock);
 120   return i;
 121 }

/* [previous][next][first][last][top][bottom][index][help]  */