
From: Roland McGrath <roland@redhat.com>

After my last change, there are plenty of unused bits available in the new
flags word in signal_struct.  This patch moves the `group_exit' flag into
one of those bits, saving a word in signal_struct.

Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/exec.c             |    7 +++----
 25-akpm/include/linux/sched.h |    2 +-
 25-akpm/kernel/exit.c         |   10 +++++-----
 25-akpm/kernel/fork.c         |    3 +--
 25-akpm/kernel/signal.c       |   15 ++++++++++-----
 5 files changed, 20 insertions(+), 17 deletions(-)

diff -puN fs/exec.c~move-group_exit-flag-into-signal_structflags-word fs/exec.c
--- 25/fs/exec.c~move-group_exit-flag-into-signal_structflags-word	2004-12-03 20:56:02.685351952 -0800
+++ 25-akpm/fs/exec.c	2004-12-03 20:56:02.695350432 -0800
@@ -600,7 +600,7 @@ static inline int de_thread(struct task_
 	 */
 	read_lock(&tasklist_lock);
 	spin_lock_irq(lock);
-	if (sig->group_exit) {
+	if (sig->flags & SIGNAL_GROUP_EXIT) {
 		/*
 		 * Another group action in progress, just
 		 * return so that the signal is processed.
@@ -610,7 +610,6 @@ static inline int de_thread(struct task_
 		kmem_cache_free(sighand_cachep, newsighand);
 		return -EAGAIN;
 	}
-	sig->group_exit = 1;
 	zap_other_threads(current);
 	read_unlock(&tasklist_lock);
 
@@ -708,7 +707,7 @@ static inline int de_thread(struct task_
 	 * Now there are really no other threads at all,
 	 * so it's safe to stop telling them to kill themselves.
 	 */
-	sig->group_exit = 0;
+	sig->flags = 0;
 
 no_thread_group:
 	BUG_ON(atomic_read(&sig->count) != 1);
@@ -1393,7 +1392,7 @@ int do_coredump(long signr, int exit_cod
 	}
 	mm->dumpable = 0;
 	init_completion(&mm->core_done);
-	current->signal->group_exit = 1;
+	current->signal->flags = SIGNAL_GROUP_EXIT;
 	current->signal->group_exit_code = exit_code;
 	coredump_wait(mm);
 
diff -puN include/linux/sched.h~move-group_exit-flag-into-signal_structflags-word include/linux/sched.h
--- 25/include/linux/sched.h~move-group_exit-flag-into-signal_structflags-word	2004-12-03 20:56:02.687351648 -0800
+++ 25-akpm/include/linux/sched.h	2004-12-03 20:56:02.697350128 -0800
@@ -282,7 +282,6 @@ struct signal_struct {
 	struct sigpending	shared_pending;
 
 	/* thread group exit support */
-	int			group_exit;
 	int			group_exit_code;
 	/* overloaded:
 	 * - notify group_exit_task when ->count is equal to notify_count
@@ -336,6 +335,7 @@ struct signal_struct {
 #define SIGNAL_STOP_STOPPED	0x00000001 /* job control stop in effect */
 #define SIGNAL_STOP_DEQUEUED	0x00000002 /* stop signal dequeued */
 #define SIGNAL_STOP_CONTINUED	0x00000004 /* SIGCONT since WCONTINUED reap */
+#define SIGNAL_GROUP_EXIT	0x00000008 /* group exit in progress */
 
 
 /*
diff -puN kernel/exit.c~move-group_exit-flag-into-signal_structflags-word kernel/exit.c
--- 25/kernel/exit.c~move-group_exit-flag-into-signal_structflags-word	2004-12-03 20:56:02.688351496 -0800
+++ 25-akpm/kernel/exit.c	2004-12-03 20:56:02.698349976 -0800
@@ -657,7 +657,7 @@ static void exit_notify(struct task_stru
 	struct task_struct *t;
 	struct list_head ptrace_dead, *_p, *_n;
 
-	if (signal_pending(tsk) && !tsk->signal->group_exit
+	if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
 	    && !thread_group_empty(tsk)) {
 		/*
 		 * This occurs when there was a race between our exit
@@ -880,18 +880,18 @@ do_group_exit(int exit_code)
 {
 	BUG_ON(exit_code & 0x80); /* core dumps don't get here */
 
-	if (current->signal->group_exit)
+	if (current->signal->flags & SIGNAL_GROUP_EXIT)
 		exit_code = current->signal->group_exit_code;
 	else if (!thread_group_empty(current)) {
 		struct signal_struct *const sig = current->signal;
 		struct sighand_struct *const sighand = current->sighand;
 		read_lock(&tasklist_lock);
 		spin_lock_irq(&sighand->siglock);
-		if (sig->group_exit)
+		if (sig->flags & SIGNAL_GROUP_EXIT)
 			/* Another thread got here before we took the lock.  */
 			exit_code = sig->group_exit_code;
 		else {
-			sig->group_exit = 1;
+			sig->flags = SIGNAL_GROUP_EXIT;
 			sig->group_exit_code = exit_code;
 			zap_other_threads(current);
 		}
@@ -1071,7 +1071,7 @@ static int wait_task_zombie(task_t *p, i
 	read_unlock(&tasklist_lock);
 
 	retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
-	status = p->signal->group_exit
+	status = (p->signal->flags & SIGNAL_GROUP_EXIT)
 		? p->signal->group_exit_code : p->exit_code;
 	if (!retval && stat_addr)
 		retval = put_user(status, stat_addr);
diff -puN kernel/fork.c~move-group_exit-flag-into-signal_structflags-word kernel/fork.c
--- 25/kernel/fork.c~move-group_exit-flag-into-signal_structflags-word	2004-12-03 20:56:02.690351192 -0800
+++ 25-akpm/kernel/fork.c	2004-12-03 20:56:02.699349824 -0800
@@ -734,7 +734,6 @@ static inline int copy_signal(unsigned l
 	atomic_set(&sig->count, 1);
 	atomic_set(&sig->live, 1);
 	sig->flags = 0;
-	sig->group_exit = 0;
 	sig->group_exit_code = 0;
 	sig->group_exit_task = NULL;
 	sig->group_stop_count = 0;
@@ -1000,7 +999,7 @@ static task_t *copy_process(unsigned lon
 		 * do not create this new thread - the whole thread
 		 * group is supposed to exit anyway.
 		 */
-		if (current->signal->group_exit) {
+		if (current->signal->flags & SIGNAL_GROUP_EXIT) {
 			spin_unlock(&current->sighand->siglock);
 			write_unlock_irq(&tasklist_lock);
 			retval = -EAGAIN;
diff -puN kernel/signal.c~move-group_exit-flag-into-signal_structflags-word kernel/signal.c
--- 25/kernel/signal.c~move-group_exit-flag-into-signal_structflags-word	2004-12-03 20:56:02.692350888 -0800
+++ 25-akpm/kernel/signal.c	2004-12-03 20:56:02.701349520 -0800
@@ -661,6 +661,12 @@ static void handle_stop_signal(int sig, 
 {
 	struct task_struct *t;
 
+	if (p->flags & SIGNAL_GROUP_EXIT)
+		/*
+		 * The process is in the middle of dying already.
+		 */
+		return;
+
 	if (sig_kernel_stop(sig)) {
 		/*
 		 * This is a stop signal.  Remove SIGCONT from all queues.
@@ -976,7 +982,7 @@ __group_complete_signal(int sig, struct 
 	 * Found a killable thread.  If the signal will be fatal,
 	 * then start taking the whole group down immediately.
 	 */
-	if (sig_fatal(p, sig) && !p->signal->group_exit &&
+	if (sig_fatal(p, sig) && !(p->signal->flags & SIGNAL_GROUP_EXIT) &&
 	    !sigismember(&t->real_blocked, sig) &&
 	    (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) {
 		/*
@@ -989,10 +995,9 @@ __group_complete_signal(int sig, struct 
 			 * running and doing things after a slower
 			 * thread has the fatal signal pending.
 			 */
-			p->signal->group_exit = 1;
+			p->signal->flags = SIGNAL_GROUP_EXIT;
 			p->signal->group_exit_code = sig;
 			p->signal->group_stop_count = 0;
-			p->signal->flags = 0;
 			t = p;
 			do {
 				sigaddset(&t->pending.signal, SIGKILL);
@@ -1079,8 +1084,8 @@ void zap_other_threads(struct task_struc
 {
 	struct task_struct *t;
 
+	p->signal->flags = SIGNAL_GROUP_EXIT;
 	p->signal->group_stop_count = 0;
-	p->signal->flags = 0;
 
 	if (thread_group_empty(p))
 		return;
@@ -1785,7 +1790,7 @@ static inline int handle_group_stop(void
 		return 0;
 	}
 
-	if (current->signal->group_exit)
+	if (current->signal->flags & SIGNAL_GROUP_EXIT)
 		/*
 		 * Group stop is so another thread can do a core dump,
 		 * or else we are racing against a death signal.
_
