sched: change nr_context_switches calculation.
This patch changes the calculation of nr_context_switches. The variable
"nr_switches" is now used to account for the number of transition to the
idle task, or stop task. It is removed from the schedule() path.
The total calculation can be made using the fact that the transitions to
fair and rt classes are recorded in the root_task_group. One can easily
derive the total figure by adding those quantities together.
Signed-off-by: Glauber Costa <glommer@openvz.org>
CC: Peter Zijlstra <a.p.zijlstra@chello.nl>
CC: Paul Turner <pjt@google.com>
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index b34fe0b..7997a70 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2053,13 +2053,27 @@
return sum;
}
+#ifdef CONFIG_FAIR_GROUP_SCHED
+#define cfs_nr_switches(tg, cpu) (tg)->cfs_rq[cpu]->nr_switches
+#else
+#define cfs_nr_switches(tg, cpu) cpu_rq(cpu)->cfs.nr_switches
+#endif
+#ifdef CONFIG_RT_GROUP_SCHED
+#define rt_nr_switches(tg, cpu) (tg)->rt_rq[cpu]->rt_nr_switches
+#else
+#define rt_nr_switches(tg, cpu) cpu_rq(cpu)->rt.rt_nr_switches
+#endif
+
unsigned long long nr_context_switches(void)
{
int i;
unsigned long long sum = 0;
- for_each_possible_cpu(i)
+ for_each_possible_cpu(i) {
+ sum += cfs_nr_switches(&root_task_group, i);
+ sum += rt_nr_switches(&root_task_group, i);
sum += cpu_rq(i)->nr_switches;
+ }
return sum;
}
@@ -2439,7 +2453,6 @@
rq->skip_clock_update = 0;
if (likely(prev != next)) {
- rq->nr_switches++;
rq->curr = next;
++*switch_count;
diff --git a/kernel/sched/idle_task.c b/kernel/sched/idle_task.c
index 4f0a332..923286c 100644
--- a/kernel/sched/idle_task.c
+++ b/kernel/sched/idle_task.c
@@ -39,6 +39,9 @@
if (prev)
prev->sched_class->put_prev_task(rq, prev);
+ if (prev != rq->idle)
+ rq->nr_switches++;
+
schedstat_inc(rq, sched_goidle);
#ifdef CONFIG_SMP
/* Trigger the post schedule to do an idle_enter for CFS */
diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c
index 5f10918..d1e9b82 100644
--- a/kernel/sched/stop_task.c
+++ b/kernel/sched/stop_task.c
@@ -32,6 +32,8 @@
stop->se.exec_start = rq->clock_task;
if (prev)
prev->sched_class->put_prev_task(rq, prev);
+ if (prev != rq->stop)
+ rq->nr_switches++;
return stop;
}