aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-11-09 16:39:38 -0500
committerIngo Molnar <mingo@elte.hu>2007-11-09 16:39:38 -0500
commitfa13a5a1f25f671d084d8884be96fc48d9b68275 (patch)
tree97dae05bb5baef806a6dcbeed8b7eb5bdc61e4ae
parent9a41785cc43d88397f787a651ed7286a33f8462f (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>
-rw-r--r--arch/powerpc/kernel/process.c2
-rw-r--r--arch/powerpc/kernel/time.c25
-rw-r--r--arch/s390/kernel/time.c4
-rw-r--r--arch/s390/kernel/vtime.c8
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/timer.c21
6 files changed, 18 insertions, 43 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index b9d88374f14f..41e13f4cc6e3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -350,7 +350,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
350 local_irq_save(flags); 350 local_irq_save(flags);
351 351
352 account_system_vtime(current); 352 account_system_vtime(current);
353 account_process_vtime(current); 353 account_process_tick(current, 0);
354 calculate_steal_time(); 354 calculate_steal_time();
355 355
356 last = _switch(old_thread, new_thread); 356 last = _switch(old_thread, new_thread);
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 9eb3284deac4..a70dfb76d0a8 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -259,7 +259,7 @@ void account_system_vtime(struct task_struct *tsk)
259 * user and system time records. 259 * user and system time records.
260 * Must be called with interrupts disabled. 260 * Must be called with interrupts disabled.
261 */ 261 */
262void account_process_vtime(struct task_struct *tsk) 262void account_process_tick(struct task_struct *tsk, int user_tick)
263{ 263{
264 cputime_t utime, utimescaled; 264 cputime_t utime, utimescaled;
265 265
@@ -274,18 +274,6 @@ void account_process_vtime(struct task_struct *tsk)
274 account_user_time_scaled(tsk, utimescaled); 274 account_user_time_scaled(tsk, utimescaled);
275} 275}
276 276
277static void account_process_time(struct pt_regs *regs)
278{
279 int cpu = smp_processor_id();
280
281 account_process_vtime(current);
282 run_local_timers();
283 if (rcu_pending(cpu))
284 rcu_check_callbacks(cpu, user_mode(regs));
285 scheduler_tick();
286 run_posix_cpu_timers(current);
287}
288
289/* 277/*
290 * Stuff for accounting stolen time. 278 * Stuff for accounting stolen time.
291 */ 279 */
@@ -375,7 +363,6 @@ static void snapshot_purr(void)
375 363
376#else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ 364#else /* ! CONFIG_VIRT_CPU_ACCOUNTING */
377#define calc_cputime_factors() 365#define calc_cputime_factors()
378#define account_process_time(regs) update_process_times(user_mode(regs))
379#define calculate_steal_time() do { } while (0) 366#define calculate_steal_time() do { } while (0)
380#endif 367#endif
381 368
@@ -599,16 +586,6 @@ void timer_interrupt(struct pt_regs * regs)
599 get_lppaca()->int_dword.fields.decr_int = 0; 586 get_lppaca()->int_dword.fields.decr_int = 0;
600#endif 587#endif
601 588
602 /*
603 * We cannot disable the decrementer, so in the period
604 * between this cpu's being marked offline in cpu_online_map
605 * and calling stop-self, it is taking timer interrupts.
606 * Avoid calling into the scheduler rebalancing code if this
607 * is the case.
608 */
609 if (!cpu_is_offline(cpu))
610 account_process_time(regs);
611
612 if (evt->event_handler) 589 if (evt->event_handler)
613 evt->event_handler(evt); 590 evt->event_handler(evt);
614 else 591 else
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index a963fe81359e..22b800ce2126 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -145,12 +145,8 @@ void account_ticks(u64 time)
145 do_timer(ticks); 145 do_timer(ticks);
146#endif 146#endif
147 147
148#ifdef CONFIG_VIRT_CPU_ACCOUNTING
149 account_tick_vtime(current);
150#else
151 while (ticks--) 148 while (ticks--)
152 update_process_times(user_mode(get_irq_regs())); 149 update_process_times(user_mode(get_irq_regs()));
153#endif
154 150
155 s390_do_profile(); 151 s390_do_profile();
156} 152}
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 84ff78de6bac..c5f05b3fb2c3 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -32,7 +32,7 @@ static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
32 * Update process times based on virtual cpu times stored by entry.S 32 * Update process times based on virtual cpu times stored by entry.S
33 * to the lowcore fields user_timer, system_timer & steal_clock. 33 * to the lowcore fields user_timer, system_timer & steal_clock.
34 */ 34 */
35void account_tick_vtime(struct task_struct *tsk) 35void account_process_tick(struct task_struct *tsk, int user_tick)
36{ 36{
37 cputime_t cputime; 37 cputime_t cputime;
38 __u64 timer, clock; 38 __u64 timer, clock;
@@ -64,12 +64,6 @@ void account_tick_vtime(struct task_struct *tsk)
64 S390_lowcore.steal_clock -= cputime << 12; 64 S390_lowcore.steal_clock -= cputime << 12;
65 account_steal_time(tsk, cputime); 65 account_steal_time(tsk, cputime);
66 } 66 }
67
68 run_local_timers();
69 if (rcu_pending(smp_processor_id()))
70 rcu_check_callbacks(smp_processor_id(), rcu_user_flag);
71 scheduler_tick();
72 run_posix_cpu_timers(tsk);
73} 67}
74 68
75/* 69/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5457b6234e11..951759e30c09 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -254,6 +254,7 @@ long io_schedule_timeout(long timeout);
254 254
255extern void cpu_init (void); 255extern void cpu_init (void);
256extern void trap_init(void); 256extern void trap_init(void);
257extern void account_process_tick(struct task_struct *task, int user);
257extern void update_process_times(int user); 258extern void update_process_times(int user);
258extern void scheduler_tick(void); 259extern void scheduler_tick(void);
259 260
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
821void 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);