Initial Upload
This commit is contained in:
122
pipe.c
Normal file
122
pipe.c
Normal file
@ -0,0 +1,122 @@
|
||||
#include "types.h"
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "mmu.h"
|
||||
#include "proc.h"
|
||||
#include "fs.h"
|
||||
#include "spinlock.h"
|
||||
#include "sleeplock.h"
|
||||
#include "file.h"
|
||||
|
||||
#define PIPESIZE 512
|
||||
|
||||
struct pipe {
|
||||
struct spinlock lock;
|
||||
char data[PIPESIZE];
|
||||
uint nread; // number of bytes read
|
||||
uint nwrite; // number of bytes written
|
||||
int readopen; // read fd is still open
|
||||
int writeopen; // write fd is still open
|
||||
};
|
||||
|
||||
void cleanuppipealloc(struct pipe *p, struct file **f0, struct file **f1) {
|
||||
if (p) {
|
||||
kfree((char*)p);
|
||||
}
|
||||
if (*f0) {
|
||||
fileclose(*f0);
|
||||
}
|
||||
if (*f1) {
|
||||
fileclose(*f1);
|
||||
}
|
||||
}
|
||||
|
||||
int pipealloc(struct file **f0, struct file **f1) {
|
||||
struct pipe *p;
|
||||
|
||||
p = 0;
|
||||
*f0 = *f1 = 0;
|
||||
if ((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) {
|
||||
cleanuppipealloc(p, f0, f1);
|
||||
return -1;
|
||||
}
|
||||
if ((p = (struct pipe*)kalloc()) == 0) {
|
||||
cleanuppipealloc(p, f0, f1);
|
||||
return -1;
|
||||
}
|
||||
p->readopen = 1;
|
||||
p->writeopen = 1;
|
||||
p->nwrite = 0;
|
||||
p->nread = 0;
|
||||
initlock(&p->lock, "pipe");
|
||||
(*f0)->type = FD_PIPE;
|
||||
(*f0)->readable = 1;
|
||||
(*f0)->writable = 0;
|
||||
(*f0)->pipe = p;
|
||||
(*f1)->type = FD_PIPE;
|
||||
(*f1)->readable = 0;
|
||||
(*f1)->writable = 1;
|
||||
(*f1)->pipe = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pipeclose(struct pipe *p, int writable) {
|
||||
acquire(&p->lock);
|
||||
if (writable) {
|
||||
p->writeopen = 0;
|
||||
wakeup(&p->nread);
|
||||
}
|
||||
else {
|
||||
p->readopen = 0;
|
||||
wakeup(&p->nwrite);
|
||||
}
|
||||
if (p->readopen == 0 && p->writeopen == 0) {
|
||||
release(&p->lock);
|
||||
kfree((char*)p);
|
||||
}
|
||||
else {
|
||||
release(&p->lock);
|
||||
}
|
||||
}
|
||||
|
||||
int pipewrite(struct pipe *p, char *addr, int n) {
|
||||
int i;
|
||||
|
||||
acquire(&p->lock);
|
||||
for (i = 0; i < n; i++) {
|
||||
while (p->nwrite == p->nread + PIPESIZE) { //DOC: pipewrite-full
|
||||
if (p->readopen == 0 || myproc()->killed) {
|
||||
release(&p->lock);
|
||||
return -1;
|
||||
}
|
||||
wakeup(&p->nread);
|
||||
sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep
|
||||
}
|
||||
p->data[p->nwrite++ % PIPESIZE] = addr[i];
|
||||
}
|
||||
wakeup(&p->nread); //DOC: pipewrite-wakeup1
|
||||
release(&p->lock);
|
||||
return n;
|
||||
}
|
||||
|
||||
int piperead(struct pipe *p, char *addr, int n) {
|
||||
int i;
|
||||
|
||||
acquire(&p->lock);
|
||||
while (p->nread == p->nwrite && p->writeopen) { //DOC: pipe-empty
|
||||
if (myproc()->killed) {
|
||||
release(&p->lock);
|
||||
return -1;
|
||||
}
|
||||
sleep(&p->nread, &p->lock); //DOC: piperead-sleep
|
||||
}
|
||||
for (i = 0; i < n; i++) { //DOC: piperead-copy
|
||||
if (p->nread == p->nwrite) {
|
||||
break;
|
||||
}
|
||||
addr[i] = p->data[p->nread++ % PIPESIZE];
|
||||
}
|
||||
wakeup(&p->nwrite); //DOC: piperead-wakeup
|
||||
release(&p->lock);
|
||||
return i;
|
||||
}
|
Reference in New Issue
Block a user