From: Roland McGrath 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 Signed-off-by: Andrew Morton --- 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(¤t->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. _