Пример #1
0
/*
 * Clone the current process.
 *
 * The new thread is given a copy of the caller's file handles if RET
 * is not null. (If RET is null, what we're creating is a kernel-only
 * thread and it doesn't need an address space or file handles.)
 * However, the new thread always inherits its current working
 * directory from the caller. The new thread is given no address space
 * (the caller decides that).
 */
int
proc_fork(struct proc **ret)
{
	struct proc *proc;
	struct filetable *tbl;
	int result;

	proc = proc_create(curproc->p_name);
	if (proc == NULL) {
		return ENOMEM;
	}

	/* VM fields */
	/* do not clone address space -- let caller decide on that */

	/* VFS fields */
	tbl = curproc->p_filetable;
	if (tbl != NULL) {
		result = filetable_copy(tbl, &proc->p_filetable);
		if (result) {
			as_destroy(proc->p_addrspace);
			proc->p_addrspace = NULL;
			proc_destroy(proc);
			return result;
		}
	}

	spinlock_acquire(&curproc->p_lock);
	/* we don't need to lock proc->p_lock as we have the only reference */
	if (curproc->p_cwd != NULL) {
		VOP_INCREF(curproc->p_cwd);
		proc->p_cwd = curproc->p_cwd;
	}
	spinlock_release(&curproc->p_lock);

	*ret = proc;
	return 0;
}
Пример #2
0
int sys_fork(struct trapframe *tf, pid_t *retval) {
	int result;
	char* name;
	(void) result;
	(void) tf;
	(void) retval;
	struct trapframe *temp_tf = kmalloc(sizeof(*temp_tf));
	*temp_tf = *tf;

	struct proc *newproc = proc_create("forked_process");

	// TODO: concurrency issue?
	as_copy(curproc->p_addrspace, &newproc->p_addrspace);

	newproc->p_filetable = kmalloc(sizeof(struct filetable));
	newproc->p_filetable->filetable_lock = lock_create("filetable_lock");

	filetable_copy(newproc->p_filetable);
	// copied from proc.c init p_cwd
	spinlock_acquire(&curproc->p_lock);
	if (curproc->p_cwd != NULL) {
		VOP_INCREF(curproc->p_cwd);
		newproc->p_cwd = curproc->p_cwd;
	}
	spinlock_release(&curproc->p_lock);

	newproc->parent_pid = curproc->pid;

	name = kstrdup(curproc->p_name);

	*retval = newproc->pid;

	thread_fork(name, newproc ,run_forked_proc, (void *)temp_tf, 0);

	return 0;
}
Пример #3
0
int
sys_fork(struct trapframe* tf, pid_t* retval)
{
    DEBUG(DB_EXEC,"sys_fork(): entering\n");
    KASSERT(curproc != NULL);
    KASSERT(sizeof(struct trapframe)==(37*4));

    char* child_name = kmalloc(sizeof(char)* NAME_MAX);
    strcpy(child_name, curproc->p_name);
    strcat(child_name, "_c");

    // create PCB for child
    struct proc* child_proc = NULL;
    proc_fork(&child_proc);
    if (child_proc == NULL)
    {
        return ENOMEM;
    }
    strcpy(child_proc->p_name, child_name);
    
    KASSERT(child_proc->p_pid > 0);

    // copy address space and registers from this process to child
    struct addrspace* child_as = kmalloc(sizeof(struct addrspace));
    if (child_as == NULL)
    {
        kfree(child_name);
        proc_destroy(child_proc);
        return ENOMEM;
    }

    struct trapframe* child_tf = kmalloc(sizeof(struct trapframe));
    if (child_tf == NULL)
    {
        kfree(child_name);
        as_destroy(child_as);
        proc_destroy(child_proc);
        return ENOMEM;
    }

    DEBUG(DB_EXEC,"sys_fork(): copying address space...\n");
    // copy the address space just created into the child process's
    // PCB structure
    int result = as_copy(curproc->p_addrspace, &child_as);
    if (result)
    {
        kfree(child_name);
        as_destroy(child_as);
        proc_destroy(child_proc);
        return result;
    }
    child_proc->p_addrspace = child_as;

    DEBUG(DB_EXEC,"sys_fork(): copying trapframe space...\n");
    // copy this process's trapframe to the child process
    memcpy(child_tf, tf, sizeof(struct trapframe));

    
    DEBUG(DB_EXEC, "sys_fork(): copying filetable...\n");
    filetable_copy(curproc->p_filetable,&child_proc->p_filetable);

    DEBUG(DB_EXEC,"sys_fork(): assigning child process's parent as this process...\n");
    // assign child processes parent as this process
    child_proc->p_parent = curproc;

    DEBUG(DB_EXEC,"sys_fork(): adding child to children procarray...\n");
    result = procarray_add(&curproc->p_children, child_proc, NULL);
    if (result)
    {
        DEBUG(DB_EXEC, "sys_fork(): failed to add child process to proc_table...\n");
    }

    DEBUG(DB_EXEC,"sys_fork(): allocating data...\n");
    void **data = kmalloc(2*sizeof(void*));
    data[0] = (void*)child_tf;
    data[1] = (void*)child_as;

    result = thread_fork(child_name, child_proc, &enter_forked_process, data, 0);
    if (result)
    {
        kfree(child_name);
        kfree(child_tf);
        as_destroy(child_as);
        proc_destroy(child_proc);
        return ENOMEM;
    }

    *retval = child_proc->p_pid;
    DEBUG(DB_EXEC, "sys_fork(): thread_fork returned: curproc=%u, child_proc=%u\n",curproc->p_pid,child_proc->p_pid);
    return 0;
}