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>

authored by Paul Mackerras and committed by Ingo Molnar fa13a5a1 9a41785c

+18 -43
+1 -1
arch/powerpc/kernel/process.c
··· 350 local_irq_save(flags); 351 352 account_system_vtime(current); 353 - account_process_vtime(current); 354 calculate_steal_time(); 355 356 last = _switch(old_thread, new_thread);
··· 350 local_irq_save(flags); 351 352 account_system_vtime(current); 353 + account_process_tick(current, 0); 354 calculate_steal_time(); 355 356 last = _switch(old_thread, new_thread);
+1 -24
arch/powerpc/kernel/time.c
··· 259 * user and system time records. 260 * Must be called with interrupts disabled. 261 */ 262 - void account_process_vtime(struct task_struct *tsk) 263 { 264 cputime_t utime, utimescaled; 265 ··· 272 utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta; 273 get_paca()->spurrdelta = get_paca()->purrdelta = 0; 274 account_user_time_scaled(tsk, utimescaled); 275 - } 276 - 277 - static 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 /* ··· 363 364 #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ 365 #define calc_cputime_factors() 366 - #define account_process_time(regs) update_process_times(user_mode(regs)) 367 #define calculate_steal_time() do { } while (0) 368 #endif 369 ··· 585 if (firmware_has_feature(FW_FEATURE_ISERIES)) 586 get_lppaca()->int_dword.fields.decr_int = 0; 587 #endif 588 - 589 - /* 590 - * We cannot disable the decrementer, so in the period 591 - * between this cpu's being marked offline in cpu_online_map 592 - * and calling stop-self, it is taking timer interrupts. 593 - * Avoid calling into the scheduler rebalancing code if this 594 - * is the case. 595 - */ 596 - if (!cpu_is_offline(cpu)) 597 - account_process_time(regs); 598 599 if (evt->event_handler) 600 evt->event_handler(evt);
··· 259 * user and system time records. 260 * Must be called with interrupts disabled. 261 */ 262 + void account_process_tick(struct task_struct *tsk, int user_tick) 263 { 264 cputime_t utime, utimescaled; 265 ··· 272 utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta; 273 get_paca()->spurrdelta = get_paca()->purrdelta = 0; 274 account_user_time_scaled(tsk, utimescaled); 275 } 276 277 /* ··· 375 376 #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ 377 #define calc_cputime_factors() 378 #define calculate_steal_time() do { } while (0) 379 #endif 380 ··· 598 if (firmware_has_feature(FW_FEATURE_ISERIES)) 599 get_lppaca()->int_dword.fields.decr_int = 0; 600 #endif 601 602 if (evt->event_handler) 603 evt->event_handler(evt);
-4
arch/s390/kernel/time.c
··· 145 do_timer(ticks); 146 #endif 147 148 - #ifdef CONFIG_VIRT_CPU_ACCOUNTING 149 - account_tick_vtime(current); 150 - #else 151 while (ticks--) 152 update_process_times(user_mode(get_irq_regs())); 153 - #endif 154 155 s390_do_profile(); 156 }
··· 145 do_timer(ticks); 146 #endif 147 148 while (ticks--) 149 update_process_times(user_mode(get_irq_regs())); 150 151 s390_do_profile(); 152 }
+1 -7
arch/s390/kernel/vtime.c
··· 32 * Update process times based on virtual cpu times stored by entry.S 33 * to the lowcore fields user_timer, system_timer & steal_clock. 34 */ 35 - void account_tick_vtime(struct task_struct *tsk) 36 { 37 cputime_t cputime; 38 __u64 timer, clock; ··· 64 S390_lowcore.steal_clock -= cputime << 12; 65 account_steal_time(tsk, cputime); 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 } 74 75 /*
··· 32 * Update process times based on virtual cpu times stored by entry.S 33 * to the lowcore fields user_timer, system_timer & steal_clock. 34 */ 35 + void account_process_tick(struct task_struct *tsk, int user_tick) 36 { 37 cputime_t cputime; 38 __u64 timer, clock; ··· 64 S390_lowcore.steal_clock -= cputime << 12; 65 account_steal_time(tsk, cputime); 66 } 67 } 68 69 /*
+1
include/linux/sched.h
··· 254 255 extern void cpu_init (void); 256 extern void trap_init(void); 257 extern void update_process_times(int user); 258 extern void scheduler_tick(void); 259
··· 254 255 extern void cpu_init (void); 256 extern void trap_init(void); 257 + extern void account_process_tick(struct task_struct *task, int user); 258 extern void update_process_times(int user); 259 extern void scheduler_tick(void); 260
+14 -7
kernel/timer.c
··· 817 818 #endif 819 820 /* 821 * 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. ··· 840 int cpu = smp_processor_id(); 841 842 /* Note: this timer irq context must be accounted for as well. */ 843 - if (user_tick) { 844 - account_user_time(p, jiffies_to_cputime(1)); 845 - account_user_time_scaled(p, jiffies_to_cputime(1)); 846 - } else { 847 - account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1)); 848 - account_system_time_scaled(p, jiffies_to_cputime(1)); 849 - } 850 run_local_timers(); 851 if (rcu_pending(cpu)) 852 rcu_check_callbacks(cpu, user_tick);
··· 817 818 #endif 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 + 833 /* 834 * Called from the timer interrupt handler to charge one tick to the current 835 * process. user_tick is 1 if the tick is user time, 0 for system. ··· 827 int cpu = smp_processor_id(); 828 829 /* Note: this timer irq context must be accounted for as well. */ 830 + account_process_tick(p, user_tick); 831 run_local_timers(); 832 if (rcu_pending(cpu)) 833 rcu_check_callbacks(cpu, user_tick);