/** * * Terminate the current process (maybe). If the current process has * more than one running thread, only terminate the current thread. * The process is only completely terminated (as per process_join * wakeup and page table deallocation) when the final thread calls * process_finish(). * * @param The return value of the process. This is only used when the * final thread exits. * */ void process_finish(int retval) { interrupt_status_t intr_status; thread_table_t *thread = thread_get_current_thread_entry(); process_id_t pid = thread->process_id; if (retval < 0) { /* Not permitted! */ retval = 0; } intr_status = _interrupt_disable(); spinlock_acquire(&process_table_slock); /* Mark the stack as free so new threads can reuse it. */ process_free_stack(thread); if (--process_table[pid].threads == 0) { /* We are the last thread - kill process! */ vm_destroy_pagetable(thread->pagetable); finish_given_process(pid, retval); } thread->pagetable = NULL; spinlock_release(&process_table_slock); _interrupt_set_state(intr_status); thread_finish(); }
/** * Terminates the current process and sets a return value */ void process_finish(uint32_t retval) { interrupt_status_t intr_status; process_id_t pid; thread_table_t *my_thread; // Find out who we are. pid = process_get_current_process(); my_thread = thread_get_current_thread_entry(); // Ensure that we're the only ones touching the process table. intr_status = _interrupt_disable(); spinlock_acquire(&process_table_slock); // Mark the stack as free so new threads can reuse it. process_free_stack(my_thread); if(--process_table[pid].threads == 0) { // Last thread in process; now we die. // Mark ourself as dying. process_table[pid].retval = retval; process_table[pid].state = PROCESS_DYING; vm_destroy_pagetable(my_thread->pagetable); // Wake whomever may be sleeping for the process sleepq_wake(&process_table[pid]); } // Free our locks. spinlock_release(&process_table_slock); _interrupt_set_state(intr_status); my_thread->pagetable = NULL; // Kill the thread. thread_finish(); }