aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/kernel/time.c25
-rw-r--r--arch/powerpc/kernel/time.c47
-rw-r--r--arch/s390/include/asm/cputime.h3
-rw-r--r--include/linux/kernel_stat.h2
-rw-r--r--kernel/sched/cputime.c26
5 files changed, 73 insertions, 30 deletions
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 16bb6eda879d..01cd43e491cd 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -116,29 +116,32 @@ void vtime_task_switch(struct task_struct *prev)
116 * Account time for a transition between system, hard irq or soft irq state. 116 * Account time for a transition between system, hard irq or soft irq state.
117 * Note that this function is called with interrupts enabled. 117 * Note that this function is called with interrupts enabled.
118 */ 118 */
119void vtime_account(struct task_struct *tsk) 119static cputime_t vtime_delta(struct task_struct *tsk)
120{ 120{
121 struct thread_info *ti = task_thread_info(tsk); 121 struct thread_info *ti = task_thread_info(tsk);
122 unsigned long flags;
123 cputime_t delta_stime; 122 cputime_t delta_stime;
124 __u64 now; 123 __u64 now;
125 124
126 local_irq_save(flags);
127
128 now = ia64_get_itc(); 125 now = ia64_get_itc();
129 126
130 delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); 127 delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
131 if (irq_count() || idle_task(smp_processor_id()) != tsk)
132 account_system_time(tsk, 0, delta_stime, delta_stime);
133 else
134 account_idle_time(delta_stime);
135 ti->ac_stime = 0; 128 ti->ac_stime = 0;
136
137 ti->ac_stamp = now; 129 ti->ac_stamp = now;
138 130
139 local_irq_restore(flags); 131 return delta_stime;
132}
133
134void vtime_account_system(struct task_struct *tsk)
135{
136 cputime_t delta = vtime_delta(tsk);
137
138 account_system_time(tsk, 0, delta, delta);
139}
140
141void vtime_account_idle(struct task_struct *tsk)
142{
143 account_idle_time(vtime_delta(tsk));
140} 144}
141EXPORT_SYMBOL_GPL(vtime_account);
142 145
143/* 146/*
144 * Called from the timer interrupt handler to charge accumulated user time 147 * Called from the timer interrupt handler to charge accumulated user time
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 39899d7ebda0..29b6d3e1ea28 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -291,13 +291,12 @@ static inline u64 calculate_stolen_time(u64 stop_tb)
291 * Account time for a transition between system, hard irq 291 * Account time for a transition between system, hard irq
292 * or soft irq state. 292 * or soft irq state.
293 */ 293 */
294void vtime_account(struct task_struct *tsk) 294static u64 vtime_delta(struct task_struct *tsk,
295 u64 *sys_scaled, u64 *stolen)
295{ 296{
296 u64 now, nowscaled, delta, deltascaled; 297 u64 now, nowscaled, deltascaled;
297 unsigned long flags; 298 u64 udelta, delta, user_scaled;
298 u64 stolen, udelta, sys_scaled, user_scaled;
299 299
300 local_irq_save(flags);
301 now = mftb(); 300 now = mftb();
302 nowscaled = read_spurr(now); 301 nowscaled = read_spurr(now);
303 get_paca()->system_time += now - get_paca()->starttime; 302 get_paca()->system_time += now - get_paca()->starttime;
@@ -305,7 +304,7 @@ void vtime_account(struct task_struct *tsk)
305 deltascaled = nowscaled - get_paca()->startspurr; 304 deltascaled = nowscaled - get_paca()->startspurr;
306 get_paca()->startspurr = nowscaled; 305 get_paca()->startspurr = nowscaled;
307 306
308 stolen = calculate_stolen_time(now); 307 *stolen = calculate_stolen_time(now);
309 308
310 delta = get_paca()->system_time; 309 delta = get_paca()->system_time;
311 get_paca()->system_time = 0; 310 get_paca()->system_time = 0;
@@ -322,28 +321,38 @@ void vtime_account(struct task_struct *tsk)
322 * the user ticks get saved up in paca->user_time_scaled to be 321 * the user ticks get saved up in paca->user_time_scaled to be
323 * used by account_process_tick. 322 * used by account_process_tick.
324 */ 323 */
325 sys_scaled = delta; 324 *sys_scaled = delta;
326 user_scaled = udelta; 325 user_scaled = udelta;
327 if (deltascaled != delta + udelta) { 326 if (deltascaled != delta + udelta) {
328 if (udelta) { 327 if (udelta) {
329 sys_scaled = deltascaled * delta / (delta + udelta); 328 *sys_scaled = deltascaled * delta / (delta + udelta);
330 user_scaled = deltascaled - sys_scaled; 329 user_scaled = deltascaled - *sys_scaled;
331 } else { 330 } else {
332 sys_scaled = deltascaled; 331 *sys_scaled = deltascaled;
333 } 332 }
334 } 333 }
335 get_paca()->user_time_scaled += user_scaled; 334 get_paca()->user_time_scaled += user_scaled;
336 335
337 if (in_interrupt() || idle_task(smp_processor_id()) != tsk) { 336 return delta;
338 account_system_time(tsk, 0, delta, sys_scaled); 337}
339 if (stolen) 338
340 account_steal_time(stolen); 339void vtime_account_system(struct task_struct *tsk)
341 } else { 340{
342 account_idle_time(delta + stolen); 341 u64 delta, sys_scaled, stolen;
343 } 342
344 local_irq_restore(flags); 343 delta = vtime_delta(tsk, &sys_scaled, &stolen);
344 account_system_time(tsk, 0, delta, sys_scaled);
345 if (stolen)
346 account_steal_time(stolen);
347}
348
349void vtime_account_idle(struct task_struct *tsk)
350{
351 u64 delta, sys_scaled, stolen;
352
353 delta = vtime_delta(tsk, &sys_scaled, &stolen);
354 account_idle_time(delta + stolen);
345} 355}
346EXPORT_SYMBOL_GPL(vtime_account);
347 356
348/* 357/*
349 * Transfer the user and system times accumulated in the paca 358 * Transfer the user and system times accumulated in the paca
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index 8709bdef233c..023d5ae24482 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -12,6 +12,9 @@
12#include <linux/spinlock.h> 12#include <linux/spinlock.h>
13#include <asm/div64.h> 13#include <asm/div64.h>
14 14
15
16#define __ARCH_HAS_VTIME_ACCOUNT
17
15/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ 18/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */
16 19
17typedef unsigned long long __nocast cputime_t; 20typedef unsigned long long __nocast cputime_t;
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index ca0944b92f4a..36d12f0884c3 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -132,6 +132,8 @@ extern void account_idle_ticks(unsigned long ticks);
132 132
133#ifdef CONFIG_VIRT_CPU_ACCOUNTING 133#ifdef CONFIG_VIRT_CPU_ACCOUNTING
134extern void vtime_task_switch(struct task_struct *prev); 134extern void vtime_task_switch(struct task_struct *prev);
135extern void vtime_account_system(struct task_struct *tsk);
136extern void vtime_account_idle(struct task_struct *tsk);
135#else 137#else
136static inline void vtime_task_switch(struct task_struct *prev) { } 138static inline void vtime_task_switch(struct task_struct *prev) { }
137#endif 139#endif
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 53f5b12f2821..81b763ba58a6 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -432,6 +432,32 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
432 *ut = cputime.utime; 432 *ut = cputime.utime;
433 *st = cputime.stime; 433 *st = cputime.stime;
434} 434}
435
436/*
437 * Archs that account the whole time spent in the idle task
438 * (outside irq) as idle time can rely on this and just implement
439 * vtime_account_system() and vtime_account_idle(). Archs that
440 * have other meaning of the idle time (s390 only includes the
441 * time spent by the CPU when it's in low power mode) must override
442 * vtime_account().
443 */
444#ifndef __ARCH_HAS_VTIME_ACCOUNT
445void vtime_account(struct task_struct *tsk)
446{
447 unsigned long flags;
448
449 local_irq_save(flags);
450
451 if (in_interrupt() || !is_idle_task(tsk))
452 vtime_account_system(tsk);
453 else
454 vtime_account_idle(tsk);
455
456 local_irq_restore(flags);
457}
458EXPORT_SYMBOL_GPL(vtime_account);
459#endif /* __ARCH_HAS_VTIME_ACCOUNT */
460
435#else 461#else
436 462
437#ifndef nsecs_to_cputime 463#ifndef nsecs_to_cputime