Commit 6ba7b420 authored by Roland McGrath's avatar Roland McGrath Committed by Linus Torvalds

[PATCH] task_struct.exit_state usage

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: default avatarRoland McGrath <roland@redhat.com>
Acked-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 10d6e374
...@@ -159,7 +159,7 @@ static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task) ...@@ -159,7 +159,7 @@ static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task)
do_each_task_pid(pgrp, PIDTYPE_PGID, p) { do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
if (p == ignored_task if (p == ignored_task
|| p->exit_state >= EXIT_ZOMBIE || p->exit_state
|| p->real_parent->pid == 1) || p->real_parent->pid == 1)
continue; continue;
if (process_group(p->real_parent) != pgrp if (process_group(p->real_parent) != pgrp
...@@ -517,7 +517,7 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re ...@@ -517,7 +517,7 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re
* Make sure we're not reparenting to ourselves and that * Make sure we're not reparenting to ourselves and that
* the parent is not a zombie. * 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; p->real_parent = reaper;
if (p->parent == p->real_parent) if (p->parent == p->real_parent)
BUG(); BUG();
...@@ -599,7 +599,7 @@ static inline void forget_original_parent(struct task_struct * father, ...@@ -599,7 +599,7 @@ static inline void forget_original_parent(struct task_struct * father,
reaper = child_reaper; reaper = child_reaper;
break; break;
} }
} while (reaper->exit_state >= EXIT_ZOMBIE); } while (reaper->exit_state);
/* /*
* There are only two places where our children can be: * There are only two places where our children can be:
...@@ -1182,7 +1182,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap, ...@@ -1182,7 +1182,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap,
* race with the EXIT_ZOMBIE case. * race with the EXIT_ZOMBIE case.
*/ */
exit_code = xchg(&p->exit_code, 0); 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 * The task resumed and then died. Let the next iteration
* catch it in EXIT_ZOMBIE. Note that exit_code might * catch it in EXIT_ZOMBIE. Note that exit_code might
......
...@@ -2541,7 +2541,7 @@ asmlinkage void __sched schedule(void) ...@@ -2541,7 +2541,7 @@ asmlinkage void __sched schedule(void)
* schedule() atomically, we ignore that path for now. * schedule() atomically, we ignore that path for now.
* Otherwise, whine if we are scheduling when we should not be. * 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())) { if (unlikely(in_atomic())) {
printk(KERN_ERR "scheduling while atomic: " printk(KERN_ERR "scheduling while atomic: "
"%s/0x%08x/%d\n", "%s/0x%08x/%d\n",
......
...@@ -934,10 +934,10 @@ __group_complete_signal(int sig, struct task_struct *p) ...@@ -934,10 +934,10 @@ __group_complete_signal(int sig, struct task_struct *p)
struct task_struct *t; 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) * SIGKILL will punch through stopped state)
*/ */
mask = EXIT_DEAD | EXIT_ZOMBIE | TASK_TRACED; mask = TASK_TRACED;
if (sig != SIGKILL) if (sig != SIGKILL)
mask |= TASK_STOPPED; mask |= TASK_STOPPED;
...@@ -1094,7 +1094,7 @@ void zap_other_threads(struct task_struct *p) ...@@ -1094,7 +1094,7 @@ void zap_other_threads(struct task_struct *p)
/* /*
* Don't bother with already dead threads * Don't bother with already dead threads
*/ */
if (t->exit_state & (EXIT_ZOMBIE|EXIT_DEAD)) if (t->exit_state)
continue; continue;
/* /*
......
...@@ -806,7 +806,7 @@ static inline void do_process_times(struct task_struct *p, ...@@ -806,7 +806,7 @@ static inline void do_process_times(struct task_struct *p,
psecs = (p->utime += user); psecs = (p->utime += user);
psecs += (p->stime += system); 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) { psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_cur) {
/* Send SIGXCPU every second.. */ /* Send SIGXCPU every second.. */
if (!(psecs % HZ)) if (!(psecs % HZ))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment