Exemplo n.º 1
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);
}
Exemplo n.º 2
0
// man page
// int execv(const char *program, char **args);
int sys_execv(char *progname, char **argv){
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;
	unsigned long argc = 0;

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

	/* Destroy the current address space */
	as_deactivate();
	as = curproc_setas(NULL);
	as_destroy(as);

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

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

	/* Switch to it and activate it. */
	curproc_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;
	}

	// we need to figure out what argc would be
	for(unsigned long i = 0; argv[i] != NULL; i++){
		argc = i + 1;
	}

	#if OPT_A2
		// How much space do we need for args in stack?
		// We need space for each pointer (4argc)
		// We need space for each character, including NULL termination, plus
		// padding to make multiples of 4
		int stringSpace = 0;
		for (unsigned long i = 0; i < argc; i++) {
			stringSpace += strlen(argv[i]) + 1;
		}

		// Align stack pointer to an 8-byte alignment
		while ((stackptr - (4*argc) - stringSpace) % 8 != 0) {
			stackptr--;
		}

		// Use a vaddr array to track the addresses the strings end up in
		// One bigger than argc to also have the pointer to the final NULL
		// value
		vaddr_t stringAddr[argc+1];

		// Copy argument strings onto stack
		// Array must end with NULL pointer, so do that first
		stackptr -= 4;
		copyout((void *)NULL, (userptr_t)stackptr, (size_t)4);
		stringAddr[argc] = stackptr;
		for (int i = argc-1; i >= 0; i--) {
			stackptr -= strlen(argv[i]) + 1;
			while (stackptr % 4 != 0) stackptr--;
			copyoutstr(argv[i], (userptr_t)stackptr, (size_t)strlen(argv[i]), NULL);
			stringAddr[i] = stackptr;
		}

		// Now use the stored addresses of the string to add the appropriate
		// pointers to the stack
		for (int i = argc; i >= 0; i--) {
			stackptr -= sizeof(vaddr_t);
			copyout(&stringAddr[i], (userptr_t)stackptr, sizeof(vaddr_t));
		}

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

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

	(void)progname;
	(void)argv;
}
Exemplo n.º 3
0
int
sys___execv(char * p_name,char **ar )
{
	struct vnode *p_vnode;
		vaddr_t  stackptr;
		vaddr_t entrypoint;

		int result;
		size_t copied_length;
		char *kname;

		if(p_name==NULL)
			return EFAULT;

		if(ar==NULL)
			return EFAULT;

		if(p_name == '\0')
			return ENOEXEC;


		kname = (char *) kmalloc(sizeof(p_name));
		result = copyinstr((const_userptr_t)p_name,kname,NAME_MAX,&copied_length);
		if(copied_length == 1)
		{
			kfree(kname);
			return EINVAL;
		}
		if(result)
		{
			kfree(kname);
			return result;
		}

		char **karguments1 = kmalloc(100*sizeof(char*));
		result = copyin((const_userptr_t) ar,karguments1,(100*sizeof(char*)));
		if(result)
		{
			kfree(karguments1);
			kfree(kname);
			return result;
		}
		else
			kfree(karguments1);

		char **arguments_kernel =(char **) kmalloc(sizeof(char**));
		result = copyin((const_userptr_t) ar,arguments_kernel,(sizeof(char**)));
		if(result)
		{
			kfree(kname);
			kfree(arguments_kernel);
			return result;

		}

		char **karguments = (char **) kmalloc(sizeof(char **));

		int counter=0;
		size_t actual_lenght1;
		while(!(ar[counter]==NULL))
		{
			int string_length = strlen(ar[counter])+1;
			karguments[counter] = (char *) kmalloc(sizeof(char) * string_length);
			result = copyinstr((const_userptr_t) ar[counter],karguments[counter],string_length,&actual_lenght1);
			if(result)
			{
				kfree(kname);
				kfree(arguments_kernel);
				return result;
			}

			counter++;
		}
		karguments[counter] = NULL;

		result = vfs_open(kname, O_RDONLY, 0, &p_vnode);
		if (result) {
			return result;
		}

		as_destroy(curthread->t_addrspace);

		//Create a new address space.
		curthread->t_addrspace = as_create();
		if (curthread->t_addrspace==NULL)
		{
			vfs_close(p_vnode);
			return ENOMEM;
		}

		//Activate it.
		as_activate(curthread->t_addrspace);

		/* Load the executable. */
		result = load_elf(p_vnode, &entrypoint);
		if (result)
		{
			/* thread_exit destroys curthread->t_addrspace */
			vfs_close(p_vnode);
			return result;
		}

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

		//Get the pointer to the stack starting
		result = as_define_stack(curthread->t_addrspace, &stackptr);
		if (result)
		{
			/* thread_exit destroys curthread->t_addrspace */
			return result;
		}

		//Now copy the arguments
		int count =0;
		char **karray= kmalloc(sizeof(char**));
		size_t final_stack=0;

		while(karguments[count] != NULL)
		{
			int string_length = strlen(karguments[count])+1;
			char *k_des= karguments[count];

			int new_length = string_length;
			if((string_length) % 4 != 0)
			{
				while(new_length%4 !=0)
				{
					new_length++;
				}
				for(int i=string_length;i<=new_length;i++)
				{
					k_des[i]= '\0';
				}
			}

			//Argument aligned by 4

			size_t final_length= (size_t)new_length;

			if(count==0)
			{
				final_stack= stackptr- final_length;
			}
			else
			{
				final_stack= (size_t)karray[count-1]- final_length;
			}

			size_t actual_length1;
			result= copyoutstr(k_des, (userptr_t) (final_stack), final_length, &actual_length1);
			if(result)
			{
				return result;
			}

			karray[count]=  (char*)(final_stack);

			count++;
		} //End of While

		karray[count]= (char*)NULL;
		int value= count+1;
		int arr_length = (value+1)*sizeof(char*);
		final_stack= (size_t)karray[count-1]- arr_length;
		result= copyout(karray, (userptr_t) (final_stack),arr_length);
		if(result)
		{
			return result;
		}


			/* Warp to user mode. */
				enter_new_process(count /*argc*/, (userptr_t)(final_stack) /*userspace addr of argv*/,
						final_stack, entrypoint);

		return 0;
}
Exemplo n.º 4
0
int sys_execv(char* program, char** args) {
	int result;

	char name[strlen(program) + 1];
	result = copyin((userptr_t) program,
				name, (strlen(program) + 1) * sizeof(char));
	//kprintf("%s", name);

	int len_arg = 0;
	while(args[len_arg] != NULL) {
		len_arg++;
	}

	int length_every_arg[len_arg];
	for(int i = 0; i < len_arg; i++) {
		length_every_arg[i] = strlen(args[i]);
	}

	char* kern_args[len_arg];
	for(int i = 0; i < len_arg; i++) {
		kern_args[i] = kmalloc(sizeof(char) * length_every_arg[i] + 1);
		copyin((const_userptr_t)args[i], kern_args[i],
              (length_every_arg[i] + 1) * sizeof(char));
	}
/*
	for(int i = 0; i < len_arg; i++) {
		kprintf("{ _%d__%p__%p_",strlen(kern_args[i]), kern_args[i],args[i]);
		kprintf("%s", kern_args[i]);
		kprintf("}\n");
	}
*/
/////////////////////////////////////////////////////
// this is "copied" from runprogram
  	struct addrspace* old_as;
	struct vnode* v;
	vaddr_t entrypoint, stackptr;

	result = vfs_open(program, O_RDONLY, 0, &v);
	if(result) {
		return result;
	}

	as_deactivate();
	old_as = curproc_setas(NULL);
	as_destroy(old_as);

	struct addrspace* new_as = as_create();
	if(new_as == NULL) {
		vfs_close(v);
		return ENOMEM;
	}
	curproc_setas(new_as);
	as_activate();

	result = load_elf(v, &entrypoint);
	if(result) {
		vfs_close(v);
		return result;
	}

	vfs_close(v);
	
	result = as_define_stack(new_as, &stackptr);
	if(result) {
		return result;
	}
//////////////////////////////////////////////////////////
// kern_args
// the addr of stackptr is 0x8000 0000
	vaddr_t argv = stackptr;
	for(int i = 0; i < len_arg + 1; i++) {
		argv = argv - 4;
	}
   
	vaddr_t start = argv;
	vaddr_t temp = argv;

	copyout(NULL, (userptr_t)(stackptr - 4), 4);
	//starts from 1, because argv[0] is reserved for the program name
	for(int i = 0; i < len_arg; i++) {
		//question? why do I have to add 2
		int m = sizeof(char) * (strlen(kern_args[i]) + 1);
	//	kprintf("the value of m -> %d\n", m);
		argv = argv - m;
		copyout(kern_args[i], (userptr_t)argv, m);
	//	kprintf("***(%d)%s(%p)\n***", m, (char* )argv, (void *) argv);
		copyout(&argv, (userptr_t)temp, sizeof(char* ));
		temp = temp + 4;
	}
	
	for(int i = 0; i < len_arg; i++) {
		kfree(kern_args[i]);
	}
	
	while(argv % 8 != 0) {argv--;}
	 
	enter_new_process(len_arg, (userptr_t)start, (vaddr_t) argv, entrypoint);

//	enter_new_process(0, NULL, stackptr, entrypoint);
	panic("enter_new_process returned");
	return EINVAL;
}
Exemplo n.º 5
0
int 
sys_execv(userptr_t progname, userptr_t args){ /*This function implements the execv functionality*/
    size_t get, offset;
    struct vnode *v;
    vaddr_t entrypoint, stackptr;
    userptr_t userdest;
    int i=0, append_zero, argc=0, result, part=0;
    char *buf_mem;
    int n=0;
    struct addrspace *old_addr = curthread->t_vmspace;
    char **usr_args = (char**)args;
    buf_mem = (void *) kmalloc(sizeof(void *));
    result = copyin((const_userptr_t)args,buf_mem,4);
    if (result){
        kfree(buf_mem);
        return result;
    }

   lock_acquire(execv_lock);


    kfree(buf_mem);


    while(usr_args[argc] != NULL){
        argc++;
    }
    size_t len_string[argc];
    userptr_t user_argv[argc];

    char *args_buf = kmalloc(PAGE_SIZE*sizeof(char));

    // Check user pointer
    buf_mem = (char *)kmalloc(1024*sizeof(char));
    if (buf_mem == NULL){
        result = ENOMEM;
        kfree(args_buf);
    }
    

    result = copyinstr((const_userptr_t)progname,buf_mem,1024,&get);
    if (result){
        kfree(buf_mem);
    }
	//Implementation from runprogram from here
    /* Open the file. */
    result = vfs_open((char *)progname, O_RDONLY, &v);
    if (result) {
        kfree(buf_mem);
    }
    // Keep old addrspace in case of failure
    struct addrspace *new_addr = as_create();
    if (new_addr == NULL){
        result = ENOMEM;
        vfs_close(v);
    }
    while (usr_args[i] != NULL){
        result = copyinstr((const_userptr_t)usr_args[i], &args_buf[part], PAGE_SIZE, &len_string[i]);
        if (result){
            as_destroy(new_addr);
        }
        part += len_string[i];
        i++;
    }
    /* Swap addrspace and Activate it*/
    curthread->t_vmspace = new_addr;
    as_activate(curthread->t_vmspace);

    /* Load the executable. */
    result = load_elf(v, &entrypoint);
    if (result) {
        curthread->t_vmspace = old_addr;
        as_activate(curthread->t_vmspace);
    }
    /* Define the user stack in the address space */
    result = as_define_stack(curthread->t_vmspace, &stackptr);
    if (result) {
        curthread->t_vmspace = old_addr;
        as_activate(curthread->t_vmspace);
    }

    // Copy args to new addrspace
    offset = 0;
    for (i=argc-1; i>-1; i--){
        part -= len_string[i]; // readjust inherited part index
        append_zero = (4 - (len_string[i]%4) ) % 4; // Word align
        offset += append_zero;
        offset += len_string[i];

        user_argv[i] = (userptr_t)(stackptr - offset);

        result = copyoutstr((const char*)&args_buf[part], user_argv[i], len_string[i], &get);
        if (result){
        curthread->t_vmspace = old_addr;
        as_activate(curthread->t_vmspace);
        }
    }

    // Copy pointers to argv
    userdest = user_argv[0] - 4 * (argc+1);
    stackptr = (vaddr_t)userdest; // Set stack pointer
    for (i=0; i<argc; i++){
        result = copyout((const void *)&user_argv[i], userdest, 4);
        if (result)
        curthread->t_vmspace = old_addr;
        as_activate(curthread->t_vmspace);
        userdest += 4;
    }

    // Wrap up
    kfree(args_buf);
    vfs_close(v);



    /* Warp to user mode. */
    md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint);


	lock_release(execv_lock);
    	return EINVAL;

}
Exemplo n.º 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, char **args, int nargs)
{

    struct vnode *v;
    vaddr_t entrypoint, stackptr, arguments[nargs+1], exactnewstackptr;
    int result, i; 
    size_t len, offset = 0;


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

    /* We should be a new thread. */
    assert(curthread->t_vmspace == NULL);

    /* Create a new address space. */
    struct addrspace * old_vmspace = curthread->t_vmspace;
    curthread->t_vmspace = as_create();
    if (curthread->t_vmspace==NULL) {
        vfs_close(v);
        return ENOMEM;
    }

    /* Activate it. */
    as_activate(curthread->t_vmspace);

    /* Load the executable. */
    result = load_elf(v, &entrypoint);
    if (result) {
        /* thread_exit destroys curthread->t_vmspace */
        curthread->t_vmspace = old_vmspace;
        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(curthread->t_vmspace, &stackptr);
    if (result) {
        /* thread_exit destroys curthread->t_vmspace */
        curthread->t_vmspace = old_vmspace;
        return result;
    }

    if(old_vmspace){
        as_destroy(old_vmspace);
    }

    for (i = 0; i < nargs; i++)
    {
        len = strlen(args[i]) + 1;
        offset += len;
        arguments[i] = stackptr - offset;
        copyout((void *)args[i], (userptr_t) arguments[i], (size_t) len);
    }

    arguments[nargs] = 0;

    offset += sizeof(vaddr_t) * (nargs+1);

    exactnewstackptr = stackptr - offset;

    stackptr = exactnewstackptr - exactnewstackptr%4;

    copyout((void *) arguments, (userptr_t) stackptr, (size_t) sizeof(vaddr_t) * (nargs+1));
    
    md_usermode(nargs, (userptr_t) stackptr, stackptr, entrypoint);

    panic("md_usermode returned\n");

    return EINVAL;
}
Exemplo n.º 7
0
int sys_execv(const char *prog, char **userArgs) {
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int res = 0;
	int length = 0;
	int index = 0;

	lock_acquire(allProcLock);
	char *progname;
	size_t size;
	progname = (char *) kmalloc(sizeof(char) * PATH_MAX);
	res = copyinstr((const_userptr_t) prog, progname, PATH_MAX, &size);
	char **args = (char **) kmalloc(sizeof(char **));
	res = copyin((const_userptr_t)userArgs, args, sizeof(char **));

	while (userArgs[index] != NULL) {
		args[index] = (char *) kmalloc(sizeof(char) * PATH_MAX);
		res = copyinstr((const_userptr_t) userArgs[index], args[index], PATH_MAX, &size);
		index++;
	}
	args[index] = NULL;
	index = 0;

	res = vfs_open(progname, O_RDONLY, 0, &v);

	struct addrspace *temp;
	temp = curproc->p_addrspace;

	if(curproc->p_addrspace != NULL){
		as_destroy(curproc->p_addrspace);
		curproc->p_addrspace = NULL;
	}

	KASSERT(curproc->p_addrspace == NULL);

	if((curproc->p_addrspace = as_create()) == NULL){
		kfree(progname);
		kfree(args);
		vfs_close(v);
		return ENOMEM;
	}

	as_activate();

	res = load_elf(v, &entrypoint);
	vfs_close(v);

	res = as_define_stack(curproc->p_addrspace, &stackptr);

	while(args[index] != NULL) {
		char * arg;
		length = strlen(args[index]) + 1;
		int orignalLength = length;
		if(length % 4 != 0) {
			length = length + (4 - length % 4);
		}
		arg = kmalloc(sizeof(length));
		arg = kstrdup(args[index]);

		for(int i = 0; i < length; i++){
			if(i >= orignalLength){
				arg[i] = '\0';
			}
			else{
				arg[i] = args[index][i];
			}
		}
		stackptr -= length;
		res = copyout((const void *) arg, (userptr_t) stackptr, (size_t) length);
		kfree(arg);
		args[index] = (char *) stackptr;
		index++;
	}
	if(args[index] == NULL){
		stackptr -= 4 * sizeof(char);
	}

	for(int i = (index - 1); i >= 0; i--) {
		stackptr = stackptr - sizeof(char*);
		res = copyout((const void *) (args + i), (userptr_t) stackptr, sizeof(char*));
	}
	kfree(progname);
	kfree(args);
	lock_release(allProcLock);
	enter_new_process(index, (userptr_t) stackptr, stackptr, entrypoint);
	return EINVAL;

}
Exemplo n.º 8
0
int execv(const char *program, char **args)
{
	//    kprintf("\n\n execv testing \n\n") ;
    	if (program == NULL )
        {
		return EFAULT ;
	}
	//char * kernel_pgm = (char *)kmalloc(sizeof(char *)) ;
	char * kernel_pgm = (char *)kmalloc(__PATH_MAX) ;
	
	size_t bytes_copied  ;
	int result = copyinstr((const userptr_t)program,kernel_pgm,__PATH_MAX,&bytes_copied) ;

	if (result )
	{
		return result ;
	}

	if (strlen(kernel_pgm) == 0)
	{
		return EINVAL ;
	}
	if (strlen(kernel_pgm) >= __PATH_MAX)
	{
		return ENAMETOOLONG ;
	}
	int argc = 0 ;
	if (args == NULL)
	{
		return EFAULT ;
	}
	char *temp1 = (char *)kmalloc(ARG_MAX*sizeof(char)) ;
        result = copyinstr((const userptr_t)args,temp1,ARG_MAX*sizeof(char),&bytes_copied) ;
        if(result){
                return result;
        }
        kfree(temp1);
    while(args[argc]!=NULL)                                                 //while (true)
    {
     	char *temp = (char *)kmalloc(ARG_MAX*sizeof(char)) ;
        result = copyinstr((const userptr_t)args[argc],temp,ARG_MAX*sizeof(char),&bytes_copied) ;
        if (result)
        	{
            	kfree(temp);
                return EFAULT ;//break ;
            }
            argc++ ;
            kfree(temp) ;
        }
	char **temp = (char **)kmalloc(argc*sizeof(char *)) ;
	
	int i = 0 ;
	while(i<argc)
	{
		temp[i] = (char *)kmalloc(ARG_MAX*sizeof(char)) ;
		result = copyinstr((const userptr_t)args[i],temp[i],ARG_MAX*sizeof(char),&bytes_copied) ;
		if (result)
		{
			return result ;
		}
		i++ ;
	}
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	result = vfs_open(kernel_pgm, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

	struct addrspace *addrspace_copy=curthread->t_addrspace;
	if(curthread->t_addrspace != NULL){
		as_destroy(curthread->t_addrspace);
		curthread->t_addrspace = NULL;
	}
	//struct addrspace *addrspace_copy=curthread->t_addrspace;
	curthread->t_addrspace = as_create();
	if (curthread->t_addrspace==NULL) {
		vfs_close(v);
		curthread->t_addrspace = addrspace_copy;
		return ENOMEM;
	}
	as_activate(curthread->t_addrspace);
	result = load_elf(v, &entrypoint);
	if (result) {
		vfs_close(v);
		return result;
	}
	vfs_close(v);
	result = as_define_stack(curthread->t_addrspace, &stackptr);
	if (result) {
		return result;
	}
	i = i -1 ;
	vaddr_t index[25] ;
	int k = 0 ;
	while(i>= 0)
	{
		int length = strlen(temp[i]) ;
		int num0 = (4 - (length % 4)) ;
		int j = 0 ;
		char *temp1 = (char *)kmalloc((length+num0)*sizeof(char)) ;
		strcpy(temp1,temp[i]) ;
		while(j<num0)
		{
			strcat(temp1,"\0") ;
			j++ ;
		}
		stackptr = stackptr - ((length+num0)*sizeof(char)) ;
		result = copyoutstr(temp1,(userptr_t) stackptr,(length+num0)*sizeof(char),&bytes_copied) ;
		if (result)
		{
			return result ;
		}
		index[k] = (vaddr_t )stackptr;
		k++ ;
		i-- ;
		kfree(temp1) ;
	}
	i = 0 ;
	stackptr = stackptr - sizeof(int) ;
	stackptr = stackptr - sizeof(int) ;
	k-- ;
	while(i<=k)
	{
		result = copyout(&index[i],(userptr_t) stackptr,sizeof(int)) ;
		if (result)
		{
			return result ;
		}
		i++ ;
		if (i<=k){
			stackptr = stackptr - sizeof(int) ;
		}
	}
	kfree(temp) ;
	kfree(kernel_pgm) ;
	enter_new_process(argc,(userptr_t) stackptr , stackptr, entrypoint);
	panic("enter_new_process returned\n");
	return EINVAL;
}																																																																																																    
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
int
sys_execv(const char *progname, char**args) {
    kprintf("hello world");
    struct vnode *v;
    vaddr_t entrypoint, stackptr;
    int result;
    int argc = getargc(args);

    /* Copy the arguments into the kernel buffer */
    char** kbuffer = kmalloc(argc*sizeof(char*));
    int i;
    for (i=0; i<argc; i++) {
        kbuffer[i] = kmalloc(strlen(args[i])*sizeof(char*)+1);
        copyinstr(args[i], kbuffer[i], strlen(args[i])*sizeof(char*)+1, NULL);
    }
    
    args = kbuffer;
    
    /* Open the file. */
    result = vfs_open(progname, O_RDONLY, &v);
    if (result) {
        return result;
    }

    /* This is not the first process, we have to make sure
     the previous process address space is not NULL. */
    assert(curthread->t_vmspace != NULL);

    /* Destroy the old process address space */
    as_destroy(curthread->t_vmspace);

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

    /* Activate it. */
    as_activate(curthread->t_vmspace);

    /* Load the executable. */
    result = load_elf(v, &entrypoint);
    if (result) {
        /* thread_exit destroys curthread->t_vmspace */
        vfs_close(v);
        return result;
    }

    /* Done with the file now. */
    vfs_close(v);
    /* Free the current process user stack */
    kfree(curthread->t_stack);

    /* Define the user stack in the address space */
    result = as_define_stack(curthread->t_vmspace, &stackptr);
    if (result) {
        /* thread_exit destroys curthread->t_vmspace */
        return result;
    }
    
    /* copy arguments to user space */
    char **args_u; /* user space arguments.(array of ptrs
                   to string arguments.*/
    /* string length of the arguments */
    size_t argstrlen = getlen(argc, args);
    /* address space for the string arguments value. */
    char* arg_str = (char *) stackptr - argstrlen;
    /* address space for the pointers to string arguments. */
    args_u = (char **) arg_str - (argc + 1) * sizeof (char**);
    /* adjust the address so that its divisable by 4 */
    args_u = (int) args_u - (int) args_u % 4;

    /* copy the arguments to the user address space */
    int len;
    for (i = 0; i < argc; i++) {
        /* copy a single argument  to the user address space */
        copyoutstr(args[i], (userptr_t) arg_str, strlen(args[i]) + 1, &len);
        /* set the user argument to the current argument string pointer */
        args_u[i] = arg_str;
        /* increment the argument pointer to the next argument */
        arg_str += (strlen(args[i]) + 1) * sizeof (char);
    }
    /* set the n+1th argument to be NULL */
    args_u[argc] = NULL;
    /* set the stackptr to the starting point of args_u and adjust the stack pointer */
    stackptr = args_u - sizeof (char**) - ((int)args_u%8);

    /* Warp to user mode. */
    md_usermode(argc, (userptr_t) args_u, stackptr, entrypoint);
    /*********************** end of A2 stuff *****************/

    /* md_usermode does not return */
    panic("md_usermode returned\n");
    return EINVAL;
}
Exemplo n.º 11
0
int sys_execv(const char *prog_path, char **args) {
	int spl = splhigh();
	// the prog_path is in user space, we need to copy it into kernel space
	if(prog_path == NULL) {
		return EINVAL;
	}
	// frist the program path
	char* program = (char *) kmalloc(MAX_PATH_LEN * sizeof(char));
	int size;
	int result = copyinstr((const_userptr_t) prog_path, program, MAX_PATH_LEN, &size);
	if(result) {
		kfree(program);
		return EFAULT;
	}
	// arguments
	char** argv = (char**) kmalloc(sizeof(char**));
	// char** argv;
	result = copyin((const_userptr_t)args, argv, sizeof(char **));
	if(result) {
		kfree(program);
		kfree(argv);
		return EFAULT;
	}
	// count the number of arguments
	int i = 0;
	while(args[i] != NULL){
		argv[i] = (char*) kmalloc(sizeof(char) * MAX_ARG_LEN);
		if(copyinstr((const_userptr_t) args[i], argv[i], MAX_ARG_LEN, &size) != 0) {
			return EFAULT;
		}
		i++;
	}
	argv[i] = NULL;
	// runprogram_exev_syscall(program, argv, i);
	/*********************** runprogram starts*****************/

	struct vnode *v;
	vaddr_t entrypoint, stackptr;	

	result = vfs_open(program, O_RDONLY, &v);

	if (result) {
		return result;
	}

	// destroy the old addrspace
	if(curthread->t_vmspace != NULL){
		as_destroy(curthread->t_vmspace);
		curthread->t_vmspace = NULL;
	}

	assert(curthread->t_vmspace == NULL);

	// Create a new address space. 
	curthread->t_vmspace = as_create();
	if (curthread->t_vmspace==NULL) {
		vfs_close(v);
		return ENOMEM;
	}

	// Activate it. 
	as_activate(curthread->t_vmspace);

	// Load the executable. 
	result = load_elf(v, &entrypoint); // Load an ELF executable user program into the current address space and
	// returns the entry point (initial PC) for the program in ENTRYPOINT.
	if (result) {
		vfs_close(v);
		return result;
	}
	vfs_close(v);

	result = as_define_stack(curthread->t_vmspace, &stackptr);
	if (result) {
		// thread_exit destroys curthread->t_vmspace 
		return result;
	}

	int narg = i - 1;
	int j;
	for(j = 0; j < narg; ++j){
	    int len = 1 + strlen(argv[j]);
	    len = ROUNDUP(len, 8);
		stackptr -= len;

		result = copyoutstr(argv[j],(userptr_t)stackptr, len, &len); 
		if(result){
			return result;
		}	
		argv[j] = (char*)stackptr;
    }

    argv[i] = NULL;
    size_t arg_size = (narg + 1) * sizeof(char*);
    arg_size = ROUNDUP(arg_size, 8);
    // align the stackptr to 8 byte aligned
    stackptr -= arg_size;
    // stackptr -= stackptr % 8;

    copyout(argv, stackptr, (narg + 1) * 4);
	md_usermode(i, stackptr, stackptr, entrypoint); 
	panic("md_usermode returned\n");
	return EINVAL;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
/*
 * runprogram is run from menu, and its arguments 
 * are passed by thread_fork (a ptr & a int)
 * so we need to construct a struct to store progname and args
 */
int
runprogram(struct runprogram_info *prog_info)
{
	char *progname = prog_info->progname;

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

	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, &v);
	if (result) {
		return result;
	}
	
	/*
	 * if runprogram is called by sys_execv, it is for sure that 
	 * curthread has its own user addr_space already.
	 * we need to destroy it.
	 * if runprogram is called by menu, there is no addrspace created.  
	 */
	// ===========================================
	struct addrspace *old_as = curthread->t_vmspace;
	if (old_as != NULL) {
		as_destroy(old_as);
		curthread->t_vmspace = NULL;
	}
	// ===========================================

	/* We should be a new thread. */
	assert(curthread->t_vmspace == NULL);

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

	/* Activate it. */
	as_activate(curthread->t_vmspace);

	/* Load the executable. */
	// entrypoint is set by load_elf
	result = load_elf(v, &entrypoint);
	
	// ===========================================
	/*
	 * in dumbvm, we only need to set up the addrspace for stack
	 * now, we need to load stack (set up page table, without dealing with the content)
	 */
	// ===========================================
	
	if (result) {
		/* thread_exit destroys curthread->t_vmspace */
		// which means runprogram is called by some other function, 
		// and when it returns, thread_exit will be called outside runprogram
		// that's why runprom should not return
		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(curthread->t_vmspace, &stackptr);
	if (result) {
		/* thread_exit destroys curthread->t_vmspace */
		return result;
	}
	// ============================================
	size_t len;
	void *ks_start = setup_args_mem(prog_info, &stackptr, &len);
	int err = copyout(ks_start, stackptr, len);
	if (err != 0) {
		panic("runprogram: copyout err!\n");
	}
	/*
	int i;
	for (i = 0; i < len/4; i++) {
		//i in terms of word
		//kfree will free 4 bytes at a time?
		kfree((int *)((int *)ks_start+i));
	}
	*/
	kfree(ks_start);
	//kprintf("copyout result: %d\n", err);
	// ============================================
	/* Warp to user mode. */
	int nargc = prog_info->argc;
	kfree(prog_info);
	//cmd_coremapstats(1, NULL);
	md_usermode(nargc /*argc*/, stackptr /*userspace addr of argv*/,
		    stackptr, entrypoint);
	
	/* md_usermode does not return */
	panic("md_usermode returned\n");
	return EINVAL;
}
Exemplo n.º 14
0
/*
 * Function called when user-level code hits a fatal fault.
 */
static
void
kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
{
    int sig = 0;

    KASSERT(code < NTRAPCODES);
    switch (code) {
    case EX_IRQ:
    case EX_IBE:
    case EX_DBE:
    case EX_SYS:
        /* should not be seen */
        KASSERT(0);
        sig = SIGABRT;
        break;
    case EX_MOD:
    case EX_TLBL:
    case EX_TLBS:
        sig = SIGSEGV;
        break;
    case EX_ADEL:
    case EX_ADES:
        sig = SIGBUS;
        break;
    case EX_BP:
        sig = SIGTRAP;
        break;
    case EX_RI:
        sig = SIGILL;
        break;
    case EX_CPU:
        sig = SIGSEGV;
        break;
    case EX_OVF:
        sig = SIGFPE;
        break;
    }

    /*
     * You will probably want to change this.
     */
#if OPT_A3
    //supposed to be similar to sys_exit
    (void)epc;
    (void)vaddr;
    struct addrspace *as;
    struct proc *p = curproc;
    as_deactivate();
    as = curproc_setas(NULL);
    as_destroy(as);
    proc_remthread(curthread);
    proc_destroy(p);
    thread_exit();
    panic("Should not have returned here!\n");

#else

    kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n",
            code, sig, trapcodenames[code], epc, vaddr);
    panic("I don't know how to handle this\n");
#endif
}
Exemplo n.º 15
0
int
as_copy(struct addrspace *old, struct addrspace **ret)
{
    struct addrspace *newas;

    newas = as_create();
    if (newas==NULL) {
        return ENOMEM;
    }

    //	kprintf(" **** inside as copy ****  \n");
    //	spinlock_acquire(newas->as_splock);
    //	spinlock_acquire(old->as_splock);

    if(use_small_lock == true && swapping_started == true)
    {
        lock_acquire(newas->as_lock);
        lock_acquire(old->as_lock);
    }
    else if(use_big_lock == true && swapping_started == true)
        lock_acquire(as_lock);
    struct as_region* r_old = old->as_region_list;
    while(r_old != NULL)
    {
        struct as_region* r_new = (struct as_region*)kmalloc(sizeof(struct as_region));
        if(r_new == NULL)
        {
            if(use_big_lock == true && swapping_started == true)
                lock_release(as_lock);
            else if(use_small_lock == true && swapping_started == true)
            {
                lock_release(old->as_lock);
                lock_release(newas->as_lock);
            }
            //spinlock_release(old->as_splock);
            //spinlock_release(newas->as_splock);
            as_destroy(newas);
            return ENOMEM;
        }

        r_new->region_base = r_old->region_base;
        r_new->region_npages = r_old->region_npages;
        r_new->can_read = r_old->can_read;
        r_new->can_write = r_old->can_write;
        r_new->can_execute = r_old->can_execute;

        int ret = region_list_add_node(&newas->as_region_list,r_new);
        if(ret == -1)
        {
            if(use_big_lock == true && swapping_started == true)
                lock_release(as_lock);
            else if(use_small_lock == true  && swapping_started == true)
            {
                lock_release(old->as_lock);
                lock_release(newas->as_lock);
            }
            //	spinlock_release(old->as_splock);
            //	spinlock_release(newas->as_splock);
            as_destroy(newas);
            return ENOMEM;
        }
        r_old = r_old->next;
    }

    struct page_table_entry* p_old = old->as_page_list;
    while(p_old != NULL)
    {
        struct page_table_entry* p_new = (struct page_table_entry*)kmalloc(sizeof(struct page_table_entry));
        if(p_new == NULL)
        {
            if(use_big_lock == true && swapping_started == true)
                lock_release(as_lock);
            else if(use_small_lock == true && swapping_started == true)
            {
                lock_release(old->as_lock);
                lock_release(newas->as_lock);
            }
            //		spinlock_release(old->as_splock);
            //		spinlock_release(newas->as_splock);
            as_destroy(newas);

            return ENOMEM;
        }
        p_new->vaddr = p_old->vaddr;
        p_new->swap_pos = -1;

        KASSERT(p_old->page_state != SWAPPING);
        while(p_old->page_state == SWAPPING)
        {

            thread_yield();

        }

        //	if(!spinlock_do_i_hold)
        //	KASSERT(p_old->page_state != SWAPPING);

        if(p_old->page_state == MAPPED)
        {
            if(use_page_lock == true && swapping_started == true)
                lock_acquire(coremap[(p_old->paddr)/PAGE_SIZE].page_lock);

            if(p_old->page_state == MAPPED)
            {
                paddr_t paddr = get_user_page(p_old->vaddr, false, newas);
                KASSERT(p_old->page_state == MAPPED);
                //	int spl = splhigh();
                if(use_small_lock == true && swapping_started == true)
                {
                    if(lock_do_i_hold(newas->as_lock) == false)
                        lock_acquire(newas->as_lock);
                    if(lock_do_i_hold(old->as_lock) == false)
                        lock_acquire(newas->as_lock);
                }
                else if(use_big_lock == true && swapping_started == true)
                {
                    if(lock_do_i_hold(as_lock) == false)
                        lock_acquire(as_lock);
                }
                if(paddr == 0)
                {
                    if(use_big_lock == true && swapping_started == true)
                        lock_release(as_lock);
                    else if(use_small_lock == true && swapping_started == true)
                    {
                        lock_release(old->as_lock);
                        lock_release(newas->as_lock);
                    }
                    //				spinlock_release(old->as_splock);
                    //				spinlock_release(newas->as_splock);
                    as_destroy(newas);
                    return ENOMEM;
                }
                uint32_t old_index = p_old->paddr/PAGE_SIZE;
                KASSERT(coremap[old_index].is_victim == false);
                KASSERT(coremap[paddr/PAGE_SIZE].is_victim == false);
                memmove((void*)PADDR_TO_KVADDR(paddr),
                        (const void *)PADDR_TO_KVADDR(p_old->paddr), //use this? or PADDR_TO_KVADDR like dumbvm does?. But why does dumbvm do that in the first place.
                        PAGE_SIZE);									// i know why, cannot call functions on user memory addresses. So convert it into a kv address.
                // the function will translate it into a physical address again and free it. ugly Hack. but no other way.

                p_new->paddr = paddr;
                p_new->page_state = MAPPED;

                //	splx(spl);

                int ret = page_list_add_node(&newas->as_page_list,p_new);
                if(ret == -1)
                {
                    if(use_big_lock == true && swapping_started == true)
                        lock_release(as_lock);
                    else if(use_small_lock == true && swapping_started == true)
                    {
                        lock_release(old->as_lock);
                        lock_release(newas->as_lock);
                    }
                    //			spinlock_release(old->as_splock);
                    //			spinlock_release(newas->as_splock);
                    as_destroy(newas);
                    return ENOMEM;
                }

                if(use_page_lock == true && swapping_started == true)
                {

                    if(lock_do_i_hold(coremap[paddr/PAGE_SIZE].page_lock) == true)
                        lock_release(coremap[paddr/PAGE_SIZE].page_lock);


                    if(lock_do_i_hold(coremap[(p_old->paddr/PAGE_SIZE)].page_lock) == true)
                        lock_release(coremap[(p_old->paddr/PAGE_SIZE)].page_lock);
                }

            }
        }

        if(p_old->page_state == SWAPPED)
        {
            // this page is in disk, so we need to create a copy of that page somewhere in disk and then update the page table entry of the new process.
            // going with the disk->memory->disk approach suggested in a recitation video by jinghao shi.
            // Allocate a buffer at vm_bootstrap of size 4k (1 page). Use this buffer to temporarily copy data from disk to here and then to disk again
            // then clear the buffer. This buffer is a shared resource, so we need a lock around it.

            //	kprintf("in as_copy swap code \n");
            //	spinlock_release(old->as_splock);
            //	spinlock_release(newas->as_splock);
            swap_in(p_old->vaddr,old,copy_buffer_vaddr, p_old->swap_pos);
            //	kprintf("completed swap in \n");
            int pos = mark_swap_pos(p_new->vaddr, newas);
            KASSERT(pos != -1);
            int err = write_to_disk(KVADDR_TO_PADDR(copy_buffer_vaddr)/PAGE_SIZE, pos);
            //	kprintf("completed writing to disk \n");
            KASSERT(err == 0);
            //		spinlock_acquire(newas->as_splock);
            //		spinlock_acquire(old->as_splock);
            //	as_zero_region(KVADDR_TO_PADDR(copy_buffer_vaddr),1);
            p_new->page_state = SWAPPED;
            p_new->swap_pos = pos;
            p_new->paddr = 0;


            if(use_page_lock == true && swapping_started == true)
            {

                if(lock_do_i_hold(coremap[(p_old->paddr/PAGE_SIZE)].page_lock) == true)
                    lock_release(coremap[(p_old->paddr/PAGE_SIZE)].page_lock);
            }
        }
        p_old = p_old->next;

    }

    newas->as_heap_start = old->as_heap_start;
    newas->as_heap_end = old->as_heap_end;
    *ret = newas;


    if(use_big_lock == true && swapping_started == true)
        lock_release(as_lock);
    else if(use_small_lock == true && swapping_started == true)
    {
        lock_release(old->as_lock);
        lock_release(newas->as_lock);
    }

//	kprintf("exiting as copy \n");
    //	spinlock_release(old->as_splock);
    //	spinlock_release(newas->as_splock);
    return 0;
}
Exemplo n.º 16
0
/*
 * Function called when user-level code hits a fatal fault.
 */
static
void
kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
{
	int sig = 0;

	KASSERT(code < NTRAPCODES);
	switch (code) {
	    case EX_IRQ:
	    case EX_IBE:
	    case EX_DBE:
	    case EX_SYS:
			/* should not be seen */
			KASSERT(0);
			sig = SIGABRT;
			break;
	    case EX_MOD:
	    case EX_TLBL:
	    case EX_TLBS:
			sig = SIGSEGV;
			break;
	    case EX_ADEL:
	    case EX_ADES:
			sig = SIGBUS;
			break;
	    case EX_BP:
			sig = SIGTRAP;
			break;
	    case EX_RI:
			sig = SIGILL;
			break;
	    case EX_CPU:
			sig = SIGSEGV;
			break;
	    case EX_OVF:
			sig = SIGFPE;
			break;
	}

	/*
	 * You will probably want to change this.
	 */

	#if OPT_A3
	 (void)epc;
	 (void)vaddr;
		  struct addrspace *as;
		  struct proc *p = curproc;
		  

		    int parentLocation = locatePid(p->p_pid);
		    struct procStruct *parentProcStr = array_get(procStructArray, parentLocation);
		    parentProcStr->exitcode = _MKWAIT_SIG(sig);
		    cleanChildren(parentLocation);

		    V(parentProcStr->proc_sem);

		  KASSERT(curproc->p_addrspace != NULL);
		  as_deactivate();
		  /*
		   * clear p_addrspace before calling as_destroy. Otherwise if
		   * as_destroy sleeps (which is quite possible) when we
		   * come back we'll be calling as_activate on a
		   * half-destroyed address space. This tends to be
		   * messily fatal.
		   */
		  as = curproc_setas(NULL);
		  as_destroy(as);

		  /* detach this thread from its process */
		  /* note: curproc cannot be used after this call */
		  proc_remthread(curthread);

		  /* if this is the last user process in the system, proc_destroy()
		     will wake up the kernel menu thread */
		  proc_destroy(p);
		  
		  thread_exit();
		  /* thread_exit() does not return, so we should never get here */
		  panic("return from thread_exit in sys_exit\n");
	#else

		kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n",
			code, sig, trapcodenames[code], epc, vaddr);
		panic("I don't know how to handle this\n");
	#endif
}
Exemplo n.º 17
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;
}