Пример #1
0
void
sys__exit(int exitcode)
{

    struct addrspace* as;
    struct proc* p = curproc;
    DEBUG(DB_EXEC, "sys_exit(): process %u exiting with code %d\n",p->p_pid,exitcode);

    KASSERT(p->p_addrspace != NULL);
    as_deactivate();
    as = proc_setas(NULL);
    as_destroy(as);
    proc_remthread(curthread);

    p->p_exitstatus = _MKWAIT_EXIT(exitcode);
    p->p_exitable = true;

    lock_acquire(p->p_waitpid_lk);
        cv_broadcast(p->p_waitpid_cv, p->p_waitpid_lk);
    lock_release(p->p_waitpid_lk);

    proc_destroy(p);
    thread_exit();
    panic("sys__exit(): unexpected return from thread_exit()\n");
}
Пример #2
0
/*
 * Enter user mode for a newly forked process.
 *
 * This function is provided as a reminder. You need to write
 * both it and the code that calls it.
 *
 * Thus, you can trash it and do things another way if you prefer.
 */
void
enter_forked_process(void* ptr, unsigned long args)
{
    //panic("test");
    //while(1) {}
	struct trapframe childtf;
    bzero(&childtf, sizeof(childtf));
    childtf = *(struct trapframe *) ptr;
    childtf.tf_v0 = 0;
    childtf.tf_a3 = 0;
    childtf.tf_epc += 4;
    kfree(ptr);
    // load and activate the address space
    struct addrspace* as = (struct addrspace *) args;
    proc_setas(as);
    as_activate();

    mips_usermode(&childtf);
}
Пример #3
0
int sys_execv(char* progname, char** args, int *retval, bool iskernel) {
	int result;
	int *args_len;
	size_t len;
	size_t total_len = 0;
	char *temp;
	char **kern_args;
	int nargs = 0;
	userptr_t *usr_argv = NULL;
	char *kern_progname = kmalloc(PATH_MAX);
	args_len = kmalloc(sizeof(int) * ARG_MAX);
	temp = kmalloc(sizeof(char) * ARG_MAX);

	if (kern_progname == NULL || args_len == NULL || temp == NULL){
		*retval = -1;
		return ENOMEM;
	}

	if (args == NULL || progname == NULL) {
		*retval = -1;
		return EFAULT;
	}

	if (!iskernel) {
		result = copyinstr((userptr_t)args, temp, ARG_MAX, &len);
		if (result) {
			*retval = -1;
			return result;
		}
	}

	// Figure out nargs, and the length for each arg string
	while(args[nargs] != NULL) {
		if (iskernel) {
			len = strlen(args[nargs]) + 1;
			if (len == 1) {
				nargs--;
				break;
			}
			strcpy(temp, args[nargs]);
		} else {
			result = copyinstr((userptr_t)args[nargs], temp, ARG_MAX, &len);
			if (result) {
				*retval = -1;
				return result;
			}
		}
		args_len[nargs] = len;
		total_len += len;
		nargs += 1;
	}
	kfree(temp);

	if (total_len > ARG_MAX) {
		*retval = -1;
		return E2BIG;
	}

	kern_args = kmalloc(sizeof(char*) * nargs);

	// Go through args and copy everything over to kern_args using copyinstr
	for (int i = 0; i < nargs; i++) {
		kern_args[i] = kmalloc(sizeof(char) * args_len[i]);
		if (kern_args[i] == NULL) {
			*retval = -1;
			return ENOMEM;
		}

		if (iskernel) {
			strcpy(kern_args[i], args[i]);
			len = strlen(kern_args[i]);
		} else {
			copyinstr((userptr_t)args[i], kern_args[i], ARG_MAX, NULL);
		}
	}

	// This is from runprogram 
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;


	if (iskernel) {
		strcpy(kern_progname, progname);
		len = strlen(kern_progname);
	} else {
		result = copyinstr((userptr_t)progname, kern_progname, PATH_MAX, NULL);
	}

	if (*kern_progname == 0) {
		*retval = -1;
		return EISDIR;
	}
	if (result) {
		kfree(kern_progname);
		*retval = -1;
		return result;
	}

	/* Open the file. */
	result = vfs_open(kern_progname, O_RDONLY, 0, &v);
	if (result) {
		*retval = -1;
		return result;
	}

	// Blow up the current addrspace. TODO, this may be problematic
	if (!iskernel) {
		as_destroy(curproc->p_addrspace);
		curproc->p_addrspace = NULL;
	}

	/* We should be a new process. */
	KASSERT(proc_getas() == NULL);

	/* Create a new address space. */
	as = as_create();
	if (as == NULL) {
		vfs_close(v);
		*retval = -1;
		return ENOMEM;
	}

	/* Switch to it and activate it. */
	proc_setas(as);
	as_activate();

	/* Intialize file table, not needed for execv */
	if (iskernel)
		filetable_init();

	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		*retval = -1;
		return result;
	}

	/* Done with the file now. */
	vfs_close(v);

	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		*retval = -1;
		return result;
	}

	// Clear space for arg pointers +1 for NULL terminator
	stackptr -= (sizeof(char*)) * (nargs + 1);

	// Convenience method for indexing
	usr_argv = (userptr_t*)stackptr;

	for(int i = 0; i < nargs; i++ ) {
		// Clear out space for an arg string
		stackptr -= sizeof(char) * (strlen(kern_args[i]) + 1);
		// Assign the string's pointer to usr_argv
		usr_argv[i] = (userptr_t)stackptr;
		// Copy over string
		copyout(kern_args[i], usr_argv[i],
			sizeof(char) * (strlen(kern_args[i]) + 1));
	}

	// NULL terminate usr_argv
	usr_argv[nargs] = NULL;

	// Free memory
	for(int i = 0; i < nargs; i++) {
		kfree(kern_args[i]);
	}
	kfree(kern_args);

	/* Warp to user mode. */
	enter_new_process(nargs /*argc*/, (userptr_t)usr_argv /*userspace addr of argv*/,
			  NULL /*userspace addr of environment*/,
			  stackptr, entrypoint);

	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Пример #4
