diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-05-25 01:13:17 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-05-25 01:13:17 -0700 |
| commit | 73accc3dda343b96b37a0e2b1fd6367b57a20b64 (patch) | |
| tree | 83be4e576833276f6adee9f9ea58e7b9f7964283 | |
| parent | 9ee208ea99489c357d152f0e5020d19d33497d67 (diff) | |
[PATCH] add notify_count for de_thread
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.
| -rw-r--r-- | fs/exec.c | 1 | ||||
| -rw-r--r-- | include/linux/sched.h | 6 | ||||
| -rw-r--r-- | kernel/signal.c | 2 |
3 files changed, 8 insertions, 1 deletions
diff --git a/fs/exec.c b/fs/exec.c index 9bbd3b4e76dc..d84c9a2c4b8f 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -609,6 +609,7 @@ static inline int de_thread(struct task_struct *tsk) 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 --git a/include/linux/sched.h b/include/linux/sched.h index 75e6e1b5b363..003195629026 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -245,7 +245,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 --git a/kernel/signal.c b/kernel/signal.c index 3560d7da7032..d1f02ea4b7b1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -336,7 +336,7 @@ void __exit_signal(struct task_struct *tsk) * 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; } |
