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