0
/*
 * Destroy a proc structure.
 *
 * Note: nothing currently calls this. Your wait/exit code will
 * probably want to do so.
 */
void
proc_destroy(struct proc *proc)
{
	/*
	 * You probably want to destroy and null out much of the
	 * process (particularly the address space) at exit time if
	 * your wait/exit design calls for the process structure to
	 * hang around beyond process exit. Some wait/exit designs
	 * do, some don't.
	 */

	KASSERT(proc != NULL);
	KASSERT(proc != kproc);

	/*
	 * We don't take p_lock in here because we must have the only
	 * reference to this structure. (Otherwise it would be
	 * incorrect to destroy it.)
	 */

	/* VFS fields */
	if (proc->p_cwd) {
		VOP_DECREF(proc->p_cwd);
		proc->p_cwd = NULL;
	}
	if (proc->p_filetable) {
		filetable_destroy(proc->p_filetable);
		proc->p_filetable = NULL;
	}

	/* VM fields */
	if (proc->p_addrspace) {
		/*
		 * If p is the current process, remove it safely from
		 * p_addrspace before destroying it. This makes sure
		 * we don't try to activate the address space while
		 * it's being destroyed.
		 *
		 * Also explicitly deactivate, because setting the
		 * address space to NULL won't necessarily do that.
		 *
		 * (When the address space is NULL, it means the
		 * process is kernel-only; in that case it is normally
		 * ok if the MMU and MMU- related data structures
		 * still refer to the address space of the last
		 * process that had one. Then you save work if that
		 * process is the next one to run, which isn't
		 * uncommon. However, here we're going to destroy the
		 * address space, so we need to make sure that nothing
		 * in the VM system still refers to it.)
		 *
		 * The call to as_deactivate() must come after we
		 * clear the address space, or a timer interrupt might
		 * reactivate the old address space again behind our
		 * back.
		 *
		 * If p is not the current process, still remove it
		 * from p_addrspace before destroying it as a
		 * precaution. Note that if p is not the current
		 * process, in order to be here p must either have
		 * never run (e.g. cleaning up after fork failed) or
		 * have finished running and exited. It is quite
		 * incorrect to destroy the proc structure of some
		 * random other process while it's still running...
		 */
		struct addrspace *as;

		if (proc == curproc) {
			as = proc_setas(NULL);
			as_deactivate();
		}
		else {
			as = proc->p_addrspace;
			proc->p_addrspace = NULL;
		}
		as_destroy(as);
	}

	threadarray_cleanup(&proc->p_threads);
	spinlock_cleanup(&proc->p_lock);

	kfree(proc->p_name);
	kfree(proc);
}
Пример #5
0
int
runprogram(char *progname)
{
    struct addrspace *as;
    struct vnode *v;
    vaddr_t entrypoint, stackptr;
    int result;

    /* Open the file. */
    result = vfs_open(progname, O_RDONLY, 0, &v);
    if (result) {
        return result;
    }

    /* We should be a new process. */
    KASSERT(proc_getas() == NULL);

    /* Create a new address space. */
    as = as_create();
    if (as == NULL) {
        vfs_close(v);
        return ENOMEM;
    }

    /* Switch to it and activate it. */
    proc_setas(as);
    as_activate();

    /* Load the executable. */
    result = load_elf(v, &entrypoint);
    if (result) {
        /* p_addrspace will go away when curproc is destroyed */
        vfs_close(v);
        return result;
    }

    /* Done with the file now. */
    vfs_close(v);

    /* Define the user stack in the address space */
    result = as_define_stack(as, &stackptr);
    if (result) {
        // p_addrspace will go away when curproc is destroyed
        return result;
    }

    struct vnode* v1;
    struct vnode* v2;
    struct vnode* v3;

    const char* name = "con:";


    char *con_name = kstrdup(name);
    char *con_name2 = kstrdup(name);
    char *con_name3 = kstrdup(name);



    /*char con_name[5];
    char con_name2[5];
    char con_name3[5];

    strcpy(con_name,name);
    strcpy(con_name2,name);
    strcpy(con_name3,name);
    */

    result = vfs_open(con_name, O_RDONLY, 0664, &v1);
    if(result)
    {
        return result;
    }

    result = vfs_open(con_name2, O_WRONLY, 0664, &v2);
    if(result)
    {
        return result;
    }
    result = vfs_open(con_name3, O_WRONLY, 0664, &v3);
    if(result)
    {
        return result;
    }
    kfree(con_name);
    kfree(con_name2);
    kfree(con_name3);
    struct file_handle* fh1 = file_handle_create();
    fh1->file = v1;
    fh1->openflags = O_RDONLY;
    fh1->ref_count  = 1;
    strcpy(fh1->file_name,"con:");
    curproc->t_file_table[0] = fh1;

    struct file_handle* fh2 = file_handle_create();
    fh2->file = v2;
    fh2->openflags = O_WRONLY;
    fh2->ref_count = 1;
    strcpy(fh2->file_name, "con:");
    curproc->t_file_table[1] = fh2;

    struct file_handle* fh3 = file_handle_create();
    fh3->file = v3;
    fh3->openflags = O_WRONLY;
    fh3->ref_count = 1;
    strcpy(fh3->file_name, "con:");
    curproc->t_file_table[2] = fh3;

    /* Warp to user mode. */
    //kprintf("[run program] releasing semaphore \n");
    enter_new_process(0 /*argc*/, 0 /*userspace addr of argv*/,
                      NULL /*userspace addr of environment*/,
                      stackptr, entrypoint);

    /* enter_new_process does not return. */
    panic("enter_new_process returned\n");
    return EINVAL;
}
Пример #6
0
/*
 * Load program "progname" and start running it in usermode.
 * Does not return except on error.
 *
 * Calls vfs_open on progname and thus may destroy it.
 */
