Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=5dee1707dfbfc55eb7569b9ae5abaf932bd4c377
Commit:     5dee1707dfbfc55eb7569b9ae5abaf932bd4c377
Parent:     6806aac6d282d58b97763f5e17e2787e62c3b440
Author:     Oleg Nesterov <[EMAIL PROTECTED]>
AuthorDate: Fri Feb 8 04:19:13 2008 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Fri Feb 8 09:22:27 2008 -0800

    move the related code from exit_notify() to exit_signals()
    
    The previous bugfix was not optimal, we shouldn't care about group stop
    when we are the only thread or the group stop is in progress.  In that case
    nothing special is needed, just set PF_EXITING and return.
    
    Also, take the related "TIF_SIGPENDING re-targeting" code from 
exit_notify().
    
    So, from the performance POV the only difference is that we don't trust
    !signal_pending() until we take ->siglock.  But this in fact fixes another
    ___pure___ theoretical minor race.  __group_complete_signal() finds the
    task without PF_EXITING and chooses it as the target for signal_wake_up().
    But nothing prevents this task from exiting in between without noticing the
    pending signal and thus unpredictably delaying the actual delivery.
    
    Signed-off-by: Oleg Nesterov <[EMAIL PROTECTED]>
    Cc: Davide Libenzi <[EMAIL PROTECTED]>
    Cc: Ingo Molnar <[EMAIL PROTECTED]>
    Cc: Roland McGrath <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 kernel/exit.c   |   18 ------------------
 kernel/signal.c |   27 ++++++++++++++++++++++-----
 2 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/kernel/exit.c b/kernel/exit.c
index 8f3bf53..2b332d1 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -745,24 +745,6 @@ static void exit_notify(struct task_struct *tsk)
        struct task_struct *t;
        struct pid *pgrp;
 
-       if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
-           && !thread_group_empty(tsk)) {
-               /*
-                * This occurs when there was a race between our exit
-                * syscall and a group signal choosing us as the one to
-                * wake up.  It could be that we are the only thread
-                * alerted to check for pending signals, but another thread
-                * should be woken now to take the signal since we will not.
-                * Now we'll wake all the threads in the group just to make
-                * sure someone gets all the pending signals.
-                */
-               spin_lock_irq(&tsk->sighand->siglock);
-               for (t = next_thread(tsk); t != tsk; t = next_thread(t))
-                       if (!signal_pending(t) && !(t->flags & PF_EXITING))
-                               recalc_sigpending_and_wake(t);
-               spin_unlock_irq(&tsk->sighand->siglock);
-       }
-
        /*
         * This does two things:
         *
diff --git a/kernel/signal.c b/kernel/signal.c
index 209eec1..3d3adb9 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1903,19 +1903,36 @@ relock:
 void exit_signals(struct task_struct *tsk)
 {
        int group_stop = 0;
+       struct task_struct *t;
 
-       spin_lock_irq(&tsk->sighand->siglock);
-       if (unlikely(tsk->signal->group_stop_count) &&
-                       !--tsk->signal->group_stop_count) {
-               tsk->signal->flags = SIGNAL_STOP_STOPPED;
-               group_stop = 1;
+       if (thread_group_empty(tsk) || signal_group_exit(tsk->signal)) {
+               tsk->flags |= PF_EXITING;
+               return;
        }
 
+       spin_lock_irq(&tsk->sighand->siglock);
        /*
         * From now this task is not visible for group-wide signals,
         * see wants_signal(), do_signal_stop().
         */
        tsk->flags |= PF_EXITING;
+       if (!signal_pending(tsk))
+               goto out;
+
+       /* It could be that __group_complete_signal() choose us to
+        * notify about group-wide signal. Another thread should be
+        * woken now to take the signal since we will not.
+        */
+       for (t = tsk; (t = next_thread(t)) != tsk; )
+               if (!signal_pending(t) && !(t->flags & PF_EXITING))
+                       recalc_sigpending_and_wake(t);
+
+       if (unlikely(tsk->signal->group_stop_count) &&
+                       !--tsk->signal->group_stop_count) {
+               tsk->signal->flags = SIGNAL_STOP_STOPPED;
+               group_stop = 1;
+       }
+out:
        spin_unlock_irq(&tsk->sighand->siglock);
 
        if (unlikely(group_stop)) {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to