From: Manfred Spraul <manfred@colorfullife.com>

de_thread is called by exec to kill all threads in the thread group except
the threads required for exec.

The waiting is implemented by waiting for a wakeup from __exit_signal: If
the reference count is less or equal to 2, then the waiter is woken up.  If
exec is called by a non-leader thread, then two threads are required for
exec.

But if a thread group leader calls exec, then only one thread is required
for exec.  Thus the hardcoded "2" leads to a superfluous wakeup.  The patch
fixes that by adding a "notify_count" field to the signal structure.




 fs/exec.c             |    1 +
 include/linux/sched.h |    6 ++++++
 kernel/signal.c       |    2 +-
 3 files changed, 8 insertions(+), 1 deletion(-)

diff -puN fs/exec.c~notify_count-for-de_thread fs/exec.c
--- 25/fs/exec.c~notify_count-for-de_thread	2003-05-18 11:18:57.000000000 -0700
+++ 25-akpm/fs/exec.c	2003-05-18 11:18:57.000000000 -0700
@@ -609,6 +609,7 @@ static inline int de_thread(struct task_
 		count = 1;
 	while (atomic_read(&oldsig->count) > count) {
 		oldsig->group_exit_task = current;
+		oldsig->notify_count = count;
 		__set_current_state(TASK_UNINTERRUPTIBLE);
 		spin_unlock_irq(lock);
 		schedule();
diff -puN include/linux/sched.h~notify_count-for-de_thread include/linux/sched.h
--- 25/include/linux/sched.h~notify_count-for-de_thread	2003-05-18 11:18:57.000000000 -0700
+++ 25-akpm/include/linux/sched.h	2003-05-18 11:18:57.000000000 -0700
@@ -264,7 +264,13 @@ struct signal_struct {
 	/* thread group exit support */
 	int			group_exit;
 	int			group_exit_code;
+	/* overloaded:
+	 * - notify group_exit_task when ->count is equal to notify_count
+	 * - everyone except group_exit_task is stopped during signal delivery
+	 *   of fatal signals, group_exit_task processes the signal.
+	 */
 	struct task_struct	*group_exit_task;
+	int			notify_count;
 
 	/* thread group stop support, overloads group_exit_code too */
 	int			group_stop_count;
diff -puN kernel/signal.c~notify_count-for-de_thread kernel/signal.c
--- 25/kernel/signal.c~notify_count-for-de_thread	2003-05-18 11:18:57.000000000 -0700
+++ 25-akpm/kernel/signal.c	2003-05-18 11:18:57.000000000 -0700
@@ -336,7 +336,7 @@ void __exit_signal(struct task_struct *t
 		 * If there is any task waiting for the group exit
 		 * then notify it:
 		 */
-		if (sig->group_exit_task && atomic_read(&sig->count) <= 2) {
+		if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) {
 			wake_up_process(sig->group_exit_task);
 			sig->group_exit_task = NULL;
 		}

_