Exemplo n.º 1
0
/*
 * Create a new thread based on an existing one.
 * The new thread has name NAME, and starts executing in function FUNC.
 * DATA1 and DATA2 are passed to FUNC.
 */
int
thread_fork(const char *name,
            void *data1, unsigned long data2,
            void (*func)(void *, unsigned long),
            struct thread **ret)
{
	struct thread *newguy;
	int s, result;
    
	/* Allocate a thread */
	newguy = thread_create(name);
	if (newguy==NULL) {
		return ENOMEM;
	}
    
	/* Allocate a stack */
	newguy->t_stack = kmalloc(STACK_SIZE);
	if (newguy->t_stack==NULL) {
		kfree(newguy->t_name);
		kfree(newguy);
		return ENOMEM;
	}
    
	/* stick a magic number on the bottom end of the stack */
	newguy->t_stack[0] = 0xae;
	newguy->t_stack[1] = 0x11;
	newguy->t_stack[2] = 0xda;
	newguy->t_stack[3] = 0x33;
    
	/* Inherit the current directory */
	if (curthread->t_cwd != NULL) {
		VOP_INCREF(curthread->t_cwd);
		newguy->t_cwd = curthread->t_cwd;
	}
    
#if OPT_A2
    
    if(curthread->forkcalled) {
        int i, res, spl;
        //copy address space
        res = as_copy(curthread->t_vmspace,&newguy->t_vmspace);
        if (res) {
            //kprintf("as_copy failed in thread_fork, curthread_vmspace_addr: %p, newguy_vmspace_addr: %p\n", curthread->t_vmspace, newguy->t_vmspace);
            return res;
        }
        as_activate(curthread->t_vmspace); /* FIXME if wrong comment this out and retry */
        //copy vnodes
//        spl = splhigh();
        for(i=3;i<MAX_OPENED_FILES;i++) {
            if(curthread->files[i]!=NULL) {
                newguy->files[i] = files_create(kstrdup(curthread->files[i]->filename), curthread->files[i]->vn, curthread->files[i]->flags);
                VOP_INCOPEN(newguy->files[i]->vn);
                VOP_INCREF(newguy->files[i]->vn);
            } else {
                break;
            }
        }
//        splx(spl);
        
        curthread->forkcalled = 0;
    }
#endif
    
	/* Set up the pcb (this arranges for func to be called) */
	md_initpcb(&newguy->t_pcb, newguy->t_stack, data1, data2, func);
    
	/* Interrupts off for atomicity */
	s = splhigh();
    
	/*
	 * Make sure our data structures have enough space, so we won't
	 * run out later at an inconvenient time.
	 */
	result = array_preallocate(sleepers, numthreads+1);
	if (result) {
		goto fail;
	}
	result = array_preallocate(zombies, numthreads+1);
	if (result) {
		goto fail;
	}
    
	/* Do the same for the scheduler. */
	result = scheduler_preallocate(numthreads+1);
	if (result) {
		goto fail;
	}
    
	/* Make the new thread runnable */
	result = make_runnable(newguy);
	if (result != 0) {
		goto fail;
	}
    
	/*
	 * Increment the thread counter. This must be done atomically
	 * with the preallocate calls; otherwise the count can be
	 * temporarily too low, which would obviate its reason for
	 * existence.
	 */
	numthreads++;
    
	/* Done with stuff that needs to be atomic */
	splx(s);
    
	/*
	 * Return new thread structure if it's wanted.  Note that
	 * using the thread structure from the parent thread should be
	 * done only with caution, because in general the child thread
	 * might exit at any time.
	 */
	if (ret != NULL) {
		*ret = newguy;
	}
    
	return 0;
    
fail:
	splx(s);
	if (newguy->t_cwd != NULL) {
		VOP_DECREF(newguy->t_cwd);
	}
	kfree(newguy->t_stack);
	kfree(newguy->t_name);
	kfree(newguy);
    
	return result;
}
Exemplo n.º 2
0
/* Does most of the work for open(). */
int
vfs_open(char *path, int openflags, struct vnode **ret)
{
	int how;
	int result;
	int canwrite;
	struct vnode *vn = NULL;

	how = openflags & O_ACCMODE;

	switch (how) {
	    case O_RDONLY:
		canwrite=0;
		break;
	    case O_WRONLY:
	    case O_RDWR:
		canwrite=1;
		break;
	    default:
		return EINVAL;
	}

	if (openflags & O_CREAT) {
		char name[NAME_MAX+1];
		struct vnode *dir;
		int excl = (openflags & O_EXCL)!=0;
		
		result = vfs_lookparent(path, &dir, name, sizeof(name));
		if (result) {
			return result;
		}

		result = VOP_CREAT(dir, name, excl, &vn);

		VOP_DECREF(dir);
	}
	else {
		result = vfs_lookup(path, &vn);
	}

	if (result) {
		return result;
	}

	assert(vn != NULL);

	result = VOP_OPEN(vn, openflags);
	if (result) {
		VOP_DECREF(vn);
		return result;
	}

	VOP_INCOPEN(vn);
	
	if (openflags & O_TRUNC) {
		if (canwrite==0) {
			result = EINVAL;
		}
		else {
			result = VOP_TRUNCATE(vn, 0);
		}
		if (result) {
			VOP_DECOPEN(vn);
			VOP_DECREF(vn);
			return result;
		}
	}

	*ret = vn;

	return 0;
}