sched: Snapshot thread flags
[linux-2.6-block.git] / kernel / sched / core.c
index 523fd602ea90cd9015aa17699e878814d337d1f3..704262798fb7849a3b70f57cdfaede1f94863c0b 100644 (file)
@@ -3726,6 +3726,9 @@ out:
 
 bool cpus_share_cache(int this_cpu, int that_cpu)
 {
+       if (this_cpu == that_cpu)
+               return true;
+
        return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu);
 }
 
@@ -6625,13 +6628,13 @@ __setup("preempt=", setup_preempt_mode);
 static void __init preempt_dynamic_init(void)
 {
        if (preempt_dynamic_mode == preempt_dynamic_undefined) {
-               if (IS_ENABLED(CONFIG_PREEMPT_NONE_BEHAVIOUR)) {
+               if (IS_ENABLED(CONFIG_PREEMPT_NONE)) {
                        sched_dynamic_update(preempt_dynamic_none);
-               } else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY_BEHAVIOUR)) {
+               } else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY)) {
                        sched_dynamic_update(preempt_dynamic_voluntary);
                } else {
                        /* Default static call setting, nothing to do */
-                       WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT_BEHAVIOUR));
+                       WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT));
                        preempt_dynamic_mode = preempt_dynamic_full;
                        pr_info("Dynamic Preempt: full\n");
                }
@@ -8517,7 +8520,7 @@ void sched_show_task(struct task_struct *p)
        rcu_read_unlock();
        pr_cont(" stack:%5lu pid:%5d ppid:%6d flags:0x%08lx\n",
                free, task_pid_nr(p), ppid,
-               (unsigned long)task_thread_info(p)->flags);
+               read_task_thread_flags(p));
 
        print_worker_info(KERN_INFO, p);
        print_stop_info(KERN_INFO, p);
@@ -8616,9 +8619,6 @@ void __init init_idle(struct task_struct *idle, int cpu)
        idle->flags |= PF_IDLE | PF_KTHREAD | PF_NO_SETAFFINITY;
        kthread_set_per_cpu(idle, cpu);
 
-       scs_task_reset(idle);
-       kasan_unpoison_task_stack(idle);
-
 #ifdef CONFIG_SMP
        /*
         * It's possible that init_idle() gets called multiple times on a task,
@@ -8774,7 +8774,6 @@ void idle_task_exit(void)
                finish_arch_post_lock_switch();
        }
 
-       scs_task_reset(current);
        /* finish_cpu(), as ran on the BP, will clean up the active_mm state */
 }
 
@@ -9716,6 +9715,22 @@ static void sched_free_group(struct task_group *tg)
        kmem_cache_free(task_group_cache, tg);
 }
 
+static void sched_free_group_rcu(struct rcu_head *rcu)
+{
+       sched_free_group(container_of(rcu, struct task_group, rcu));
+}
+
+static void sched_unregister_group(struct task_group *tg)
+{
+       unregister_fair_sched_group(tg);
+       unregister_rt_sched_group(tg);
+       /*
+        * We have to wait for yet another RCU grace period to expire, as
+        * print_cfs_stats() might run concurrently.
+        */
+       call_rcu(&tg->rcu, sched_free_group_rcu);
+}
+
 /* allocate runqueue etc for a new task group */
 struct task_group *sched_create_group(struct task_group *parent)
 {
@@ -9759,25 +9774,35 @@ void sched_online_group(struct task_group *tg, struct task_group *parent)
 }
 
 /* rcu callback to free various structures associated with a task group */
-static void sched_free_group_rcu(struct rcu_head *rhp)
+static void sched_unregister_group_rcu(struct rcu_head *rhp)
 {
        /* Now it should be safe to free those cfs_rqs: */
-       sched_free_group(container_of(rhp, struct task_group, rcu));
+       sched_unregister_group(container_of(rhp, struct task_group, rcu));
 }
 
 void sched_destroy_group(struct task_group *tg)
 {
        /* Wait for possible concurrent references to cfs_rqs complete: */
-       call_rcu(&tg->rcu, sched_free_group_rcu);
+       call_rcu(&tg->rcu, sched_unregister_group_rcu);
 }
 
-void sched_offline_group(struct task_group *tg)
+void sched_release_group(struct task_group *tg)
 {
        unsigned long flags;
 
-       /* End participation in shares distribution: */
-       unregister_fair_sched_group(tg);
-
+       /*
+        * Unlink first, to avoid walk_tg_tree_from() from finding us (via
+        * sched_cfs_period_timer()).
+        *
+        * For this to be effective, we have to wait for all pending users of
+        * this task group to leave their RCU critical section to ensure no new
+        * user will see our dying task group any more. Specifically ensure
+        * that tg_unthrottle_up() won't add decayed cfs_rq's to it.
+        *
+        * We therefore defer calling unregister_fair_sched_group() to
+        * sched_unregister_group() which is guarantied to get called only after the
+        * current RCU grace period has expired.
+        */
        spin_lock_irqsave(&task_group_lock, flags);
        list_del_rcu(&tg->list);
        list_del_rcu(&tg->siblings);
@@ -9896,7 +9921,7 @@ static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
 {
        struct task_group *tg = css_tg(css);
 
-       sched_offline_group(tg);
+       sched_release_group(tg);
 }
 
 static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
@@ -9906,7 +9931,7 @@ static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
        /*
         * Relies on the RCU grace period between css_released() and this.
         */
-       sched_free_group(tg);
+       sched_unregister_group(tg);
 }
 
 /*