Esempio n. 1
0
static int
_pipeisclosed(struct Fd *fd, struct Pipe *p)
{
	int res;
	uint32_t runs1, runs2;

	// Your code here.
	// 
	// Check pageref(fd) and pageref(p),
	// returning 1 if they're the same, 0 otherwise.
	// 
	// The logic here is that pageref(p) is the total
	// number of readers *and* writers, whereas pageref(fd)
	// is the number of file descriptors like fd (readers if fd is
	// a reader, writers if fd is a writer).
	// 
	// If the number of file descriptors like fd is equal
	// to the total number of readers and writers, then
	// everybody left is what fd is.  So the other end of
	// the pipe is closed.

	for (;;) {
		runs1 = env->env_runs;
		res = pageref(fd) == pageref(p);
		runs2 = env->env_runs;

		if (runs1 == runs2)
			return res;

		if ((runs1 != runs2) && res)
			cprintf("pipe race avoided\n");
	}
}
Esempio n. 2
0
static int
_pipeisclosed(struct Fd *fd, struct Pipe *p)
{
	// Your code here.
	// 
	// Check pageref(fd) and pageref(p),
	// returning 1 if they're the same, 0 otherwise.
	// 
	// The logic here is that pageref(p) is the total
	// number of readers *and* writers, whereas pageref(fd)
	// is the number of file descriptors like fd (readers if fd is
	// a reader, writers if fd is a writer).
	// 
	// If the number of file descriptors like fd is equal
	// to the total number of readers and writers, then
	// everybody left is what fd is.  So the other end of
	// the pipe is closed.

	int runs, r;
	do {
		runs = env->env_runs;
		r = 0;
		if (pageref(fd) == pageref(p))
			r = 1;
	} while (runs != env->env_runs);

	return r;
}
Esempio n. 3
0
static int
_pipeisclosed(struct Fd *fd, struct Pipe *p)
{
	// Check pageref(fd) and pageref(p),
	// returning 1 if they're the same, 0 otherwise.
	//
	// The logic here is that pageref(p) is the total
	// number of readers *and* writers, whereas pageref(fd)
	// is the number of file descriptors like fd (readers if fd is
	// a reader, writers if fd is a writer).
	//
	// If the number of file descriptors like fd is equal
	// to the total number of readers and writers, then
	// everybody left is what fd is.  So the other end of
	// the pipe is closed.
	//
	// LAB 5: Your code here.
	while (true) {
		uint32_t before = thisenv->env_runs;
		bool test = (pageref(fd) == pageref(p));
		asm volatile("" : : : "memory");
		if (before == thisenv->env_runs) return test;
		if (test) cprintf("pipe race avoided\n");
	}
}
Esempio n. 4
0
File: serv.c Progetto: ichaos/jos
// Look up an open file for envid.
int
openfile_lookup(envid_t envid, uint32_t fileid, struct OpenFile **po)
{
	struct OpenFile *o;

	o = &opentab[fileid % MAXOPEN];
	if (pageref(o->o_fd) == 1 || o->o_fileid != fileid) {
                cprintf("pageref(o->o_fd) is %d\n", pageref(o->o_fd));
		return -E_INVAL;
        }
	*po = o;
	return 0;
}
Esempio n. 5
0
static int
_pipeisclosed(struct Fd *fd, struct Pipe *p)
{
	int n, nn, ret;

	while (1) {
		n = thisenv->env_runs;
		ret = pageref(fd) == pageref(p);
		nn = thisenv->env_runs;
		if (n == nn)
			return ret;
		if (n != nn && ret == 1)
			cprintf("pipe race avoided\n", n, thisenv->env_runs, ret);
	}
}
Esempio n. 6
0
// Allocate an open file.
int
open_alloc(struct Open **o)
{
	int i, r;

	// Find an available open-file table entry
	for (i = 0; i < MAXOPEN; i++) {
		switch (pageref(opentab[i].o_ff)) {
			case 0:

				//writef("^^^^^^^^^^^^^^^^ (u_int)opentab[i].o_ff: %x\n",(u_int)opentab[i].o_ff);
				if ((r = syscall_mem_alloc(0, (u_int)opentab[i].o_ff,
										   PTE_V | PTE_R | PTE_LIBRARY)) < 0) {
					return r;
				}

			case 1:
				opentab[i].o_fileid += MAXOPEN;
				*o = &opentab[i];
				user_bzero((void *)opentab[i].o_ff, BY2PG);
				return (*o)->o_fileid;
		}
	}

	return -E_MAX_OPEN;
}
// Look up an open file for envid.
int
openfile_lookup(envid_t envid, uint32_t fileid, struct OpenFile **po)
{
	struct OpenFile *o;

	o = &opentab[fileid % MAXOPEN];
	if (pageref(o->o_fd) <= 1 || o->o_fileid != fileid)
		return -E_INVAL;
	*po = o;
	return 0;
}
Esempio n. 8
0
// Look up an open file for envid.
int
open_lookup(u_int envid, u_int fileid, struct Open **po)
{
	struct Open *o;

	o = &opentab[fileid%MAXOPEN];
	if (pageref(o->o_ff) == 1 || o->o_fileid != fileid)
		return -E_INVAL;
	*po = o;
	return 0;
}
Esempio n. 9
0
File: pipe.c Progetto: ren85/jos2006
static int
_pipeisclosed(struct Fd *fd, struct Pipe *p)
{
	// Your code here.
	// 
	// Check pageref(fd) and pageref(p),
	// returning 1 if they're the same, 0 otherwise.
	// 
	// The logic here is that pageref(p) is the total
	// number of readers *and* writers, whereas pageref(fd)
	// is the number of file descriptors like fd (readers if fd is
	// a reader, writers if fd is a writer).
	// 
	// If the number of file descriptors like fd is equal
	// to the total number of readers and writers, then
	// everybody left is what fd is.  So the other end of
	// the pipe is closed.
    
        int runs;
        bool isclosed;
    
    tryagain:
        runs = env->env_runs;
        //critical section
        isclosed = (pageref(fd)==pageref(p));
        //end of critical section
    
        if(runs != env->env_runs)
        {
            if(isclosed)
                cprintf("pipe race avoided\n");
            goto tryagain;
        }
	if (isclosed)
            return 1;
        
        return 0;
}
Esempio n. 10
0
// Check that fdnum is in range and mapped.
// If it is, set *fd_store to the fd page virtual address.
//
// Returns 0 on success (the page is in range and mapped), < 0 on error.
// Errors are:
//	-E_INVAL: fdnum was either not in range or not mapped.
int
fd_lookup(int fdnum, struct Fd **fd_store)
{
	struct Fd *fd;

	if (fdnum >= 0 && fdnum < MAXFD) {
		fd = INDEX2FD(fdnum);
		if (pageref(fd) > 0) {
			*fd_store = fd;
			return 0;
		}
	}
	*fd_store = 0;
	return -E_INVAL;
}
Esempio n. 11
0
// Finds the smallest i from 0 to MAXFD-1 that doesn't have
// its fd page mapped.
// Sets *fd_store to the corresponding fd page virtual address.
//
// fd_alloc does NOT actually allocate an fd page.
// It is up to the caller to allocate the page somehow.
// This means that if someone calls fd_alloc twice in a row
// without allocating the first page we return, we'll return the same
// page the second time.
//
// Hint: Use INDEX2FD.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_MAX_FD: no more file descriptors
// On error, *fd_store is set to 0.
int
fd_alloc(struct Fd **fd_store)
{
	struct Fd *fd;
	int i;

	for (i = 0; i < MAXFD; i++) {
		fd = INDEX2FD(i);
		if (pageref(fd) == 0) {
			*fd_store = fd;
			return 0;
		}
	}
	*fd_store = 0;
	return -E_MAX_OPEN;
}
Esempio n. 12
0
// Close the file descriptor.
//
static int
devfile_close(struct Fd *fd)
{
	// If this call will close the last reference to the file descriptor,
	// then you must account for the outstanding open file reference
	// in the inode.
	// But the file descriptor might still be open elsewhere
	// (because of fork and dup).  Use pageref to check.
	//
	// LAB 5: Your code here.
    //cprintf("%d\n", pageref(fd));
    if (pageref(fd) > 1)
        return 0;
    struct Inode *ino;
    int r;
    if ((r = inode_open(fd->fd_file.inum, &ino)) < 0)
        return r;
    ino->i_opencount--;
    return inode_close(ino);
}
Esempio n. 13
0
// Allocate an open file.
int
openfile_alloc(struct OpenFile **o)
{
	int i, r;

	// Find an available open-file table entry
	for (i = 0; i < MAXOPEN; i++) {
		switch (pageref(opentab[i].o_fd)) {
		case 0:
			if ((r = sys_page_alloc(0, opentab[i].o_fd, PTE_P|PTE_U|PTE_W)) < 0)
				return r;
			/* fall through */
		case 1:
			opentab[i].o_fileid += MAXOPEN;
			*o = &opentab[i];
			memset(opentab[i].o_fd, 0, PGSIZE);
			return (*o)->o_fileid;
		}
	}
	return -E_MAX_OPEN;
}
Esempio n. 14
0
// Allocate an open file.
int
open_alloc(struct Open **o)
{
	int i, r;

	// Find an available open-file table entry
	for (i = 0; i < MAXOPEN; i++) {
		switch (pageref(opentab[i].o_ff)) {
		case 0:
			if ((r = sys_mem_alloc(0, (u_int)opentab[i].o_ff, PTE_P|PTE_U|PTE_W)) < 0)
				return r;
			/* fall through */
		case 1:
			opentab[i].o_fileid += MAXOPEN;
			*o = &opentab[i];
			memset((void*)opentab[i].o_ff, 0, BY2PG);
			return (*o)->o_fileid;
		}
	}
	return -E_MAX_OPEN;
}
Esempio n. 15
0
void
umain(void)
{
	int p[2], r, pid, i, max;
	void *va;
	struct Fd *fd;
	volatile struct Env *kid;

	cprintf("testing for dup race...\n");
	if ((r = pipe(p)) < 0)
		panic("pipe: %e", r);
	max = 200;
	if ((r = fork()) < 0)
		panic("fork: %e", r);
	if (r == 0) {
		close(p[1]);
		//
		// Now the ref count for p[0] will toggle between 2 and 3
		// as the parent dups and closes it (there's a close implicit in dup).
		//
		// The ref count for p[1] is 1.
		// Thus the ref count for the underlying pipe structure
		// will toggle between 3 and 4.
		//
		// If a clock interrupt catches close between unmapping
		// the pipe structure and unmapping the fd, we'll have
		// a ref count for p[0] of 3, a ref count for p[1] of 1,
		// and a ref count for the pipe structure of 3, which is
		// a no-no.
		//
		// If a clock interrupt catches dup between mapping the
		// fd and mapping the pipe structure, we'll have the same
		// ref counts, still a no-no.
		//
		for (i=0; i<max; i++) {
			if(pipeisclosed(p[0])){
				cprintf("RACE: pipe appears closed\n");
				exit();
			}
			sys_yield();
		}
		// do something to be not runnable besides exiting
		ipc_recv(0,0,0);
	}
	pid = r;
	cprintf("pid is %d\n", pid);
	va = 0;
	kid = &envs[ENVX(pid)];
	cprintf("kid is %d\n", kid-envs);
	dup(p[0], 10);
	while (kid->env_status == ENV_RUNNABLE)
		dup(p[0], 10);

	cprintf("child done with loop\n");
	if (pipeisclosed(p[0]))
		panic("somehow the other end of p[0] got closed!");
	if ((r = fd_lookup(p[0], &fd)) < 0)
		panic("cannot look up p[0]: %e", r);
	va = fd2data(fd);
	if (pageref(va) != 3+1)
		cprintf("\nchild detected race\n");
	else
		cprintf("\nrace didn't happen\n", max);
}