Beispiel #1
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");
}
/*
 * Cause the current thread to exit.
 *
 * The parts of the thread structure we don't actually need to run
 * should be cleaned up right away. The rest has to wait until
 * thread_destroy is called from exorcise().
 *
 * Note that any dynamically-allocated structures that can vary in size from
 * thread to thread should be cleaned up here, not in thread_destroy. This is
 * because the last thread left on each core runs the idle loop and does not
 * get cleaned up until new threads are created. Differences in the amount of
 * memory used by different threads after thread_exit will make it look like
 * your kernel in leaking memory and cause some of the test161 checks to fail.
 *
 * Does not return.
 */
void
thread_exit(void)
{
    struct thread *cur;

    cur = curthread;

    /*
     * Detach from our process. You might need to move this action
     * around, depending on how your wait/exit works.
     */
    proc_remthread(cur);

    /* Make sure we *are* detached (move this only if you're sure!) */
    KASSERT(cur->t_proc == NULL);

    /* Check the stack guard band. */
    thread_checkstack(cur);

    // Decrement the thread count and notify anyone interested.
    if (thread_count) {
        spinlock_acquire(&thread_count_lock);
        --thread_count;
        wchan_wakeall(thread_count_wchan, &thread_count_lock);
        spinlock_release(&thread_count_lock);
    }

    /* Interrupts off on this processor */
    splhigh();
    thread_switch(S_ZOMBIE, NULL, NULL);
    panic("braaaaaaaiiiiiiiiiiinssssss\n");
}
Beispiel #3
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");
}
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");
}
/*
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");
}
Beispiel #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");
}
Beispiel #7
0
/*
 * Cause the current thread to exit.
 *
 * The parts of the thread structure we don't actually need to run
 * should be cleaned up right away. The rest has to wait until
 * thread_destroy is called from exorcise().
 *
 * Does not return.
 */
void
thread_exit(void)
{
	struct thread *cur;

	cur = curthread;

	/*
	 * Detach from our process. You might need to move this action
	 * around, depending on how your wait/exit works.
	 */
	proc_remthread(cur);

	/* Make sure we *are* detached (move this only if you're sure!) */
	KASSERT(cur->t_proc == NULL);

	/* Check the stack guard band. */
	thread_checkstack(cur);

	/* Interrupts off on this processor */
        splhigh();
	thread_switch(S_ZOMBIE, NULL, NULL);
	panic("braaaaaaaiiiiiiiiiiinssssss\n");
}
Beispiel #8
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
}
Beispiel #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
    //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
}