Esempio n. 1
0
static ssize_t
devpipe_read(struct Fd *fd, void *vbuf, size_t n)
{
	uint8_t *buf;
	size_t i;
	struct Pipe *p;

	p = (struct Pipe*)fd2data(fd);
	if (debug)
		cprintf("[%08x] devpipe_read %08x %d rpos %d wpos %d\n",
			thisenv->env_id, uvpt[PGNUM(p)], n, p->p_rpos, p->p_wpos);

	buf = vbuf;
	for (i = 0; i < n; i++) {
		while (p->p_rpos == p->p_wpos) {
			// pipe is empty
			// if we got any data, return it
			if (i > 0)
				return i;
			// if all the writers are gone, note eof
			if (_pipeisclosed(fd, p))
				return 0;
			// yield and see what happens
			if (debug)
				cprintf("devpipe_read yield\n");
			sys_yield();
		}
		// there's a byte.  take it.
		// wait to increment rpos until the byte is taken!
		buf[i] = p->p_buf[p->p_rpos % PIPEBUFSIZ];
		p->p_rpos++;
	}
	return i;
}
Esempio n. 2
0
static ssize_t
devpipe_write(struct Fd *fd, const void *vbuf, size_t n)
{
	const uint8_t *buf;
	size_t i;
	struct Pipe *p;

	p = (struct Pipe*) fd2data(fd);
	if (debug)
		cprintf("[%08x] devpipe_write %08x %d rpos %d wpos %d\n",
			thisenv->env_id, uvpt[PGNUM(p)], n, p->p_rpos, p->p_wpos);

	buf = vbuf;
	for (i = 0; i < n; i++) {
		while (p->p_wpos >= p->p_rpos + sizeof(p->p_buf)) {
			// pipe is full
			// if all the readers are gone
			// (it's only writers like us now),
			// note eof
			if (_pipeisclosed(fd, p))
				return 0;
			// yield and see what happens
			if (debug)
				cprintf("devpipe_write yield\n");
			sys_yield();
		}
		// there's room for a byte.  store it.
		// wait to increment wpos until the byte is stored!
		p->p_buf[p->p_wpos % PIPEBUFSIZ] = buf[i];
		p->p_wpos++;
	}

	return i;
}
Esempio n. 3
0
static ssize_t
pipewrite(struct Fd *fd, const void *vbuf, size_t n, off_t offset)
{
	// Your code here.  See the lab text for a description of what 
	// pipewrite needs to do.  Write a loop that transfers one byte
	// at a time.  Unlike in read, it is not okay to write only some
	// of the data.  If the pipe fills and you've only copied some of
	// the data, wait for the pipe to empty and then keep copying.
	// If the pipe is full and closed, return 0.
	// Use _pipeisclosed to check whether the pipe is closed.

	struct Pipe *p;
	const uint8_t *buf;
	int i;

	USED(offset);

	p = (struct Pipe *)fd2data(fd);
	buf = vbuf;
	for (i = 0; i < n; i++) {
		while (p->p_wpos - p->p_rpos >= PIPEBUFSIZ) {
			if (_pipeisclosed(fd, p))
				return 0;
			sys_yield();
		}
		p->p_buf[p->p_wpos % PIPEBUFSIZ] = buf[i];
		p->p_wpos++;
	}
	return n;
}
Esempio n. 4
0
static ssize_t
devpipe_read(struct Fd *fd, void *vbuf, size_t n)
{
	struct Pipe *p = (struct Pipe *) fd2data(fd);
	uint8_t *buf = (uint8_t *) vbuf;
	size_t i;

	for (i = 0; i < n; i++) {
		while (p->p_rpos == p->p_wpos) {
			// The pipe is currently empty.
			// If any data has been read, return it.
			// Otherwise, check for EOF; if not EOF, yield
			// and try again.
			if (i > 0)
				return i;
			else if (_pipeisclosed(fd, p))
				return 0;
			else
				sys_yield();
		}

		buf[i] = p->p_buf[p->p_rpos % PIPEBUFSIZ];
		// The increment must come AFTER we write to the buffer,
		// or the C compiler might update the pointer before writing
		// to the buffer!  In fact, we need a memory barrier here---
		// on some machines a memory barrier instruction.
		asm volatile("" : : : "memory");
		p->p_rpos++;
	}

	return i;
}
Esempio n. 5
0
int
pipeisclosed(int fdnum)
{
	struct Fd *fd;
	struct Pipe *p;
	int r;

	if ((r = fd_lookup(fdnum, &fd)) < 0)
		return r;
	p = (struct Pipe*) fd2data(fd);
	return _pipeisclosed(fd, p);
}
Esempio n. 6
0
File: pipe.c Progetto: ren85/jos2006
static ssize_t
piperead(struct Fd *fd, void *vbuf, size_t n, off_t offset)
{
	// Your code here.  See the lab text for a description of
	// what piperead needs to do.  Write a loop that 
	// transfers one byte at a time.  If you decide you need
	// to yield (because the pipe is empty), only yield if
	// you have not yet copied any bytes.  (If you have copied
	// some bytes, return what you have instead of yielding.)
	// If the pipe is empty and closed and you didn't copy any data out,
	// return 0.
	// Use _pipeisclosed to check whether the pipe is closed.
        
    
        struct Pipe *pipe;
        bool haveRead;
        int k;
        char *dest;
        
        haveRead = 0;
        dest = vbuf;
        pipe = (struct Pipe *)fd2data(fd);
        
        for(k=n; k!=0; k--) {
        afterYield:
        
            if(pipe->p_rpos >= pipe->p_wpos)
            {
                if(!haveRead)
                {
                    if(_pipeisclosed(fd, pipe))
                    {
                        return 0;
                    } 
                    else 
                    {
                        sys_yield();
                        goto afterYield;
                    }
                }
                else
                    return n-k;
            }
            *dest = pipe->p_buf[pipe->p_rpos % PIPEBUFSIZ];
            dest++;
            pipe->p_rpos++; //race condition when multiple processes read from the same pipe simultaneously, don't know how to fix
                            //without writing new system call to uninterruptable kernel - ren
            haveRead = 1;
        }
        
        return n;
}
Esempio n. 7
0
static ssize_t
devpipe_write(struct Fd *fd, const void *vbuf, size_t n)
{
	// Write a loop that transfers one byte at a time.
	// Your code should be patterned on pipe_read above.
	// Unlike in read, it is not okay to write only some of the data:
	// if the pipe fills and you've only copied some of the data,
	// wait for the pipe to empty and then keep copying.
	// If the pipe is full and closed, return the number of characters
	// written.  Use _pipeisclosed to check whether the pipe is closed.

	// LAB 5: Your code here.
	struct Pipe *p = (struct Pipe *) fd2data(fd);
	uint8_t *buf = (uint8_t *)vbuf;
	size_t i;
	
	for (i = 0; i < n; i++) {
		lock(&p->p_wlock);
		while ((p->p_wpos - p->p_rpos) == PIPEBUFSIZ) {
			// The pipe is currently full.
			// Check for readers... if there
			// are still readers, yield and
			// try again.
			if (_pipeisclosed(fd, p)) {
				unlock(&p->p_wlock);
				return i;
			} else {
				unlock(&p->p_wlock);
				sys_yield();
				lock(&p->p_wlock);
			}
		}
		p->p_buf[p->p_wpos % PIPEBUFSIZ] = buf[i];
		// Need a memory barrier, just like for read.
		asm volatile("" : : : "memory");
		p->p_wpos++;
		unlock(&p->p_wlock);
	}

	return i;
}
Esempio n. 8
0
File: pipe.c Progetto: ren85/jos2006
static ssize_t
pipewrite(struct Fd *fd, const void *vbuf, size_t n, off_t offset)
{
	// Your code here.  See the lab text for a description of what 
	// pipewrite needs to do.  Write a loop that transfers one byte
	// at a time.  Unlike in read, it is not okay to write only some
	// of the data.  If the pipe fills and you've only copied some of
	// the data, wait for the pipe to empty and then keep copying.
	// If the pipe is full and closed, return 0.
	// Use _pipeisclosed to check whether the pipe is closed.

        struct Pipe *pipe;
        int k;
        const char *src;
        
        src = vbuf;
        pipe = (struct Pipe *)fd2data(fd);
    
        for(k=n; k!=0; k--) {
        afterYield:
            
            if(pipe->p_wpos - pipe->p_rpos >= PIPEBUFSIZ)
            {
                if(_pipeisclosed(fd, pipe))
                    return 0;
                
                sys_yield();
                goto afterYield;
            }
               
            pipe->p_buf[pipe->p_wpos % PIPEBUFSIZ] = *src;
            src++;
            pipe->p_wpos++;        //unfixed race condition - ren
        }
        
        return n;
}
Esempio n. 9
0
static ssize_t
piperead(struct Fd *fd, void *vbuf, size_t n, off_t offset)
{
	// Your code here.  See the lab text for a description of
	// what piperead needs to do.  Write a loop that 
	// transfers one byte at a time.  If you decide you need
	// to yield (because the pipe is empty), only yield if
	// you have not yet copied any bytes.  (If you have copied
	// some bytes, return what you have instead of yielding.)
	// If the pipe is empty and closed and you didn't copy any data out,
	// return 0.
	// Use _pipeisclosed to check whether the pipe is closed.

	struct Pipe *p;
	uint8_t *buf;
	int i;

	USED(offset);

	p = (struct Pipe *)fd2data(fd);
	buf = vbuf;
	for (i = 0; i < n; i++) {
		while (p->p_rpos >= p->p_wpos) {
			// copied some bytes, then just return
			if (i > 0)
				return i;
			// i == 0
			// i.e. have not yet copied any bytes
			if (_pipeisclosed(fd, p))
				return 0;
			sys_yield();
		}
		buf[i] = p->p_buf[p->p_rpos % PIPEBUFSIZ];
		p->p_rpos++;
	}
	return n;
}
Esempio n. 10
0
static ssize_t
piperead(struct Fd *fd, void *vbuf, size_t n, off_t offset)
{
	size_t i;
	uint8_t *buf;
	struct Pipe *p;

	USED(offset);

	// Your code here.  See the lab text for a description of
	// what piperead needs to do.  Write a loop that 
	// transfers one byte at a time.  If you decide you need
	// to yield (because the pipe is empty), only yield if
	// you have not yet copied any bytes.  (If you have copied
	// some bytes, return what you have instead of yielding.)
	// If the pipe is empty and closed and you didn't copy any data out,
	// return 0.
	// Use _pipeisclosed to check whether the pipe is closed.

	p = (struct Pipe *) fd2data(fd);
	buf = (uint8_t *) vbuf;

	for (i = 0; i < n; i++) {
		while (pipe_is_empty(p)) {
			if (_pipeisclosed(fd, p) && !i)
				return 0;
			if (!i)
				sys_yield();
			else
				return i;
		}
		buf[i] = p->p_buf[p->p_rpos];
		p->p_rpos = (p->p_rpos + 1) % PIPEBUFSIZ;
	}

	return n;
}