Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Oleg Nesterov and committed by
Linus Torvalds
d344193a 09faef11

+7 -8
+6 -7
fs/exec.c
··· 768 768 struct signal_struct *sig = tsk->signal; 769 769 struct sighand_struct *oldsighand = tsk->sighand; 770 770 spinlock_t *lock = &oldsighand->siglock; 771 - int count; 772 771 773 772 if (thread_group_empty(tsk)) 774 773 goto no_thread_group; ··· 784 785 spin_unlock_irq(lock); 785 786 return -EAGAIN; 786 787 } 787 - sig->group_exit_task = tsk; 788 - zap_other_threads(tsk); 789 788 790 - /* Account for the thread group leader hanging around: */ 791 - count = thread_group_leader(tsk) ? 1 : 2; 792 - sig->notify_count = count; 793 - while (atomic_read(&sig->count) > count) { 789 + sig->group_exit_task = tsk; 790 + sig->notify_count = zap_other_threads(tsk); 791 + if (!thread_group_leader(tsk)) 792 + sig->notify_count--; 793 + 794 + while (sig->notify_count) { 794 795 __set_current_state(TASK_UNINTERRUPTIBLE); 795 796 spin_unlock_irq(lock); 796 797 schedule();
+1 -1
kernel/exit.c
··· 97 97 * If there is any task waiting for the group exit 98 98 * then notify it: 99 99 */ 100 - if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) 100 + if (sig->notify_count > 0 && !--sig->notify_count) 101 101 wake_up_process(sig->group_exit_task); 102 102 103 103 if (tsk == sig->curr_target)