Exemplo n.º 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");
}
Exemplo n.º 2
0
void sys__exit(int exitcode) {

  struct addrspace *as;
  struct proc *p = curproc;
  /* for now, just include this to keep the compiler from complaining about
     an unused variable */
  (void)exitcode;

  DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);

  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");
}
Exemplo n.º 3
0
  /* this needs to be fixed to get exit() and waitpid() working properly */
void sys__exit(int exitcode, int type) {
  struct addrspace *as;
  struct proc *p = curproc;

  DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);
  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);


  lock_acquire(p->proc_exit_lock);

 
 if(!p->proc_parent_exited && p->pid > 1){
	

	// Parent didnt exit yet, so we must only semi-destroy the proc
	proc_set_exit_status(p,exitcode, type);

	
	cv_broadcast(p->proc_exit_cv, p->proc_exit_lock);


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


        proc_remthread(curthread);
	// semi_destroy will release the proc_exit_lock for us.


	proc_semi_destroy(p);


 	lock_release(p->proc_exit_lock);
  }else{
	proc_exited_signal(p);
	lock_release(p->proc_exit_lock);
  	/* 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");
}
Exemplo n.º 4
0
/*
void free_root(struct procinfo* pi){
  KASSERT(pi != NULL);
  if (pi->parent_pid == -1){
    array_set(proc)
  }
  
}*/
void sys__exit(int exitcode) {

  struct addrspace *as;
  struct proc *p = curproc;
  /* for now, just include this to keep the compiler from complaining about
     an unused variable */
  #if OPT_A2
  
  struct procinfo *pi = array_get(procinfotable, p->pid-1);
  
  if(pi == NULL){
    goto parentexited;
  }

  lock_acquire(p->p_waitpid_lock);
  
  pi->exit_code = _MKWAIT_EXIT(exitcode);
  pi->active = 0;
  cv_broadcast(pi->waitpid_cv,p->p_waitpid_lock);

  lock_release(p->p_waitpid_lock);

  free_children(p->pid);
  
parentexited:  
  #else

  (void)exitcode;

  #endif
  DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);

  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");
}
Exemplo n.º 5
0
Arquivo: proc.c Projeto: BWK/os161
/*
 * 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;
	}

	/* VM fields */
	if (proc->p_addrspace) {
		/*
		 * In case p is the currently running process (which
		 * it might be in some circumstances, or if this code
		 * gets moved into exit as suggested above), 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.
		 */
		struct addrspace *as;

		as_deactivate();
		as = curproc_setas(NULL);
		as_destroy(as);
	}

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

	kfree(proc->p_name);
	kfree(proc);
}
Exemplo n.º 6
0
void sys__exit(int exitcode) {
  struct addrspace *as;
  struct proc *p = curproc;
#if OPT_A2
  int pid = (int)curproc->pid;
  struct proc_entry *entry = process_table[pid];
  lock_acquire(entry->exit_mutex);
  process_table[pid]->exited = 1;
  process_table[pid]->exitcode = exitcode;
  //if(lock_do_i_hold(entry->exit_mutex))
  cv_signal(entry->exit_wait, entry->exit_mutex);
  lock_release(entry->exit_mutex);



#else
  /* for now, just include this to keep the compiler from complaining about
     an unused variable */
  (void)exitcode;
#endif
  kprintf("is exiting: %d\n", pid);
  DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);

  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");
}
Exemplo n.º 7
0
/*
 * Destroy a proc structure.
 */
void
proc_destroy(struct proc *proc)
{
	/*
         * note: some parts of the process structure, such as the address space,
         *  are destroyed in sys_exit, before we get here
         *
         * note: depending on where this function is called from, curproc may not
         * be defined because the calling thread may have already detached itself
         * from the process.
	 */

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

	#if OPT_A2
	lock_destroy(proc->opencloselock);
	if(proc->filetable != NULL) {
	for(int i = 127; i >= 0; i--) {
		if(array_get(proc->filetable, i) != NULL) {
			//kprintf("%d \n", i);
			cleanupfile(array_get(proc->filetable, i));
		}
		array_remove(proc->filetable, i);
	}
	array_destroy(proc->filetable);
	}
#endif

	/*
	 * 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;
	}


#ifndef UW  // in the UW version, space destruction occurs in sys_exit, not here
	if (proc->p_addrspace) {
		/*
		 * In case p is the currently running process (which
		 * it might be in some circumstances, or if this code
		 * gets moved into exit as suggested above), 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.
		 */
		struct addrspace *as;

		as_deactivate();
		as = curproc_setas(NULL);
		as_destroy(as);
	}
