From: Manfred Spraul 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. 25-akpm/fs/exec.c | 1 + 25-akpm/include/linux/sched.h | 6 ++++++ 25-akpm/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 Mon May 19 16:41:08 2003 +++ 25-akpm/fs/exec.c Mon May 19 16:41:08 2003 @@ -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 Mon May 19 16:41:08 2003 +++ 25-akpm/include/linux/sched.h Mon May 19 16:41:08 2003 @@ -246,7 +246,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 Mon May 19 16:41:08 2003 +++ 25-akpm/kernel/signal.c Mon May 19 16:41:08 2003 @@ -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; } _