From: Roland McGrath I just did a quick audit of the use of exit_state and the EXIT_* bit macros. I guess I didn't really review these changes very closely when you did them originally. :-( I found several places that seem like lossy cases of query-replace without enough thought about the code. Linus has previously said the >= tests ought to be & tests instead. But for exit_state, it can only ever be 0, EXIT_DEAD, or EXIT_ZOMBIE--so a nonzero test is actually the same as testing & (EXIT_DEAD|EXIT_ZOMBIE), and maybe its code is a tiny bit better. The case like in choose_new_parent is just confusing, to have the always-false test for EXIT_* bits in ->state there too. The two cases in wants_signal and do_process_times are actual regressions that will give us back old bugs in race conditions. These places had s/TASK/EXIT/ but not s/state/exit_state/, and now there tests for exiting tasks are now wrong and never catching them. I take it back: there is no regression in wants_signal in practice I think, because of the PF_EXITING test that makes the EXIT_* state checks superfluous anyway. So that is just another cosmetic case of confusing code. But in do_process_times, there is that SIGXCPU-while-exiting race condition back again. Signed-off-by: Roland McGrath Signed-off-by: Andrew Morton --- 25-akpm/kernel/exit.c | 8 ++++---- 25-akpm/kernel/sched.c | 2 +- 25-akpm/kernel/signal.c | 6 +++--- 25-akpm/kernel/timer.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff -puN kernel/exit.c~task_structexit_state-usage kernel/exit.c --- 25/kernel/exit.c~task_structexit_state-usage 2004-12-27 00:42:47.633032600 -0800 +++ 25-akpm/kernel/exit.c 2004-12-27 00:42:47.647030472 -0800 @@ -159,7 +159,7 @@ static int will_become_orphaned_pgrp(int do_each_task_pid(pgrp, PIDTYPE_PGID, p) { if (p == ignored_task - || p->exit_state >= EXIT_ZOMBIE + || p->exit_state || p->real_parent->pid == 1) continue; if (process_group(p->real_parent) != pgrp @@ -517,7 +517,7 @@ static inline void choose_new_parent(tas * Make sure we're not reparenting to ourselves and that * the parent is not a zombie. */ - BUG_ON(p == reaper || reaper->state >= EXIT_ZOMBIE || reaper->exit_state >= EXIT_ZOMBIE); + BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE); p->real_parent = reaper; if (p->parent == p->real_parent) BUG(); @@ -599,7 +599,7 @@ static inline void forget_original_paren reaper = child_reaper; break; } - } while (reaper->exit_state >= EXIT_ZOMBIE); + } while (reaper->exit_state); /* * There are only two places where our children can be: @@ -1182,7 +1182,7 @@ static int wait_task_stopped(task_t *p, * race with the EXIT_ZOMBIE case. */ exit_code = xchg(&p->exit_code, 0); - if (unlikely(p->exit_state >= EXIT_ZOMBIE)) { + if (unlikely(p->exit_state)) { /* * The task resumed and then died. Let the next iteration * catch it in EXIT_ZOMBIE. Note that exit_code might diff -puN kernel/sched.c~task_structexit_state-usage kernel/sched.c --- 25/kernel/sched.c~task_structexit_state-usage 2004-12-27 00:42:47.636032144 -0800 +++ 25-akpm/kernel/sched.c 2004-12-27 00:42:47.652029712 -0800 @@ -2541,7 +2541,7 @@ asmlinkage void __sched schedule(void) * schedule() atomically, we ignore that path for now. * Otherwise, whine if we are scheduling when we should not be. */ - if (likely(!(current->exit_state & (EXIT_DEAD | EXIT_ZOMBIE)))) { + if (likely(!current->exit_state)) { if (unlikely(in_atomic())) { printk(KERN_ERR "scheduling while atomic: " "%s/0x%08x/%d\n", diff -puN kernel/signal.c~task_structexit_state-usage kernel/signal.c --- 25/kernel/signal.c~task_structexit_state-usage 2004-12-27 00:42:47.639031688 -0800 +++ 25-akpm/kernel/signal.c 2004-12-27 00:42:47.659028648 -0800 @@ -934,10 +934,10 @@ __group_complete_signal(int sig, struct struct task_struct *t; /* - * Don't bother zombies and stopped tasks (but + * Don't bother traced and stopped tasks (but * SIGKILL will punch through stopped state) */ - mask = EXIT_DEAD | EXIT_ZOMBIE | TASK_TRACED; + mask = TASK_TRACED; if (sig != SIGKILL) mask |= TASK_STOPPED; @@ -1094,7 +1094,7 @@ void zap_other_threads(struct task_struc /* * Don't bother with already dead threads */ - if (t->exit_state & (EXIT_ZOMBIE|EXIT_DEAD)) + if (t->exit_state) continue; /* diff -puN kernel/timer.c~task_structexit_state-usage kernel/timer.c --- 25/kernel/timer.c~task_structexit_state-usage 2004-12-27 00:42:47.642031232 -0800 +++ 25-akpm/kernel/timer.c 2004-12-27 00:42:47.661028344 -0800 @@ -806,7 +806,7 @@ static inline void do_process_times(stru psecs = (p->utime += user); psecs += (p->stime += system); - if (p->signal && !unlikely(p->state & (EXIT_DEAD|EXIT_ZOMBIE)) && + if (p->signal && !unlikely(p->exit_state) && psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_cur) { /* Send SIGXCPU every second.. */ if (!(psecs % HZ)) _