#endif // UW

#ifdef UW
	if (proc->console) {
	  vfs_close(proc->console);
	}
#endif // UW

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

	kfree(proc->p_name);
	kfree(proc);


#ifdef UW
	/* decrement the process count */
        /* note: kproc is not included in the process count, but proc_destroy
	   is never called on kproc (see KASSERT above), so we're OK to decrement
	   the proc_count unconditionally here */
	P(proc_count_mutex); 
	KASSERT(proc_count > 0);
	proc_count--;
	/* signal the kernel menu thread if the process count has reached zero */
	if (proc_count == 0) {
	  V(no_proc_sem);
	}
	V(proc_count_mutex);
#endif // UW
	

}
Exemplo n.º 8
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, unsigned int nargs)
{
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;

        int argc = nargs;
        char **argv = (char **)kmalloc((argc + 1) * sizeof(char *));
        if(argv == NULL)
        {
            return ENOMEM;
        }

        for(int i = 0; i < argc; ++i)
        {
            argv[i] = args[i];
        }
        argv[argc] = NULL;
       
       
	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

	/* 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;
	}

        /*------copy args to user stack-----------*/
        
        vaddr_t *argPtrs = (vaddr_t *)kmalloc((argc + 1) * sizeof(vaddr_t));
        if(argPtrs == NULL)
        {
            for(int i = 0; i < argc; ++i)
            {
                kfree(argv[i]);
            }
            kfree(argv);
            as_deactivate();
            as = curproc_setas(NULL);
            as_destroy(as);
            return ENOMEM;
        }
        
        for(int i = argc-1; i >= 0; --i)
        {
            //arg length with null
            size_t curArgLen = strlen(argv[i]) + 1;
            
            size_t argLen = ROUNDUP(curArgLen,4);
            
            stackptr -= (argLen * sizeof(char));
            
            //kprintf("copying arg: %s to addr: %p\n", temp, (void *)stackptr);
            
            //copy to stack
            result = copyout((void *) argv[i], (userptr_t)stackptr, curArgLen);
            if(result)
            {
                kfree(argPtrs);
                for(int i = 0; i < argc; ++i)
                {
                    kfree(argv[i]);
                }
                kfree(argv);
                as_deactivate();
                as = curproc_setas(NULL);
                as_destroy(as);
                return result;
            }
            
            argPtrs[i] = stackptr;        
        }    
        
        argPtrs[argc] = (vaddr_t)NULL;
        
        //copy arg pointers
        for(int i = argc; i >= 0; --i)
        {
            stackptr -= sizeof(vaddr_t);
            result = copyout((void *) &argPtrs[i], ((userptr_t)stackptr),sizeof(vaddr_t));
            if(result)
            {
                kfree(argPtrs);
                for(int i = 0; i < argc; ++i)
                {
                    kfree(argv[i]);
                }
                kfree(argv);
                as_deactivate();
                as = curproc_setas(NULL);
                as_destroy(as);
                return result;
            }
        }
        
        
        kfree(argPtrs);
        
        
        
        
        vaddr_t baseAddress = USERSTACK;
        
        vaddr_t argvPtr = stackptr;
        
        vaddr_t offset = ROUNDUP(USERSTACK - stackptr,8);
        
        stackptr = baseAddress - offset;
        
/*
        for(vaddr_t i = baseAddress; i >= stackptr; --i)
        {
            char *temp;
            temp = (char *)i;
            //kprintf("%p: %c\n",(void *)i,*temp);
            
            kprintf("%p: %x\n", (void *)i, *temp & 0xff);
        }
*/
        
        
        /*-done-copy args to user stack-----------*/
        
	/* Warp to user mode. */
	enter_new_process(argc /*argc*/, (userptr_t)argvPtr /*userspace addr of argv*/,
			  stackptr, entrypoint);
	
	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Exemplo n.º 9
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.º 10
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.º 11
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.º 12
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.º 13
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;
}