int
runprogram(char *progname)
{
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;

  /** Initialize the file descriptors for console**/
	if (curthread->t_fdtable[0] == NULL) {
			result = init_file_descriptor();
			if (result ) { // file descriptors not initialized
				 kprintf_n("init_file_descriptor failed");
				 return result;
			}
	}
	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

	/* We should be a new process. */
	KASSERT(proc_getas() == NULL);

	/* Create a new address space. */
	as = as_create();
	if (as == NULL) {
		vfs_close(v);
		return ENOMEM;
	}

	/* Switch to it and activate it. */
	proc_setas(as);
	as_activate();

	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}

	/* Done with the file now. */
	vfs_close(v);

	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		return result;
	}

	/* Warp to user mode. */
	enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/,
			  NULL /*userspace addr of environment*/,
			  stackptr, entrypoint);

	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Пример #7
0
int
sys_execv(char *progname, char **args, int *err) {

    struct addrspace *as;
    struct vnode *v;
    vaddr_t entrypoint, stackptr;
    int result;

    /* Validations */
    if (progname == NULL) {
        *err = EFAULT;
        return -1;
    }

    if (args == NULL || (int *)args == (int *)0x40000000 || (int *)args == (int *)0x80000000) {
        *err = EFAULT;
        return -1;
    }

    /* Count number of arguments and total size of input */
    int args_count = 0;
    for (;args_count < ARG_MAX && args[args_count] != NULL; args_count++);

    if (args_count > ARG_MAX) {
        *err = E2BIG;
        return -1;
    }

    /* Copy File name */
    char *progname_copy = (char *) kmalloc(sizeof(char) * NAME_MAX);
    size_t actual = 0;
    result = copyinstr((userptr_t)progname, progname_copy, NAME_MAX, &actual);

    if (result) {
        kfree(progname_copy);
        *err = result;
        return -1;
    }

    if (strlen(progname_copy) == 0) {
        kfree(progname_copy);
        *err = EINVAL;
        return -1;
    }

    /* Allocate Kernel Memory for arguments */
    char **args_copy = (char **) kmalloc(sizeof(char *) * args_count);

    int c_args_count = 0,
            arg_size = 0,
            padded_size = 0;

    for (;c_args_count < args_count; c_args_count++) {
        if ((int *)args[c_args_count] == (int *)0x40000000 || (int *)args[c_args_count] == (int *)0x80000000) {
            kfree(progname_copy);
            *err = EFAULT;
            return -1;
        }
    }

    c_args_count = 0;
    /* Calculate total length accounting for padding */
    for (;c_args_count < args_count; c_args_count++) {
        arg_size = strlen(args[c_args_count]) + 1;

        args_copy[c_args_count] = (char *) kmalloc(sizeof(char) * arg_size);
        copyinstr((userptr_t)args[c_args_count], args_copy[c_args_count], arg_size, &actual);

        padded_size += arg_size;
        if (padded_size % 4) {
            padded_size += (4 - (padded_size % 4)) % 4;
        }
    }

    /* Open the file. */
    result = vfs_open(progname_copy, O_RDONLY, 0, &v);
    if (result) {
        kfree(progname_copy);
        *err = result;
        return -1;
    }

    /* Destroy the current process's address space to create a new one. */
    as = curproc->p_addrspace;
    curproc->p_addrspace = NULL;

    as_destroy(as);

    /* We should be a new process. */
    KASSERT(proc_getas() == NULL);

    /* Create a new address space. */
    as = as_create();
    if (as == NULL) {
        kfree(progname_copy);
        vfs_close(v);
        *err = ENOMEM;
        return -1;
    }

    /* Switch to it and activate it. */
    proc_setas(as);
    as_activate();

    /* Load the executable. */
    result = load_elf(v, &entrypoint);
    if (result) {
        /* p_addrspace will go away when curproc is destroyed */
        kfree(progname_copy);
        vfs_close(v);
        *err = result;
        return -1;
    }

    /* Done with the file now. */
    vfs_close(v);

    /* Define the user stack in the address space */
    result = as_define_stack(as, &stackptr);
    if (result) {
        /* p_addrspace will go away when curproc is destroyed */
        kfree(progname_copy);
        *err = result;
        return -1;
    }

    stackptr -= padded_size;
    char **arg_address = (char **) kmalloc(sizeof(char *) * args_count + 1);

    /* Copy arguments into user stack */
    for(int i = 0; i < args_count; i++) {
        arg_size = strlen(args_copy[i]) + 1;

        if (arg_size % 4) {
            arg_size += (4 - arg_size % 4) % 4;
        }

        /* Store address of arguments */
        arg_address[i] = (char *)stackptr;

        copyoutstr(args_copy[i], (userptr_t)stackptr, arg_size, &actual);
        stackptr += arg_size;
    }

    /* Add Null Pointer at the end */
    arg_address[args_count] = 0;

    stackptr -= padded_size;
    stackptr -= (args_count + 1) * sizeof(char *);

    /* Copy address locations into user stack*/
    for (int i = 0; i < args_count + 1; i++) {
        copyout((arg_address + i), (userptr_t)stackptr, sizeof(char *));
        stackptr += sizeof(char *);
    }

    /* Reset pointer to start of the stack */
    stackptr -= ((args_count + 1) * sizeof(char *));

    kfree(progname_copy);

    c_args_count = 0;
    for (;c_args_count < args_count; c_args_count++) {
        kfree(args_copy[c_args_count]);
    }

    kfree(args_copy);
    kfree(arg_address);

    /* Warp to user mode. */
    enter_new_process(args_count /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/,
                      (userptr_t) stackptr /*userspace addr of environment*/, stackptr, entrypoint);

    /* enter_new_process does not return. */
    panic("enter_new_process returned\n");

    *err = EINVAL;
    return -1;
}
Пример #8
0
int sys_execv(userptr_t progname, userptr_t *arguments) {
    struct proc *proc = curproc;
    struct addrspace *as;
    struct vnode *v;
    vaddr_t entrypoint, stackptr;
    int result;

    //kprintf("****EXECV]***** process-%d trying to exec", proc->pid);

    //lock_acquire(execlock);
    //kprintf("****EXECV]***** process-%d acquired exec lock", proc->pid);
	if(progname == NULL || progname == (void *)0x80000000 || progname == (void *)0x40000000) {
		return EFAULT;
	}

    if(arguments == NULL || arguments == (void *)0x80000000 || arguments == (void *)0x40000000) {
        return EFAULT;
    }
    /* This process should have an address space copied during fork */
    KASSERT(proc != NULL);
    char *_progname;
    size_t size;
    int i=0, count=0;
    _progname = (char *) kmalloc(sizeof(char)*PATH_MAX);
    result = copyinstr(progname, _progname, PATH_MAX, &size);
    if(result) {
        kfree(_progname);
        return EFAULT;
    }
    if(strlen(_progname) == 0) {
        kfree(_progname);
        return EINVAL;
    }
	if(swapping_started == true) {
    }
    kfree(_progname);

    char *args = (char *) kmalloc(sizeof(char)*ARG_MAX);
    result = copyinstr((const_userptr_t)arguments, args, ARG_MAX, &size);
    if(result) {
        kfree(args);
        return EFAULT;
    }
    /* Copy the user arguments on to the kernel */
   
    int offset = 0;
    while((char *) arguments[count] != NULL) {
        result = copyinstr((const_userptr_t) arguments[count], args+offset, ARG_MAX, &size);
        if(result) {
            kfree(args);
            return EFAULT;
        }
        offset += size;
        count++;
    }

    /* Open the file */
    result = vfs_open((char *)progname, O_RDONLY, 0, &v);
    if(result) {
        kfree(args);
        return result;
    }

    /* Destroy the current address space and Create a new address space */
    as_destroy(proc->p_addrspace);
    proc->p_addrspace = NULL;
    
    KASSERT(proc_getas() == NULL);

    as = as_create();
    if(as == NULL) {
        kfree(args);
        vfs_close(v);
        return ENOMEM;
    }
    /* Switch to it and activate it */
    proc_setas(as);
    as_activate();

    /* Load the executable. */

  //  kprintf("free pages available before load_elf : %d \n", coremap_free_bytes()/4096);
    result = load_elf(v, &entrypoint);
    if(result) {
        kfree(args);
        vfs_close(v);
        return result;
    }

    /* Done with the file now */
    vfs_close(v);

    /* Define the user stack in the address space */
    result = as_define_stack(as, &stackptr);
    if(result) {
        kfree(args);
        return result;
    }

    i = 0;
    int prevlen = 0, cur = 0;
    char **stkargs=(char**) kmalloc(sizeof(char*)*(count+1));
    while(i < offset) {
        int len=0, olen;
        for(len=0; args[i] != '\0'; len++, i++);
        olen = len;
        len = len + (4 - len%4);

        char *arg = kmalloc(len);
        //arg = kstrdup(args+prevlen);

        //kprintf("%s\n", arg);
        int j = prevlen;
        for(int k=0; k<len; k++) {
            if(k >= olen)
                arg[k] = '\0';
            else
                arg[k] = args[j++];
        }

        //kprintf("%s\n", arg);
        stackptr -= len;
        result = copyout((const void *)arg, (userptr_t)stackptr, (size_t)len);
        if(result) {
            kfree(args);
            kfree(stkargs);
            return result;
        }
        kfree(arg);
        stkargs[cur++] = (char *)stackptr;
        prevlen += olen + 1;
        i++;
    }
    stkargs[cur] = NULL;
    kfree(args);

    for(i=(cur) ; i>=0; i--) {
        stackptr = stackptr - sizeof(char *);
        //kprintf("copying arg %d at [%p]\n", i, *(stkargs+i));
        result = copyout((const void *)(stkargs+i), (userptr_t) stackptr, (sizeof(char *)));
        if(result) {
            kfree(stkargs);
            return result;
        }
        prevlen += 4;
    }
    kfree(stkargs);
    
    //unsigned int free = coremap_free_bytes();
  //  unsigned int free_pages = free/4096;

  //  kprintf("free pages available : %d \n", free_pages);

    //lock_release(execlock);
    //kprintf("****EXECV]***** process-%d released exec lock", proc->pid);
    enter_new_process(count, (userptr_t) stackptr, NULL, stackptr, entrypoint);

    panic("enter_new_process returned\n");
    return EINVAL;
}