]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/exit.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / kernel / exit.c
index 2385d434a46eeffd1d36450a1dad590c8eeaff41..b67c57faa705d991f87b13e6b17bde64afea9131 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/shm.h>
 #include <linux/kcov.h>
 #include <linux/random.h>
+#include <linux/rcuwait.h>
 
 #include <linux/uaccess.h>
 #include <asm/unistd.h>
@@ -86,7 +87,7 @@ static void __exit_signal(struct task_struct *tsk)
        bool group_dead = thread_group_leader(tsk);
        struct sighand_struct *sighand;
        struct tty_struct *uninitialized_var(tty);
-       cputime_t utime, stime;
+       u64 utime, stime;
 
        sighand = rcu_dereference_check(tsk->sighand,
                                        lockdep_tasklist_lock_is_held());
@@ -282,6 +283,35 @@ struct task_struct *task_rcu_dereference(struct task_struct **ptask)
        return task;
 }
 
+void rcuwait_wake_up(struct rcuwait *w)
+{
+       struct task_struct *task;
+
+       rcu_read_lock();
+
+       /*
+        * Order condition vs @task, such that everything prior to the load
+        * of @task is visible. This is the condition as to why the user called
+        * rcuwait_trywake() in the first place. Pairs with set_current_state()
+        * barrier (A) in rcuwait_wait_event().
+        *
+        *    WAIT                WAKE
+        *    [S] tsk = current   [S] cond = true
+        *        MB (A)              MB (B)
+        *    [L] cond            [L] tsk
+        */
+       smp_rmb(); /* (B) */
+
+       /*
+        * Avoid using task_rcu_dereference() magic as long as we are careful,
+        * see comment in rcuwait_wait_event() regarding ->exit_state.
+        */
+       task = rcu_dereference(w->task);
+       if (task)
+               wake_up_process(task);
+       rcu_read_unlock();
+}
+
 struct task_struct *try_get_task_struct(struct task_struct **ptask)
 {
        struct task_struct *task;
@@ -501,12 +531,12 @@ static void exit_mm(void)
                        complete(&core_state->startup);
 
                for (;;) {
-                       set_task_state(current, TASK_UNINTERRUPTIBLE);
+                       set_current_state(TASK_UNINTERRUPTIBLE);
                        if (!self.task) /* see coredump_finish() */
                                break;
                        freezable_schedule();
                }
-               __set_task_state(current, TASK_RUNNING);
+               __set_current_state(TASK_RUNNING);
                down_read(&mm->mmap_sem);
        }
        atomic_inc(&mm->mm_count);
@@ -1091,7 +1121,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
                struct signal_struct *sig = p->signal;
                struct signal_struct *psig = current->signal;
                unsigned long maxrss;
-               cputime_t tgutime, tgstime;
+               u64 tgutime, tgstime;
 
                /*
                 * The resource counters for the group leader are in its