diff options
author | Paul Mackerras <paulus@samba.org> | 2007-11-09 16:39:38 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2007-11-09 16:39:38 -0500 |
commit | fa13a5a1f25f671d084d8884be96fc48d9b68275 (patch) | |
tree | 97dae05bb5baef806a6dcbeed8b7eb5bdc61e4ae /kernel | |
parent | 9a41785cc43d88397f787a651ed7286a33f8462f (diff) |
sched: restore deterministic CPU accounting on powerpc
Since powerpc started using CONFIG_GENERIC_CLOCKEVENTS, the
deterministic CPU accounting (CONFIG_VIRT_CPU_ACCOUNTING) has been
broken on powerpc, because we end up counting user time twice: once in
timer_interrupt() and once in update_process_times().
This fixes the problem by pulling the code in update_process_times
that updates utime and stime into a separate function called
account_process_tick. If CONFIG_VIRT_CPU_ACCOUNTING is not defined,
there is a version of account_process_tick in kernel/timer.c that
simply accounts a whole tick to either utime or stime as before. If
CONFIG_VIRT_CPU_ACCOUNTING is defined, then arch code gets to
implement account_process_tick.
This also lets us simplify the s390 code a bit; it means that the s390
timer interrupt can now call update_process_times even when
CONFIG_VIRT_CPU_ACCOUNTING is turned on, and can just implement a
suitable account_process_tick().
account_process_tick() now takes the task_struct * as an argument.
Tested both with and without CONFIG_VIRT_CPU_ACCOUNTING.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/timer.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index 00e44e2afd67..a05817c021d6 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -817,6 +817,19 @@ unsigned long next_timer_interrupt(void) | |||
817 | 817 | ||
818 | #endif | 818 | #endif |
819 | 819 | ||
820 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | ||
821 | void account_process_tick(struct task_struct *p, int user_tick) | ||
822 | { | ||
823 | if (user_tick) { | ||
824 | account_user_time(p, jiffies_to_cputime(1)); | ||
825 | account_user_time_scaled(p, jiffies_to_cputime(1)); | ||
826 | } else { | ||
827 | account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1)); | ||
828 | account_system_time_scaled(p, jiffies_to_cputime(1)); | ||
829 | } | ||
830 | } | ||
831 | #endif | ||
832 | |||
820 | /* | 833 | /* |
821 | * Called from the timer interrupt handler to charge one tick to the current | 834 | * Called from the timer interrupt handler to charge one tick to the current |
822 | * process. user_tick is 1 if the tick is user time, 0 for system. | 835 | * process. user_tick is 1 if the tick is user time, 0 for system. |
@@ -827,13 +840,7 @@ void update_process_times(int user_tick) | |||
827 | int cpu = smp_processor_id(); | 840 | int cpu = smp_processor_id(); |
828 | 841 | ||
829 | /* Note: this timer irq context must be accounted for as well. */ | 842 | /* Note: this timer irq context must be accounted for as well. */ |
830 | if (user_tick) { | 843 | account_process_tick(p, user_tick); |
831 | account_user_time(p, jiffies_to_cputime(1)); | ||
832 | account_user_time_scaled(p, jiffies_to_cputime(1)); | ||
833 | } else { | ||
834 | account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1)); | ||
835 | account_system_time_scaled(p, jiffies_to_cputime(1)); | ||
836 | } | ||
837 | run_local_timers(); | 844 | run_local_timers(); |
838 | if (rcu_pending(cpu)) | 845 | if (rcu_pending(cpu)) |
839 | rcu_check_callbacks(cpu, user_tick); | 846 | rcu_check_callbacks(cpu, user_tick); |