aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRik van Riel <riel@redhat.com>2016-07-13 10:50:02 -0400
committerIngo Molnar <mingo@kernel.org>2016-07-14 04:42:34 -0400
commitb58c35840521bb02b150e1d0d34ca9197f8b7145 (patch)
treea1641840e235a1035e7ad8c4276a77d25552ba4e
parent57430218317e5b280a80582a139b26029c25de6c (diff)
sched/cputime: Replace VTIME_GEN irq time code with IRQ_TIME_ACCOUNTING code
The CONFIG_VIRT_CPU_ACCOUNTING_GEN irq time tracking code does not appear to currently work right. On CPUs without nohz_full=, only tick based irq time sampling is done, which breaks down when dealing with a nohz_idle CPU. On firewalls and similar systems, no ticks may happen on a CPU for a while, and the irq time spent may never get accounted properly. This can cause issues with capacity planning and power saving, which use the CPU statistics as inputs in decision making. Remove the VTIME_GEN vtime irq time code, and replace it with the IRQ_TIME_ACCOUNTING code, when selected as a config option by the user. Signed-off-by: Rik van Riel <riel@redhat.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Radim Krcmar <rkrcmar@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Wanpeng Li <wanpeng.li@hotmail.com> Link: http://lkml.kernel.org/r/1468421405-20056-3-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--include/linux/vtime.h32
-rw-r--r--init/Kconfig6
-rw-r--r--kernel/sched/cputime.c16
3 files changed, 20 insertions, 34 deletions
diff --git a/include/linux/vtime.h b/include/linux/vtime.h
index fa2196990f84..d1977d84ebdf 100644
--- a/include/linux/vtime.h
+++ b/include/linux/vtime.h
@@ -14,6 +14,18 @@ struct task_struct;
14 */ 14 */
15#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE 15#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
16static inline bool vtime_accounting_cpu_enabled(void) { return true; } 16static inline bool vtime_accounting_cpu_enabled(void) { return true; }
17
18#ifdef __ARCH_HAS_VTIME_ACCOUNT
19extern void vtime_account_irq_enter(struct task_struct *tsk);
20#else
21extern void vtime_common_account_irq_enter(struct task_struct *tsk);
22static inline void vtime_account_irq_enter(struct task_struct *tsk)
23{
24 if (vtime_accounting_cpu_enabled())
25 vtime_common_account_irq_enter(tsk);
26}
27#endif /* __ARCH_HAS_VTIME_ACCOUNT */
28
17#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ 29#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
18 30
19#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 31#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
@@ -64,17 +76,6 @@ extern void vtime_account_system(struct task_struct *tsk);
64extern void vtime_account_idle(struct task_struct *tsk); 76extern void vtime_account_idle(struct task_struct *tsk);
65extern void vtime_account_user(struct task_struct *tsk); 77extern void vtime_account_user(struct task_struct *tsk);
66 78
67#ifdef __ARCH_HAS_VTIME_ACCOUNT
68extern void vtime_account_irq_enter(struct task_struct *tsk);
69#else
70extern void vtime_common_account_irq_enter(struct task_struct *tsk);
71static inline void vtime_account_irq_enter(struct task_struct *tsk)
72{
73 if (vtime_accounting_cpu_enabled())
74 vtime_common_account_irq_enter(tsk);
75}
76#endif /* __ARCH_HAS_VTIME_ACCOUNT */
77
78#else /* !CONFIG_VIRT_CPU_ACCOUNTING */ 79#else /* !CONFIG_VIRT_CPU_ACCOUNTING */
79 80
80static inline void vtime_task_switch(struct task_struct *prev) { } 81static inline void vtime_task_switch(struct task_struct *prev) { }
@@ -85,13 +86,8 @@ static inline void vtime_account_irq_enter(struct task_struct *tsk) { }
85 86
86#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 87#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
87extern void arch_vtime_task_switch(struct task_struct *tsk); 88extern void arch_vtime_task_switch(struct task_struct *tsk);
88extern void vtime_gen_account_irq_exit(struct task_struct *tsk); 89static inline void vtime_account_irq_enter(struct task_struct *tsk) { }
89 90static inline void vtime_account_irq_exit(struct task_struct *tsk) { }
90static inline void vtime_account_irq_exit(struct task_struct *tsk)
91{
92 if (vtime_accounting_cpu_enabled())
93 vtime_gen_account_irq_exit(tsk);
94}
95 91
96extern void vtime_user_enter(struct task_struct *tsk); 92extern void vtime_user_enter(struct task_struct *tsk);
97 93
diff --git a/init/Kconfig b/init/Kconfig
index c02d89777713..787dd76acf29 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -375,9 +375,11 @@ config VIRT_CPU_ACCOUNTING_GEN
375 375
376 If unsure, say N. 376 If unsure, say N.
377 377
378endchoice
379
378config IRQ_TIME_ACCOUNTING 380config IRQ_TIME_ACCOUNTING
379 bool "Fine granularity task level IRQ time accounting" 381 bool "Fine granularity task level IRQ time accounting"
380 depends on HAVE_IRQ_TIME_ACCOUNTING && !NO_HZ_FULL 382 depends on HAVE_IRQ_TIME_ACCOUNTING && !VIRT_CPU_ACCOUNTING_NATIVE
381 help 383 help
382 Select this option to enable fine granularity task irq time 384 Select this option to enable fine granularity task irq time
383 accounting. This is done by reading a timestamp on each 385 accounting. This is done by reading a timestamp on each
@@ -386,8 +388,6 @@ config IRQ_TIME_ACCOUNTING
386 388
387 If in doubt, say N here. 389 If in doubt, say N here.
388 390
389endchoice
390
391config BSD_PROCESS_ACCT 391config BSD_PROCESS_ACCT
392 bool "BSD Process Accounting" 392 bool "BSD Process Accounting"
393 depends on MULTIUSER 393 depends on MULTIUSER
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index db82ae12cf01..ca7e33cb0967 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -711,14 +711,14 @@ static cputime_t vtime_delta(struct task_struct *tsk)
711static cputime_t get_vtime_delta(struct task_struct *tsk) 711static cputime_t get_vtime_delta(struct task_struct *tsk)
712{ 712{
713 unsigned long now = READ_ONCE(jiffies); 713 unsigned long now = READ_ONCE(jiffies);
714 cputime_t delta, steal; 714 cputime_t delta, other;
715 715
716 delta = jiffies_to_cputime(now - tsk->vtime_snap); 716 delta = jiffies_to_cputime(now - tsk->vtime_snap);
717 steal = steal_account_process_time(delta); 717 other = account_other_time(delta);
718 WARN_ON_ONCE(tsk->vtime_snap_whence == VTIME_INACTIVE); 718 WARN_ON_ONCE(tsk->vtime_snap_whence == VTIME_INACTIVE);
719 tsk->vtime_snap = now; 719 tsk->vtime_snap = now;
720 720
721 return delta - steal; 721 return delta - other;
722} 722}
723 723
724static void __vtime_account_system(struct task_struct *tsk) 724static void __vtime_account_system(struct task_struct *tsk)
@@ -738,16 +738,6 @@ void vtime_account_system(struct task_struct *tsk)
738 write_seqcount_end(&tsk->vtime_seqcount); 738 write_seqcount_end(&tsk->vtime_seqcount);
739} 739}
740 740
741void vtime_gen_account_irq_exit(struct task_struct *tsk)
742{
743 write_seqcount_begin(&tsk->vtime_seqcount);
744 if (vtime_delta(tsk))
745 __vtime_account_system(tsk);
746 if (context_tracking_in_user())
747 tsk->vtime_snap_whence = VTIME_USER;
748 write_seqcount_end(&tsk->vtime_seqcount);
749}
750
751void vtime_account_user(struct task_struct *tsk) 741void vtime_account_user(struct task_struct *tsk)
752{ 742{
753 cputime_t delta_cpu; 743 cputime_t delta_cpu;