summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-05-25 01:13:17 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-05-25 01:13:17 -0700
commit73accc3dda343b96b37a0e2b1fd6367b57a20b64 (patch)
tree83be4e576833276f6adee9f9ea58e7b9f7964283
parent9ee208ea99489c357d152f0e5020d19d33497d67 (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.c1
-rw-r--r--include/linux/sched.h6
-rw-r--r--kernel/signal.c2
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;
}