xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

pipe.c (2380B)


      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 "file.h"
      8 #include "spinlock.h"
      9 
     10 #define PIPESIZE 512
     11 
     12 struct pipe {
     13   struct spinlock lock;
     14   char data[PIPESIZE];
     15   uint nread;     // number of bytes read
     16   uint nwrite;    // number of bytes written
     17   int readopen;   // read fd is still open
     18   int writeopen;  // write fd is still open
     19 };
     20 
     21 int
     22 pipealloc(struct file **f0, struct file **f1)
     23 {
     24   struct pipe *p;
     25 
     26   p = 0;
     27   *f0 = *f1 = 0;
     28   if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
     29     goto bad;
     30   if((p = (struct pipe*)kalloc()) == 0)
     31     goto bad;
     32   p->readopen = 1;
     33   p->writeopen = 1;
     34   p->nwrite = 0;
     35   p->nread = 0;
     36   initlock(&p->lock, "pipe");
     37   (*f0)->type = FD_PIPE;
     38   (*f0)->readable = 1;
     39   (*f0)->writable = 0;
     40   (*f0)->pipe = p;
     41   (*f1)->type = FD_PIPE;
     42   (*f1)->readable = 0;
     43   (*f1)->writable = 1;
     44   (*f1)->pipe = p;
     45   return 0;
     46 
     47 //PAGEBREAK: 20
     48  bad:
     49   if(p)
     50     kfree((char*)p);
     51   if(*f0)
     52     fileclose(*f0);
     53   if(*f1)
     54     fileclose(*f1);
     55   return -1;
     56 }
     57 
     58 void
     59 pipeclose(struct pipe *p, int writable)
     60 {
     61   acquire(&p->lock);
     62   if(writable){
     63     p->writeopen = 0;
     64     wakeup(&p->nread);
     65   } else {
     66     p->readopen = 0;
     67     wakeup(&p->nwrite);
     68   }
     69   if(p->readopen == 0 && p->writeopen == 0){
     70     release(&p->lock);
     71     kfree((char*)p);
     72   } else
     73     release(&p->lock);
     74 }
     75 
     76 //PAGEBREAK: 40
     77 int
     78 pipewrite(struct pipe *p, char *addr, int n)
     79 {
     80   int i;
     81 
     82   acquire(&p->lock);
     83   for(i = 0; i < n; i++){
     84     while(p->nwrite == p->nread + PIPESIZE){  //DOC: pipewrite-full
     85       if(p->readopen == 0 || proc->killed){
     86         release(&p->lock);
     87         return -1;
     88       }
     89       wakeup(&p->nread);
     90       sleep(&p->nwrite, &p->lock);  //DOC: pipewrite-sleep
     91     }
     92     p->data[p->nwrite++ % PIPESIZE] = addr[i];
     93   }
     94   wakeup(&p->nread);  //DOC: pipewrite-wakeup1
     95   release(&p->lock);
     96   return n;
     97 }
     98 
     99 int
    100 piperead(struct pipe *p, char *addr, int n)
    101 {
    102   int i;
    103 
    104   acquire(&p->lock);
    105   while(p->nread == p->nwrite && p->writeopen){  //DOC: pipe-empty
    106     if(proc->killed){
    107       release(&p->lock);
    108       return -1;
    109     }
    110     sleep(&p->nread, &p->lock); //DOC: piperead-sleep
    111   }
    112   for(i = 0; i < n; i++){  //DOC: piperead-copy
    113     if(p->nread == p->nwrite)
    114       break;
    115     addr[i] = p->data[p->nread++ % PIPESIZE];
    116   }
    117   wakeup(&p->nwrite);  //DOC: piperead-wakeup
    118   release(&p->lock);
    119   return i;
    120 }