summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.osdl.org>2003-10-26 03:16:23 -0800
committerLinus Torvalds <torvalds@home.osdl.org>2003-10-26 03:16:23 -0800
commitedf12049eae51473bf5050646d9b9787ee648926 (patch)
treef4f84106112ad31eb6eb152a6a8a410e24e7cf1b
parentc2988baf02a8a29f0224115b10e575b826d5abcd (diff)
Add a sticky "PF_DEAD" task flag to keep track of dead processes.
Use this to simplify 'finish_task_switch', but perhaps more importantly we can use this to track down why some processes seem to sometimes not die properly even after having been marked as ZOMBIE. The "task->state" flags are too fluid to allow that well.
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/exit.c1
-rw-r--r--kernel/sched.c9
3 files changed, 5 insertions, 6 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4241be4f518f..031579e7e3fc 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -483,6 +483,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
/* Not implemented yet, only for 486*/
#define PF_STARTING 0x00000002 /* being created */
#define PF_EXITING 0x00000004 /* getting shut down */
+#define PF_DEAD 0x00000008 /* Dead */
#define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */
#define PF_SUPERPRIV 0x00000100 /* used super-user privileges */
#define PF_DUMPCORE 0x00000200 /* dumped core */
diff --git a/kernel/exit.c b/kernel/exit.c
index 25b62f5971be..32f739f782d1 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -688,6 +688,7 @@ static void exit_notify(struct task_struct *tsk)
}
tsk->state = TASK_ZOMBIE;
+ tsk->flags |= PF_DEAD;
/*
* In the preemption case it must be impossible for the task
* to get runnable again, so use "_raw_" unlock to keep
diff --git a/kernel/sched.c b/kernel/sched.c
index 7a13a492c62d..f4e5d8e04b9c 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -742,7 +742,7 @@ static inline void finish_task_switch(task_t *prev)
{
runqueue_t *rq = this_rq();
struct mm_struct *mm = rq->prev_mm;
- int drop_task_ref;
+ unsigned long prev_task_flags;
rq->prev_mm = NULL;
@@ -757,14 +757,11 @@ static inline void finish_task_switch(task_t *prev)
* be dropped twice.
* Manfred Spraul <manfred@colorfullife.com>
*/
- drop_task_ref = 0;
- if (unlikely(prev->state & (TASK_DEAD | TASK_ZOMBIE)))
- drop_task_ref = 1;
-
+ prev_task_flags = prev->flags;
finish_arch_switch(rq, prev);
if (mm)
mmdrop(mm);
- if (drop_task_ref)
+ if (unlikely(prev_task_flags & PF_DEAD))
put_task_struct(prev);
}