]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - kernel/exit.c
Freezer: make kernel threads nonfreezable by default
[net-next-2.6.git] / kernel / exit.c
index 5b888c24e43e0ce650e554c5cec34a99f699c1fd..e8af8d0c2483232248ba163dc0e9eb03ad6ed504 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/mempolicy.h>
 #include <linux/taskstats_kern.h>
 #include <linux/delayacct.h>
+#include <linux/freezer.h>
 #include <linux/cpuset.h>
 #include <linux/syscalls.h>
 #include <linux/signal.h>
@@ -122,9 +123,9 @@ static void __exit_signal(struct task_struct *tsk)
                sig->maj_flt += tsk->maj_flt;
                sig->nvcsw += tsk->nvcsw;
                sig->nivcsw += tsk->nivcsw;
-               sig->sched_time += tsk->sched_time;
                sig->inblock += task_io_get_inblock(tsk);
                sig->oublock += task_io_get_oublock(tsk);
+               sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
                sig = NULL; /* Marker for below. */
        }
 
@@ -182,7 +183,6 @@ repeat:
                zap_leader = (leader->exit_signal == -1);
        }
 
-       sched_exit(p);
        write_unlock_irq(&tasklist_lock);
        proc_flush_task(p);
        release_thread(p);
@@ -291,7 +291,7 @@ static void reparent_to_kthreadd(void)
        /* Set the exit signal to SIGCHLD so we signal init on exit */
        current->exit_signal = SIGCHLD;
 
-       if (!has_rt_policy(current) && (task_nice(current) < 0))
+       if (task_nice(current) < 0)
                set_user_nice(current, 0);
        /* cpus_allowed? */
        /* rt_priority? */
@@ -388,6 +388,11 @@ void daemonize(const char *name, ...)
         * they would be locked into memory.
         */
        exit_mm(current);
+       /*
+        * We don't want to have TIF_FREEZE set if the system-wide hibernation
+        * or suspend transition begins right now.
+        */
+       current->flags |= PF_NOFREEZE;
 
        set_special_pids(1, 1);
        proc_clear_tty(current);
@@ -859,6 +864,34 @@ static void exit_notify(struct task_struct *tsk)
                release_task(tsk);
 }
 
+#ifdef CONFIG_DEBUG_STACK_USAGE
+static void check_stack_usage(void)
+{
+       static DEFINE_SPINLOCK(low_water_lock);
+       static int lowest_to_date = THREAD_SIZE;
+       unsigned long *n = end_of_stack(current);
+       unsigned long free;
+
+       while (*n == 0)
+               n++;
+       free = (unsigned long)n - (unsigned long)end_of_stack(current);
+
+       if (free >= lowest_to_date)
+               return;
+
+       spin_lock(&low_water_lock);
+       if (free < lowest_to_date) {
+               printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
+                               "left\n",
+                               current->comm, free);
+               lowest_to_date = free;
+       }
+       spin_unlock(&low_water_lock);
+}
+#else
+static inline void check_stack_usage(void) {}
+#endif
+
 fastcall NORET_TYPE void do_exit(long code)
 {
        struct task_struct *tsk = current;
@@ -892,13 +925,29 @@ fastcall NORET_TYPE void do_exit(long code)
        if (unlikely(tsk->flags & PF_EXITING)) {
                printk(KERN_ALERT
                        "Fixing recursive fault but reboot is needed!\n");
+               /*
+                * We can do this unlocked here. The futex code uses
+                * this flag just to verify whether the pi state
+                * cleanup has been done or not. In the worst case it
+                * loops once more. We pretend that the cleanup was
+                * done as there is no way to return. Either the
+                * OWNER_DIED bit is set by now or we push the blocked
+                * task into the wait for ever nirwana as well.
+                */
+               tsk->flags |= PF_EXITPIDONE;
                if (tsk->io_context)
                        exit_io_context();
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule();
        }
 
+       /*
+        * tsk->flags are checked in the futex code to protect against
+        * an exiting task cleaning up the robust pi futexes.
+        */
+       spin_lock_irq(&tsk->pi_lock);
        tsk->flags |= PF_EXITING;
+       spin_unlock_irq(&tsk->pi_lock);
 
        if (unlikely(in_atomic()))
                printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
@@ -912,7 +961,7 @@ fastcall NORET_TYPE void do_exit(long code)
        }
        group_dead = atomic_dec_and_test(&tsk->signal->live);
        if (group_dead) {
-               hrtimer_cancel(&tsk->signal->real_timer);
+               hrtimer_cancel(&tsk->signal->real_timer);
                exit_itimers(tsk->signal);
        }
        acct_collect(code, group_dead);
@@ -922,6 +971,8 @@ fastcall NORET_TYPE void do_exit(long code)
        if (unlikely(tsk->compat_robust_list))
                compat_exit_robust_list(tsk);
 #endif
+       if (group_dead)
+               tty_audit_exit();
        if (unlikely(tsk->audit_context))
                audit_free(tsk);
 
@@ -934,6 +985,7 @@ fastcall NORET_TYPE void do_exit(long code)
        exit_sem(tsk);
        __exit_files(tsk);
        __exit_fs(tsk);
+       check_stack_usage();
        exit_thread();
        cpuset_exit(tsk);
        exit_keys(tsk);
@@ -965,6 +1017,12 @@ fastcall NORET_TYPE void do_exit(long code)
         * Make sure we are holding no locks:
         */
        debug_check_no_locks_held(tsk);
+       /*
+        * We can do this unlocked here. The futex code uses this flag
+        * just to verify whether the pi state cleanup has been done
+        * or not. In the worst case it loops once more.
+        */
+       tsk->flags |= PF_EXITPIDONE;
 
        if (tsk->io_context)
                exit_io_context();