* same with xv6
[mascara-docs.git] / i386 / MIT / src.xv6 / pipe.c
blobf76ed5c557301bfb83cb9d34299955359560a2cc
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"
10 #define PIPESIZE 512
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
21 int
22 pipealloc(struct file **f0, struct file **f1)
24 struct pipe *p;
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;
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;
58 void
59 pipeclose(struct pipe *p, int writable)
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);
69 if(p->readopen == 0 && p->writeopen == 0){
70 release(&p->lock);
71 kfree((char*)p);
72 } else
73 release(&p->lock);
76 //PAGEBREAK: 40
77 int
78 pipewrite(struct pipe *p, char *addr, int n)
80 int i;
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;
89 wakeup(&p->nread);
90 sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep
92 p->data[p->nwrite++ % PIPESIZE] = addr[i];
94 wakeup(&p->nread); //DOC: pipewrite-wakeup1
95 release(&p->lock);
96 return n;
99 int
100 piperead(struct pipe *p, char *addr, int n)
102 int i;
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;
110 sleep(&p->nread, &p->lock); //DOC: piperead-sleep
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];
117 wakeup(&p->nwrite); //DOC: piperead-wakeup
118 release(&p->lock);
119 return i;