]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/exit.c
doc: move vm/00-INDEX to Documentation/vm
[linux-2.6-omap-h63xx.git] / kernel / exit.c
index 9d6e0897a4476dac387116af94aa721f06183219..2c704c86edb3200864d4ec950c4e2bd89cbf3443 100644 (file)
@@ -92,10 +92,9 @@ static 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) == sig->notify_count) {
+               if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count)
                        wake_up_process(sig->group_exit_task);
-                       sig->group_exit_task = NULL;
-               }
+
                if (tsk == sig->curr_target)
                        sig->curr_target = next_thread(tsk);
                /*
@@ -747,13 +746,11 @@ static void exit_notify(struct task_struct *tsk)
                 * Now we'll wake all the threads in the group just to make
                 * sure someone gets all the pending signals.
                 */
-               read_lock(&tasklist_lock);
                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);
-               read_unlock(&tasklist_lock);
        }
 
        write_lock_irq(&tasklist_lock);
@@ -781,9 +778,8 @@ static void exit_notify(struct task_struct *tsk)
         * and we were the only connection outside, so our pgrp
         * is about to become orphaned.
         */
-        
        t = tsk->real_parent;
-       
+
        pgrp = task_pgrp(tsk);
        if ((task_pgrp(t) != pgrp) &&
            (task_session(t) == task_session(tsk)) &&
@@ -830,6 +826,11 @@ static void exit_notify(struct task_struct *tsk)
                state = EXIT_DEAD;
        tsk->exit_state = state;
 
+       if (thread_group_leader(tsk) &&
+           tsk->signal->notify_count < 0 &&
+           tsk->signal->group_exit_task)
+               wake_up_process(tsk->signal->group_exit_task);
+
        write_unlock_irq(&tasklist_lock);
 
        list_for_each_safe(_p, _n, &ptrace_dead) {
@@ -946,11 +947,13 @@ fastcall NORET_TYPE void do_exit(long code)
                exit_itimers(tsk->signal);
        }
        acct_collect(code, group_dead);
+#ifdef CONFIG_FUTEX
        if (unlikely(tsk->robust_list))
                exit_robust_list(tsk);
-#if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT)
+#ifdef CONFIG_COMPAT
        if (unlikely(tsk->compat_robust_list))
                compat_exit_robust_list(tsk);
+#endif
 #endif
        if (group_dead)
                tty_audit_exit();
@@ -986,6 +989,7 @@ fastcall NORET_TYPE void do_exit(long code)
        mpol_free(tsk->mempolicy);
        tsk->mempolicy = NULL;
 #endif
+#ifdef CONFIG_FUTEX
        /*
         * This must happen late, after the PID is not
         * hashed anymore:
@@ -994,6 +998,7 @@ fastcall NORET_TYPE void do_exit(long code)
                exit_pi_state_list(tsk);
        if (unlikely(current->pi_state_cache))
                kfree(current->pi_state_cache);
+#endif
        /*
         * Make sure we are holding no locks:
         */
@@ -1158,8 +1163,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
                            int __user *stat_addr, struct rusage __user *ru)
 {
        unsigned long state;
-       int retval;
-       int status;
+       int retval, status, traced;
 
        if (unlikely(noreap)) {
                pid_t pid = p->pid;
@@ -1193,15 +1197,11 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
                BUG_ON(state != EXIT_DEAD);
                return 0;
        }
-       if (unlikely(p->exit_signal == -1 && p->ptrace == 0)) {
-               /*
-                * This can only happen in a race with a ptraced thread
-                * dying on another processor.
-                */
-               return 0;
-       }
 
-       if (likely(p->real_parent == p->parent)) {
+       /* traced means p->ptrace, but not vice versa */
+       traced = (p->real_parent != p->parent);
+
+       if (likely(!traced)) {
                struct signal_struct *psig;
                struct signal_struct *sig;
 
@@ -1288,35 +1288,30 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
                retval = put_user(p->pid, &infop->si_pid);
        if (!retval && infop)
                retval = put_user(p->uid, &infop->si_uid);
-       if (retval) {
-               // TODO: is this safe?
-               p->exit_state = EXIT_ZOMBIE;
-               return retval;
-       }
-       retval = p->pid;
-       if (p->real_parent != p->parent) {
+       if (!retval)
+               retval = p->pid;
+
+       if (traced) {
                write_lock_irq(&tasklist_lock);
-               /* Double-check with lock held.  */
-               if (p->real_parent != p->parent) {
-                       __ptrace_unlink(p);
-                       // TODO: is this safe?
-                       p->exit_state = EXIT_ZOMBIE;
-                       /*
-                        * If this is not a detached task, notify the parent.
-                        * If it's still not detached after that, don't release
-                        * it now.
-                        */
+               /* We dropped tasklist, ptracer could die and untrace */
+               ptrace_unlink(p);
+               /*
+                * If this is not a detached task, notify the parent.
+                * If it's still not detached after that, don't release
+                * it now.
+                */
+               if (p->exit_signal != -1) {
+                       do_notify_parent(p, p->exit_signal);
                        if (p->exit_signal != -1) {
-                               do_notify_parent(p, p->exit_signal);
-                               if (p->exit_signal != -1)
-                                       p = NULL;
+                               p->exit_state = EXIT_ZOMBIE;
+                               p = NULL;
                        }
                }
                write_unlock_irq(&tasklist_lock);
        }
        if (p != NULL)
                release_task(p);
-       BUG_ON(!retval);
+
        return retval;
 }
 
@@ -1335,7 +1330,7 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader,
        if (!p->exit_code)
                return 0;
        if (delayed_group_leader && !(p->ptrace & PT_PTRACED) &&
-           p->signal && p->signal->group_stop_count > 0)
+           p->signal->group_stop_count > 0)
                /*
                 * A group stop is in progress and this is the group leader.
                 * We won't report until all threads have stopped.
@@ -1449,9 +1444,6 @@ static int wait_task_continued(struct task_struct *p, int noreap,
        pid_t pid;
        uid_t uid;
 
-       if (unlikely(!p->signal))
-               return 0;
-
        if (!(p->signal->flags & SIGNAL_STOP_CONTINUED))
                return 0;