aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched/stats.h
diff options
context:
space:
mode:
authorJason Low <jason.low2@hp.com>2015-04-28 16:00:22 -0400
committerIngo Molnar <mingo@kernel.org>2015-05-08 06:15:31 -0400
commit1018016c706f7ff9f56fde3a649789c47085a293 (patch)
tree1f564aa153c8b4d3610c354ebb3e963c6a29e165 /kernel/sched/stats.h
parent7e5a2c1729f1612618ed236249a15bf15f309325 (diff)
sched, timer: Replace spinlocks with atomics in thread_group_cputimer(), to improve scalability
While running a database workload, we found a scalability issue with itimers. Much of the problem was caused by the thread_group_cputimer spinlock. Each time we account for group system/user time, we need to obtain a thread_group_cputimer's spinlock to update the timers. On larger systems (such as a 16 socket machine), this caused more than 30% of total time spent trying to obtain this kernel lock to update these group timer stats. This patch converts the timers to 64-bit atomic variables and use atomic add to update them without a lock. With this patch, the percent of total time spent updating thread group cputimer timers was reduced from 30% down to less than 1%. Note: On 32-bit systems using the generic 64-bit atomics, this causes sample_group_cputimer() to take locks 3 times instead of just 1 time. However, we tested this patch on a 32-bit system ARM system using the generic atomics and did not find the overhead to be much of an issue. An explanation for why this isn't an issue is that 32-bit systems usually have small numbers of CPUs, and cacheline contention from extra spinlocks called periodically is not really apparent on smaller systems. Signed-off-by: Jason Low <jason.low2@hp.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Rik van Riel <riel@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Aswin Chandramouleeswaran <aswin@hp.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Mike Galbraith <umgwanakikbuti@gmail.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Preeti U Murthy <preeti@linux.vnet.ibm.com> Cc: Scott J Norton <scott.norton@hp.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Waiman Long <Waiman.Long@hp.com> Link: http://lkml.kernel.org/r/1430251224-5764-4-git-send-email-jason.low2@hp.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched/stats.h')
-rw-r--r--kernel/sched/stats.h15
1 files changed, 5 insertions, 10 deletions
diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h
index 4ab704339656..c6d1c7da3ea5 100644
--- a/kernel/sched/stats.h
+++ b/kernel/sched/stats.h
@@ -174,7 +174,8 @@ static inline bool cputimer_running(struct task_struct *tsk)
174{ 174{
175 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; 175 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
176 176
177 if (!cputimer->running) 177 /* Check if cputimer isn't running. This is accessed without locking. */
178 if (!READ_ONCE(cputimer->running))
178 return false; 179 return false;
179 180
180 /* 181 /*
@@ -215,9 +216,7 @@ static inline void account_group_user_time(struct task_struct *tsk,
215 if (!cputimer_running(tsk)) 216 if (!cputimer_running(tsk))
216 return; 217 return;
217 218
218 raw_spin_lock(&cputimer->lock); 219 atomic64_add(cputime, &cputimer->utime);
219 cputimer->cputime.utime += cputime;
220 raw_spin_unlock(&cputimer->lock);
221} 220}
222 221
223/** 222/**
@@ -238,9 +237,7 @@ static inline void account_group_system_time(struct task_struct *tsk,
238 if (!cputimer_running(tsk)) 237 if (!cputimer_running(tsk))
239 return; 238 return;
240 239
241 raw_spin_lock(&cputimer->lock); 240 atomic64_add(cputime, &cputimer->stime);
242 cputimer->cputime.stime += cputime;
243 raw_spin_unlock(&cputimer->lock);
244} 241}
245 242
246/** 243/**
@@ -261,7 +258,5 @@ static inline void account_group_exec_runtime(struct task_struct *tsk,
261 if (!cputimer_running(tsk)) 258 if (!cputimer_running(tsk))
262 return; 259 return;
263 260
264 raw_spin_lock(&cputimer->lock); 261 atomic64_add(ns, &cputimer->sum_exec_runtime);
265 cputimer->cputime.sum_exec_runtime += ns;
266 raw_spin_unlock(&cputimer->lock);
267} 262}