diff options
-rw-r--r-- | arch/ia64/kernel/time.c | 25 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 47 | ||||
-rw-r--r-- | arch/s390/include/asm/cputime.h | 3 | ||||
-rw-r--r-- | include/linux/kernel_stat.h | 2 | ||||
-rw-r--r-- | kernel/sched/cputime.c | 26 |
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 | */ |
119 | void vtime_account(struct task_struct *tsk) | 119 | static 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 | |||
134 | void 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 | |||
141 | void vtime_account_idle(struct task_struct *tsk) | ||
142 | { | ||
143 | account_idle_time(vtime_delta(tsk)); | ||
140 | } | 144 | } |
141 | EXPORT_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 | */ |
294 | void vtime_account(struct task_struct *tsk) | 294 | static 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); | 339 | void 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 | |||
349 | void 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 | } |
346 | EXPORT_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 | ||
17 | typedef unsigned long long __nocast cputime_t; | 20 | typedef 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 |
134 | extern void vtime_task_switch(struct task_struct *prev); | 134 | extern void vtime_task_switch(struct task_struct *prev); |
135 | extern void vtime_account_system(struct task_struct *tsk); | ||
136 | extern void vtime_account_idle(struct task_struct *tsk); | ||
135 | #else | 137 | #else |
136 | static inline void vtime_task_switch(struct task_struct *prev) { } | 138 | static 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 | ||
445 | void 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 | } | ||
458 | EXPORT_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 |