NORET_TYPE void do_exit(long code) { struct task_struct *tsk = current; if (in_interrupt()) panic("Aiee, killing interrupt handler!"); if (!tsk->pid) panic("Attempted to kill the idle task!"); if (tsk->pid == 1) panic("Attempted to kill init!"); tsk->flags |= PF_EXITING; del_timer_sync(&tsk->real_timer); fake_volatile: #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif if (current->tux_info) { #ifdef CONFIG_TUX_DEBUG printk("Possibly unexpected TUX-thread exit(%ld) at %p?\n", code, __builtin_return_address(0)); #endif current->tux_exit(); } __exit_mm(tsk); lock_kernel(); sem_exit(); __exit_files(tsk); __exit_fs(tsk); exit_namespace(tsk); exit_sighand(tsk); exit_thread(); if (current->leader) disassociate_ctty(1); put_exec_domain(tsk->exec_domain); if (tsk->binfmt && tsk->binfmt->module) __MOD_DEC_USE_COUNT(tsk->binfmt->module); tsk->exit_code = code; exit_notify(); schedule(); BUG(); /* * In order to get rid of the "volatile function does return" message * I did this little loop that confuses gcc to think do_exit really * is volatile. In fact it's schedule() that is volatile in some * circumstances: when current->state = ZOMBIE, schedule() never * returns. * * In fact the natural way to do all this is to have the label and the * goto right after each other, but I put the fake_volatile label at * the start of the function just in case something /really/ bad * happens, and the schedule returns. This way we can try again. I'm * not paranoid: it's just that everybody is out to get me. */ goto fake_volatile; }
NORET_TYPE void do_exit(long code) { struct task_struct *tsk = current; if (in_interrupt()) printk("Aiee, killing interrupt handler\n"); if (!tsk->pid) panic("Attempted to kill the idle task!"); tsk->flags |= PF_EXITING; start_bh_atomic(); del_timer(&tsk->real_timer); end_bh_atomic(); lock_kernel(); fake_volatile: #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif sem_exit(); __exit_mm(tsk); #if CONFIG_AP1000 exit_msc(tsk); #endif __exit_files(tsk); __exit_fs(tsk); __exit_sighand(tsk); exit_thread(); tsk->state = TASK_ZOMBIE; tsk->exit_code = code; exit_notify(); #ifdef DEBUG_PROC_TREE audit_ptree(); #endif if (tsk->exec_domain && tsk->exec_domain->module) __MOD_DEC_USE_COUNT(tsk->exec_domain->module); if (tsk->binfmt && tsk->binfmt->module) __MOD_DEC_USE_COUNT(tsk->binfmt->module); schedule(); /* * In order to get rid of the "volatile function does return" message * I did this little loop that confuses gcc to think do_exit really * is volatile. In fact it's schedule() that is volatile in some * circumstances: when current->state = ZOMBIE, schedule() never * returns. * * In fact the natural way to do all this is to have the label and the * goto right after each other, but I put the fake_volatile label at * the start of the function just in case something /really/ bad * happens, and the schedule returns. This way we can try again. I'm * not paranoid: it's just that everybody is out to get me. */ goto fake_volatile; }
NORET_TYPE void do_exit(long code) { //... __exit_mm(tsk); exit_sem(tsk); __exit_files(tsk); __exit_fs(tsk); exit_namespace(tsk); exit_itimers(tsk); exit_thread(); //... tsk->exit_code = code; exit_notify(tsk); schedule(); }
NORET_TYPE void do_exit(long code) { if (intr_count) { printk("Aiee, killing interrupt handler\n"); intr_count = 0; } fake_volatile: acct_process(code); current->flags |= PF_EXITING; del_timer(¤t->real_timer); sem_exit(); kerneld_exit(); __exit_mm(current); __exit_files(current); __exit_fs(current); __exit_sighand(current); exit_thread(); current->state = TASK_ZOMBIE; current->exit_code = code; exit_notify(); #ifdef DEBUG_PROC_TREE audit_ptree(); #endif if (current->exec_domain && current->exec_domain->use_count) (*current->exec_domain->use_count)--; if (current->binfmt && current->binfmt->use_count) (*current->binfmt->use_count)--; schedule(); /* * In order to get rid of the "volatile function does return" message * I did this little loop that confuses gcc to think do_exit really * is volatile. In fact it's schedule() that is volatile in some * circumstances: when current->state = ZOMBIE, schedule() never * returns. * * In fact the natural way to do all this is to have the label and the * goto right after each other, but I put the fake_volatile label at * the start of the function just in case something /really/ bad * happens, and the schedule returns. This way we can try again. I'm * not paranoid: it's just that everybody is out to get me. */ goto fake_volatile; }
NORET_TYPE void do_exit(long code) { struct task_struct *tsk = current; if (in_interrupt()) panic("Aiee, killing interrupt handler!"); if (!tsk->pid) panic("Attempted to kill the idle task!"); if (tsk->pid == 1) panic("Attempted to kill init!"); /* * If do_exit is called because this processes oopsed, it's possible * that get_fs() was left as KERNEL_DS, so reset it to USER_DS before * continuing. Amongst other possible reasons, this is to prevent * mm_release()->clear_child_tid() from writing to a user-controlled * kernel address. */ set_fs(USER_DS); tsk->flags |= PF_EXITING; del_timer_sync(&tsk->real_timer); fake_volatile: #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif __exit_mm(tsk); lock_kernel(); sem_exit(); __exit_files(tsk); __exit_fs(tsk); exit_namespace(tsk); exit_sighand(tsk); exit_thread(); if (current->leader) disassociate_ctty(1); put_exec_domain(tsk->exec_domain); if (tsk->binfmt && tsk->binfmt->module) __MOD_DEC_USE_COUNT(tsk->binfmt->module); tsk->exit_code = code; exit_notify(); schedule(); BUG(); /* * In order to get rid of the "volatile function does return" message * I did this little loop that confuses gcc to think do_exit really * is volatile. In fact it's schedule() that is volatile in some * circumstances: when current->state = ZOMBIE, schedule() never * returns. * * In fact the natural way to do all this is to have the label and the * goto right after each other, but I put the fake_volatile label at * the start of the function just in case something /really/ bad * happens, and the schedule returns. This way we can try again. I'm * not paranoid: it's just that everybody is out to get me. */ goto fake_volatile; }
void exit_mm(struct task_struct *tsk) { __exit_mm(tsk); }