diff options
author | Oleg Nesterov <oleg@redhat.com> | 2010-05-26 17:43:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-27 12:12:46 -0400 |
commit | d344193a05da89c97e965da2c5cbf687d7385eae (patch) | |
tree | 6267b68c31c4547f1749acd35d2a5bfaff919839 /fs/exec.c | |
parent | 09faef11df8c559a23e2405d123cb2683733a79a (diff) |
exit: avoid sig->count in de_thread/__exit_signal synchronization
de_thread() and __exit_signal() use signal_struct->count/notify_count for
synchronization. We can simplify the code and use ->notify_count only.
Instead of comparing these two counters, we can change de_thread() to set
->notify_count = nr_of_sub_threads, then change __exit_signal() to
dec-and-test this counter and notify group_exit_task.
Note that __exit_signal() checks "notify_count > 0" just for symmetry with
exit_notify(), we could just check it is != 0.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Roland McGrath <roland@redhat.com>
Cc: Veaceslav Falico <vfalico@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 11 |
1 files changed, 5 insertions, 6 deletions
@@ -768,7 +768,6 @@ static int de_thread(struct task_struct *tsk) | |||
768 | struct signal_struct *sig = tsk->signal; | 768 | struct signal_struct *sig = tsk->signal; |
769 | struct sighand_struct *oldsighand = tsk->sighand; | 769 | struct sighand_struct *oldsighand = tsk->sighand; |
770 | spinlock_t *lock = &oldsighand->siglock; | 770 | spinlock_t *lock = &oldsighand->siglock; |
771 | int count; | ||
772 | 771 | ||
773 | if (thread_group_empty(tsk)) | 772 | if (thread_group_empty(tsk)) |
774 | goto no_thread_group; | 773 | goto no_thread_group; |
@@ -785,13 +784,13 @@ static int de_thread(struct task_struct *tsk) | |||
785 | spin_unlock_irq(lock); | 784 | spin_unlock_irq(lock); |
786 | return -EAGAIN; | 785 | return -EAGAIN; |
787 | } | 786 | } |
787 | |||
788 | sig->group_exit_task = tsk; | 788 | sig->group_exit_task = tsk; |
789 | zap_other_threads(tsk); | 789 | sig->notify_count = zap_other_threads(tsk); |
790 | if (!thread_group_leader(tsk)) | ||
791 | sig->notify_count--; | ||
790 | 792 | ||
791 | /* Account for the thread group leader hanging around: */ | 793 | while (sig->notify_count) { |
792 | count = thread_group_leader(tsk) ? 1 : 2; | ||
793 | sig->notify_count = count; | ||
794 | while (atomic_read(&sig->count) > count) { | ||
795 | __set_current_state(TASK_UNINTERRUPTIBLE); | 794 | __set_current_state(TASK_UNINTERRUPTIBLE); |
796 | spin_unlock_irq(lock); | 795 | spin_unlock_irq(lock); |
797 | schedule(); | 796 | schedule(); |