From 7be69615b4e6c721bdeeadfede771546ef4d44d8 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 2 Feb 2010 14:46:13 -0800 Subject: [PATCH] --- yaml --- r: 182519 b: refs/heads/master c: fa535a77bd3fa32b9215ba375d6a202fe73e1dd6 h: refs/heads/master i: 182517: 9974d5d12f4668a2284f02119462e08ffc8a79a9 182515: 54c9bb6245125c53b871ffd01b3139edcb9b87ab 182511: ce7ff1d7b70989e4914f6f25aca6f3644a1ee26a v: v3 --- [refs] | 2 +- trunk/kernel/sched.c | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index f21b6089709e..3703aace0256 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0c9cf2efd74dbc90354e2ccc7dbd6bad68ec6c4d +refs/heads/master: fa535a77bd3fa32b9215ba375d6a202fe73e1dd6 diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index f96be9370b75..bae6fcfe6d75 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -8997,6 +8997,23 @@ static void cpuacct_charge(struct task_struct *tsk, u64 cputime) rcu_read_unlock(); } +/* + * When CONFIG_VIRT_CPU_ACCOUNTING is enabled one jiffy can be very large + * in cputime_t units. As a result, cpuacct_update_stats calls + * percpu_counter_add with values large enough to always overflow the + * per cpu batch limit causing bad SMP scalability. + * + * To fix this we scale percpu_counter_batch by cputime_one_jiffy so we + * batch the same amount of time with CONFIG_VIRT_CPU_ACCOUNTING disabled + * and enabled. We cap it at INT_MAX which is the largest allowed batch value. + */ +#ifdef CONFIG_SMP +#define CPUACCT_BATCH \ + min_t(long, percpu_counter_batch * cputime_one_jiffy, INT_MAX) +#else +#define CPUACCT_BATCH 0 +#endif + /* * Charge the system/user time to the task's accounting group. */ @@ -9004,6 +9021,7 @@ static void cpuacct_update_stats(struct task_struct *tsk, enum cpuacct_stat_index idx, cputime_t val) { struct cpuacct *ca; + int batch = CPUACCT_BATCH; if (unlikely(!cpuacct_subsys.active)) return; @@ -9012,7 +9030,7 @@ static void cpuacct_update_stats(struct task_struct *tsk, ca = task_ca(tsk); do { - percpu_counter_add(&ca->cpustat[idx], val); + __percpu_counter_add(&ca->cpustat[idx], val, batch); ca = ca->parent; } while (ca); rcu_read_unlock();