aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-10-30 03:33:01 -0400
committerIngo Molnar <mingo@kernel.org>2012-10-30 03:33:01 -0400
commit38ca9c927c7d3db61f57e3d3a9334958c3af6e9a (patch)
tree58be18cf3dce7a407c84ab2532e92bdb8b7ee067
parente9c84cb8d5f1b1ea6fcbe6190d51dc84b6975938 (diff)
parent3e1df4f506836e6bea1ab61cf88c75c8b1840643 (diff)
Merge tag 'cputime-cleanups-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into sched/core
Pull cputime cleanups and optimizations from Frederic Weisbecker: * Gather vtime headers that were a bit scattered around * Separate irqtime and vtime namespaces that were colliding, resulting in useless calls to irqtime accounting. * Slightly optimize irq and guest vtime accounting. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/ia64/kernel/time.c8
-rw-r--r--arch/powerpc/kernel/time.c4
-rw-r--r--arch/s390/kernel/vtime.c4
-rw-r--r--arch/s390/kvm/kvm-s390.c4
-rw-r--r--include/linux/hardirq.h15
-rw-r--r--include/linux/kernel_stat.h9
-rw-r--r--include/linux/kvm_host.h12
-rw-r--r--include/linux/vtime.h47
-rw-r--r--kernel/sched/cputime.c20
-rw-r--r--kernel/softirq.c6
10 files changed, 89 insertions, 40 deletions
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index f6388216080d..5e4850305d3f 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -106,9 +106,9 @@ void vtime_task_switch(struct task_struct *prev)
106 struct thread_info *ni = task_thread_info(current); 106 struct thread_info *ni = task_thread_info(current);
107 107
108 if (idle_task(smp_processor_id()) != prev) 108 if (idle_task(smp_processor_id()) != prev)
109 vtime_account_system(prev); 109 __vtime_account_system(prev);
110 else 110 else
111 vtime_account_idle(prev); 111 __vtime_account_idle(prev);
112 112
113 vtime_account_user(prev); 113 vtime_account_user(prev);
114 114
@@ -135,14 +135,14 @@ static cputime_t vtime_delta(struct task_struct *tsk)
135 return delta_stime; 135 return delta_stime;
136} 136}
137 137
138void vtime_account_system(struct task_struct *tsk) 138void __vtime_account_system(struct task_struct *tsk)
139{ 139{
140 cputime_t delta = vtime_delta(tsk); 140 cputime_t delta = vtime_delta(tsk);
141 141
142 account_system_time(tsk, 0, delta, delta); 142 account_system_time(tsk, 0, delta, delta);
143} 143}
144 144
145void vtime_account_idle(struct task_struct *tsk) 145void __vtime_account_idle(struct task_struct *tsk)
146{ 146{
147 account_idle_time(vtime_delta(tsk)); 147 account_idle_time(vtime_delta(tsk));
148} 148}
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index ce4cb772dc78..0db456f30d45 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -336,7 +336,7 @@ static u64 vtime_delta(struct task_struct *tsk,
336 return delta; 336 return delta;
337} 337}
338 338
339void vtime_account_system(struct task_struct *tsk) 339void __vtime_account_system(struct task_struct *tsk)
340{ 340{
341 u64 delta, sys_scaled, stolen; 341 u64 delta, sys_scaled, stolen;
342 342
@@ -346,7 +346,7 @@ void vtime_account_system(struct task_struct *tsk)
346 account_steal_time(stolen); 346 account_steal_time(stolen);
347} 347}
348 348
349void vtime_account_idle(struct task_struct *tsk) 349void __vtime_account_idle(struct task_struct *tsk)
350{ 350{
351 u64 delta, sys_scaled, stolen; 351 u64 delta, sys_scaled, stolen;
352 352
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 790334427895..783e988c4e1e 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -140,6 +140,10 @@ void vtime_account(struct task_struct *tsk)
140} 140}
141EXPORT_SYMBOL_GPL(vtime_account); 141EXPORT_SYMBOL_GPL(vtime_account);
142 142
143void __vtime_account_system(struct task_struct *tsk)
144__attribute__((alias("vtime_account")));
145EXPORT_SYMBOL_GPL(__vtime_account_system);
146
143void __kprobes vtime_stop_cpu(void) 147void __kprobes vtime_stop_cpu(void)
144{ 148{
145 struct s390_idle_data *idle = &__get_cpu_var(s390_idle); 149 struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index ecced9d18986..d91a95568002 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -608,9 +608,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
608 kvm_s390_deliver_pending_interrupts(vcpu); 608 kvm_s390_deliver_pending_interrupts(vcpu);
609 609
610 vcpu->arch.sie_block->icptcode = 0; 610 vcpu->arch.sie_block->icptcode = 0;
611 local_irq_disable();
612 kvm_guest_enter(); 611 kvm_guest_enter();
613 local_irq_enable();
614 VCPU_EVENT(vcpu, 6, "entering sie flags %x", 612 VCPU_EVENT(vcpu, 6, "entering sie flags %x",
615 atomic_read(&vcpu->arch.sie_block->cpuflags)); 613 atomic_read(&vcpu->arch.sie_block->cpuflags));
616 trace_kvm_s390_sie_enter(vcpu, 614 trace_kvm_s390_sie_enter(vcpu,
@@ -629,9 +627,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
629 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", 627 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
630 vcpu->arch.sie_block->icptcode); 628 vcpu->arch.sie_block->icptcode);
631 trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode); 629 trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode);
632 local_irq_disable();
633 kvm_guest_exit(); 630 kvm_guest_exit();
634 local_irq_enable();
635 631
636 memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16); 632 memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
637 return rc; 633 return rc;
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index cab3da3d0949..624ef3f45c8e 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -4,6 +4,7 @@
4#include <linux/preempt.h> 4#include <linux/preempt.h>
5#include <linux/lockdep.h> 5#include <linux/lockdep.h>
6#include <linux/ftrace_irq.h> 6#include <linux/ftrace_irq.h>
7#include <linux/vtime.h>
7#include <asm/hardirq.h> 8#include <asm/hardirq.h>
8 9
9/* 10/*
@@ -129,16 +130,6 @@ extern void synchronize_irq(unsigned int irq);
129# define synchronize_irq(irq) barrier() 130# define synchronize_irq(irq) barrier()
130#endif 131#endif
131 132
132struct task_struct;
133
134#if !defined(CONFIG_VIRT_CPU_ACCOUNTING) && !defined(CONFIG_IRQ_TIME_ACCOUNTING)
135static inline void vtime_account(struct task_struct *tsk)
136{
137}
138#else
139extern void vtime_account(struct task_struct *tsk);
140#endif
141
142#if defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU) 133#if defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU)
143 134
144static inline void rcu_nmi_enter(void) 135static inline void rcu_nmi_enter(void)
@@ -162,7 +153,7 @@ extern void rcu_nmi_exit(void);
162 */ 153 */
163#define __irq_enter() \ 154#define __irq_enter() \
164 do { \ 155 do { \
165 vtime_account(current); \ 156 vtime_account_irq_enter(current); \
166 add_preempt_count(HARDIRQ_OFFSET); \ 157 add_preempt_count(HARDIRQ_OFFSET); \
167 trace_hardirq_enter(); \ 158 trace_hardirq_enter(); \
168 } while (0) 159 } while (0)
@@ -178,7 +169,7 @@ extern void irq_enter(void);
178#define __irq_exit() \ 169#define __irq_exit() \
179 do { \ 170 do { \
180 trace_hardirq_exit(); \ 171 trace_hardirq_exit(); \
181 vtime_account(current); \ 172 vtime_account_irq_exit(current); \
182 sub_preempt_count(HARDIRQ_OFFSET); \ 173 sub_preempt_count(HARDIRQ_OFFSET); \
183 } while (0) 174 } while (0)
184 175
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 36d12f0884c3..1865b1f29770 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -7,6 +7,7 @@
7#include <linux/cpumask.h> 7#include <linux/cpumask.h>
8#include <linux/interrupt.h> 8#include <linux/interrupt.h>
9#include <linux/sched.h> 9#include <linux/sched.h>
10#include <linux/vtime.h>
10#include <asm/irq.h> 11#include <asm/irq.h>
11#include <asm/cputime.h> 12#include <asm/cputime.h>
12 13
@@ -130,12 +131,4 @@ extern void account_process_tick(struct task_struct *, int user);
130extern void account_steal_ticks(unsigned long ticks); 131extern void account_steal_ticks(unsigned long ticks);
131extern void account_idle_ticks(unsigned long ticks); 132extern void account_idle_ticks(unsigned long ticks);
132 133
133#ifdef CONFIG_VIRT_CPU_ACCOUNTING
134extern void vtime_task_switch(struct task_struct *prev);
135extern void vtime_account_system(struct task_struct *tsk);
136extern void vtime_account_idle(struct task_struct *tsk);
137#else
138static inline void vtime_task_switch(struct task_struct *prev) { }
139#endif
140
141#endif /* _LINUX_KERNEL_STAT_H */ 134#endif /* _LINUX_KERNEL_STAT_H */
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 93bfc9f9815c..0e2212fe4784 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -737,7 +737,11 @@ static inline int kvm_deassign_device(struct kvm *kvm,
737static inline void kvm_guest_enter(void) 737static inline void kvm_guest_enter(void)
738{ 738{
739 BUG_ON(preemptible()); 739 BUG_ON(preemptible());
740 vtime_account(current); 740 /*
741 * This is running in ioctl context so we can avoid
742 * the call to vtime_account() with its unnecessary idle check.
743 */
744 vtime_account_system(current);
741 current->flags |= PF_VCPU; 745 current->flags |= PF_VCPU;
742 /* KVM does not hold any references to rcu protected data when it 746 /* KVM does not hold any references to rcu protected data when it
743 * switches CPU into a guest mode. In fact switching to a guest mode 747 * switches CPU into a guest mode. In fact switching to a guest mode
@@ -751,7 +755,11 @@ static inline void kvm_guest_enter(void)
751 755
752static inline void kvm_guest_exit(void) 756static inline void kvm_guest_exit(void)
753{ 757{
754 vtime_account(current); 758 /*
759 * This is running in ioctl context so we can avoid
760 * the call to vtime_account() with its unnecessary idle check.
761 */
762 vtime_account_system(current);
755 current->flags &= ~PF_VCPU; 763 current->flags &= ~PF_VCPU;
756} 764}
757 765
diff --git a/include/linux/vtime.h b/include/linux/vtime.h
new file mode 100644
index 000000000000..0c2a2d303020
--- /dev/null
+++ b/include/linux/vtime.h
@@ -0,0 +1,47 @@
1#ifndef _LINUX_KERNEL_VTIME_H
2#define _LINUX_KERNEL_VTIME_H
3
4struct task_struct;
5
6#ifdef CONFIG_VIRT_CPU_ACCOUNTING
7extern void vtime_task_switch(struct task_struct *prev);
8extern void __vtime_account_system(struct task_struct *tsk);
9extern void vtime_account_system(struct task_struct *tsk);
10extern void __vtime_account_idle(struct task_struct *tsk);
11extern void vtime_account(struct task_struct *tsk);
12#else
13static inline void vtime_task_switch(struct task_struct *prev) { }
14static inline void __vtime_account_system(struct task_struct *tsk) { }
15static inline void vtime_account_system(struct task_struct *tsk) { }
16static inline void vtime_account(struct task_struct *tsk) { }
17#endif
18
19#ifdef CONFIG_IRQ_TIME_ACCOUNTING
20extern void irqtime_account_irq(struct task_struct *tsk);
21#else
22static inline void irqtime_account_irq(struct task_struct *tsk) { }
23#endif
24
25static inline void vtime_account_irq_enter(struct task_struct *tsk)
26{
27 /*
28 * Hardirq can interrupt idle task anytime. So we need vtime_account()
29 * that performs the idle check in CONFIG_VIRT_CPU_ACCOUNTING.
30 * Softirq can also interrupt idle task directly if it calls
31 * local_bh_enable(). Such case probably don't exist but we never know.
32 * Ksoftirqd is not concerned because idle time is flushed on context
33 * switch. Softirqs in the end of hardirqs are also not a problem because
34 * the idle time is flushed on hardirq time already.
35 */
36 vtime_account(tsk);
37 irqtime_account_irq(tsk);
38}
39
40static inline void vtime_account_irq_exit(struct task_struct *tsk)
41{
42 /* On hard|softirq exit we always account to hard|softirq cputime */
43 __vtime_account_system(tsk);
44 irqtime_account_irq(tsk);
45}
46
47#endif /* _LINUX_KERNEL_VTIME_H */
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 81b763ba58a6..8d859dae5bed 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -43,7 +43,7 @@ DEFINE_PER_CPU(seqcount_t, irq_time_seq);
43 * Called before incrementing preempt_count on {soft,}irq_enter 43 * Called before incrementing preempt_count on {soft,}irq_enter
44 * and before decrementing preempt_count on {soft,}irq_exit. 44 * and before decrementing preempt_count on {soft,}irq_exit.
45 */ 45 */
46void vtime_account(struct task_struct *curr) 46void irqtime_account_irq(struct task_struct *curr)
47{ 47{
48 unsigned long flags; 48 unsigned long flags;
49 s64 delta; 49 s64 delta;
@@ -73,7 +73,7 @@ void vtime_account(struct task_struct *curr)
73 irq_time_write_end(); 73 irq_time_write_end();
74 local_irq_restore(flags); 74 local_irq_restore(flags);
75} 75}
76EXPORT_SYMBOL_GPL(vtime_account); 76EXPORT_SYMBOL_GPL(irqtime_account_irq);
77 77
78static int irqtime_account_hi_update(void) 78static int irqtime_account_hi_update(void)
79{ 79{
@@ -433,10 +433,20 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
433 *st = cputime.stime; 433 *st = cputime.stime;
434} 434}
435 435
436void vtime_account_system(struct task_struct *tsk)
437{
438 unsigned long flags;
439
440 local_irq_save(flags);
441 __vtime_account_system(tsk);
442 local_irq_restore(flags);
443}
444EXPORT_SYMBOL_GPL(vtime_account_system);
445
436/* 446/*
437 * Archs that account the whole time spent in the idle task 447 * Archs that account the whole time spent in the idle task
438 * (outside irq) as idle time can rely on this and just implement 448 * (outside irq) as idle time can rely on this and just implement
439 * vtime_account_system() and vtime_account_idle(). Archs that 449 * __vtime_account_system() and __vtime_account_idle(). Archs that
440 * have other meaning of the idle time (s390 only includes the 450 * 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 451 * time spent by the CPU when it's in low power mode) must override
442 * vtime_account(). 452 * vtime_account().
@@ -449,9 +459,9 @@ void vtime_account(struct task_struct *tsk)
449 local_irq_save(flags); 459 local_irq_save(flags);
450 460
451 if (in_interrupt() || !is_idle_task(tsk)) 461 if (in_interrupt() || !is_idle_task(tsk))
452 vtime_account_system(tsk); 462 __vtime_account_system(tsk);
453 else 463 else
454 vtime_account_idle(tsk); 464 __vtime_account_idle(tsk);
455 465
456 local_irq_restore(flags); 466 local_irq_restore(flags);
457} 467}
diff --git a/kernel/softirq.c b/kernel/softirq.c
index cc96bdc0c2c9..ed567babe789 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -221,7 +221,7 @@ asmlinkage void __do_softirq(void)
221 current->flags &= ~PF_MEMALLOC; 221 current->flags &= ~PF_MEMALLOC;
222 222
223 pending = local_softirq_pending(); 223 pending = local_softirq_pending();
224 vtime_account(current); 224 vtime_account_irq_enter(current);
225 225
226 __local_bh_disable((unsigned long)__builtin_return_address(0), 226 __local_bh_disable((unsigned long)__builtin_return_address(0),
227 SOFTIRQ_OFFSET); 227 SOFTIRQ_OFFSET);
@@ -272,7 +272,7 @@ restart:
272 272
273 lockdep_softirq_exit(); 273 lockdep_softirq_exit();
274 274
275 vtime_account(current); 275 vtime_account_irq_exit(current);
276 __local_bh_enable(SOFTIRQ_OFFSET); 276 __local_bh_enable(SOFTIRQ_OFFSET);
277 tsk_restore_flags(current, old_flags, PF_MEMALLOC); 277 tsk_restore_flags(current, old_flags, PF_MEMALLOC);
278} 278}
@@ -341,7 +341,7 @@ static inline void invoke_softirq(void)
341 */ 341 */
342void irq_exit(void) 342void irq_exit(void)
343{ 343{
344 vtime_account(current); 344 vtime_account_irq_exit(current);
345 trace_hardirq_exit(); 345 trace_hardirq_exit();
346 sub_preempt_count(IRQ_EXIT_OFFSET); 346 sub_preempt_count(IRQ_EXIT_OFFSET);
347 if (!in_interrupt() && local_softirq_pending()) 347 if (!in_interrupt() && local_softirq_pending())