added base src
[xv6-db.git] / pipe.c
blobbdc280f6f02f8f48064d0e41de87d70d61745863
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 bad:
48 if(p)
49 kfree((char*)p);
50 if(*f0)
51 fileclose(*f0);
52 if(*f1)
53 fileclose(*f1);
54 return -1;
57 void
58 pipeclose(struct pipe *p, int writable)
60 acquire(&p->lock);
61 if(writable){
62 p->writeopen = 0;
63 wakeup(&p->nread);
64 } else {
65 p->readopen = 0;
66 wakeup(&p->nwrite);
68 if(p->readopen == 0 && p->writeopen == 0){
69 release(&p->lock);
70 kfree((char*)p);
71 } else
72 release(&p->lock);
75 int
76 pipewrite(struct pipe *p, char *addr, int n)
78 int i;
80 acquire(&p->lock);
81 for(i = 0; i < n; i++){
82 while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full
83 if(p->readopen == 0 || proc->killed){
84 release(&p->lock);
85 return -1;
87 wakeup(&p->nread);
88 sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep
90 p->data[p->nwrite++ % PIPESIZE] = addr[i];
92 wakeup(&p->nread); //DOC: pipewrite-wakeup1
93 release(&p->lock);
94 return n;
97 int
98 piperead(struct pipe *p, char *addr, int n)
100 int i;
102 acquire(&p->lock);
103 while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty
104 if(proc->killed){
105 release(&p->lock);
106 return -1;
108 sleep(&p->nread, &p->lock); //DOC: piperead-sleep
110 for(i = 0; i < n; i++){ //DOC: piperead-copy
111 if(p->nread == p->nwrite)
112 break;
113 addr[i] = p->data[p->nread++ % PIPESIZE];
115 wakeup(&p->nwrite); //DOC: piperead-wakeup
116 release(&p->lock);
117 return i;