diff options
-rw-r--r-- | arch/ia64/include/asm/cputime.h | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/time.c | 26 | ||||
-rw-r--r-- | arch/powerpc/include/asm/cputime.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 24 | ||||
-rw-r--r-- | arch/s390/include/asm/cputime.h | 1 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 13 | ||||
-rw-r--r-- | include/linux/kernel_stat.h | 8 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 4 | ||||
-rw-r--r-- | include/linux/vtime.h | 9 | ||||
-rw-r--r-- | kernel/sched/cputime.c | 31 |
10 files changed, 65 insertions, 55 deletions
diff --git a/arch/ia64/include/asm/cputime.h b/arch/ia64/include/asm/cputime.h index 3deac956d325..7fcf7f08ab06 100644 --- a/arch/ia64/include/asm/cputime.h +++ b/arch/ia64/include/asm/cputime.h | |||
@@ -103,5 +103,7 @@ static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val) | |||
103 | #define cputime64_to_clock_t(__ct) \ | 103 | #define cputime64_to_clock_t(__ct) \ |
104 | cputime_to_clock_t((__force cputime_t)__ct) | 104 | cputime_to_clock_t((__force cputime_t)__ct) |
105 | 105 | ||
106 | extern void arch_vtime_task_switch(struct task_struct *tsk); | ||
107 | |||
106 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | 108 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ |
107 | #endif /* __IA64_CPUTIME_H */ | 109 | #endif /* __IA64_CPUTIME_H */ |
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 5e4850305d3f..b1995efbfd21 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
@@ -83,7 +83,7 @@ static struct clocksource *itc_clocksource; | |||
83 | 83 | ||
84 | extern cputime_t cycle_to_cputime(u64 cyc); | 84 | extern cputime_t cycle_to_cputime(u64 cyc); |
85 | 85 | ||
86 | static void vtime_account_user(struct task_struct *tsk) | 86 | void vtime_account_user(struct task_struct *tsk) |
87 | { | 87 | { |
88 | cputime_t delta_utime; | 88 | cputime_t delta_utime; |
89 | struct thread_info *ti = task_thread_info(tsk); | 89 | struct thread_info *ti = task_thread_info(tsk); |
@@ -100,18 +100,11 @@ static void vtime_account_user(struct task_struct *tsk) | |||
100 | * accumulated times to the current process, and to prepare accounting on | 100 | * accumulated times to the current process, and to prepare accounting on |
101 | * the next process. | 101 | * the next process. |
102 | */ | 102 | */ |
103 | void vtime_task_switch(struct task_struct *prev) | 103 | void arch_vtime_task_switch(struct task_struct *prev) |
104 | { | 104 | { |
105 | struct thread_info *pi = task_thread_info(prev); | 105 | struct thread_info *pi = task_thread_info(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) | ||
109 | __vtime_account_system(prev); | ||
110 | else | ||
111 | __vtime_account_idle(prev); | ||
112 | |||
113 | vtime_account_user(prev); | ||
114 | |||
115 | pi->ac_stamp = ni->ac_stamp; | 108 | pi->ac_stamp = ni->ac_stamp; |
116 | ni->ac_stime = ni->ac_utime = 0; | 109 | ni->ac_stime = ni->ac_utime = 0; |
117 | } | 110 | } |
@@ -126,6 +119,8 @@ static cputime_t vtime_delta(struct task_struct *tsk) | |||
126 | cputime_t delta_stime; | 119 | cputime_t delta_stime; |
127 | __u64 now; | 120 | __u64 now; |
128 | 121 | ||
122 | WARN_ON_ONCE(!irqs_disabled()); | ||
123 | |||
129 | now = ia64_get_itc(); | 124 | now = ia64_get_itc(); |
130 | 125 | ||
131 | delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); | 126 | delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); |
@@ -135,27 +130,18 @@ static cputime_t vtime_delta(struct task_struct *tsk) | |||
135 | return delta_stime; | 130 | return delta_stime; |
136 | } | 131 | } |
137 | 132 | ||
138 | void __vtime_account_system(struct task_struct *tsk) | 133 | void vtime_account_system(struct task_struct *tsk) |
139 | { | 134 | { |
140 | cputime_t delta = vtime_delta(tsk); | 135 | cputime_t delta = vtime_delta(tsk); |
141 | 136 | ||
142 | account_system_time(tsk, 0, delta, delta); | 137 | account_system_time(tsk, 0, delta, delta); |
143 | } | 138 | } |
144 | 139 | ||
145 | void __vtime_account_idle(struct task_struct *tsk) | 140 | void vtime_account_idle(struct task_struct *tsk) |
146 | { | 141 | { |
147 | account_idle_time(vtime_delta(tsk)); | 142 | account_idle_time(vtime_delta(tsk)); |
148 | } | 143 | } |
149 | 144 | ||
150 | /* | ||
151 | * Called from the timer interrupt handler to charge accumulated user time | ||
152 | * to the current process. Must be called with interrupts disabled. | ||
153 | */ | ||
154 | void account_process_tick(struct task_struct *p, int user_tick) | ||
155 | { | ||
156 | vtime_account_user(p); | ||
157 | } | ||
158 | |||
159 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | 145 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ |
160 | 146 | ||
161 | static irqreturn_t | 147 | static irqreturn_t |
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h index 487d46ff68a1..483733bd06d4 100644 --- a/arch/powerpc/include/asm/cputime.h +++ b/arch/powerpc/include/asm/cputime.h | |||
@@ -228,6 +228,8 @@ static inline cputime_t clock_t_to_cputime(const unsigned long clk) | |||
228 | 228 | ||
229 | #define cputime64_to_clock_t(ct) cputime_to_clock_t((cputime_t)(ct)) | 229 | #define cputime64_to_clock_t(ct) cputime_to_clock_t((cputime_t)(ct)) |
230 | 230 | ||
231 | static inline void arch_vtime_task_switch(struct task_struct *tsk) { } | ||
232 | |||
231 | #endif /* __KERNEL__ */ | 233 | #endif /* __KERNEL__ */ |
232 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | 234 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ |
233 | #endif /* __POWERPC_CPUTIME_H */ | 235 | #endif /* __POWERPC_CPUTIME_H */ |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 0db456f30d45..b3b14352b05e 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -297,6 +297,8 @@ static u64 vtime_delta(struct task_struct *tsk, | |||
297 | u64 now, nowscaled, deltascaled; | 297 | u64 now, nowscaled, deltascaled; |
298 | u64 udelta, delta, user_scaled; | 298 | u64 udelta, delta, user_scaled; |
299 | 299 | ||
300 | WARN_ON_ONCE(!irqs_disabled()); | ||
301 | |||
300 | now = mftb(); | 302 | now = mftb(); |
301 | nowscaled = read_spurr(now); | 303 | nowscaled = read_spurr(now); |
302 | get_paca()->system_time += now - get_paca()->starttime; | 304 | get_paca()->system_time += now - get_paca()->starttime; |
@@ -336,7 +338,7 @@ static u64 vtime_delta(struct task_struct *tsk, | |||
336 | return delta; | 338 | return delta; |
337 | } | 339 | } |
338 | 340 | ||
339 | void __vtime_account_system(struct task_struct *tsk) | 341 | void vtime_account_system(struct task_struct *tsk) |
340 | { | 342 | { |
341 | u64 delta, sys_scaled, stolen; | 343 | u64 delta, sys_scaled, stolen; |
342 | 344 | ||
@@ -346,7 +348,7 @@ void __vtime_account_system(struct task_struct *tsk) | |||
346 | account_steal_time(stolen); | 348 | account_steal_time(stolen); |
347 | } | 349 | } |
348 | 350 | ||
349 | void __vtime_account_idle(struct task_struct *tsk) | 351 | void vtime_account_idle(struct task_struct *tsk) |
350 | { | 352 | { |
351 | u64 delta, sys_scaled, stolen; | 353 | u64 delta, sys_scaled, stolen; |
352 | 354 | ||
@@ -355,15 +357,15 @@ void __vtime_account_idle(struct task_struct *tsk) | |||
355 | } | 357 | } |
356 | 358 | ||
357 | /* | 359 | /* |
358 | * Transfer the user and system times accumulated in the paca | 360 | * Transfer the user time accumulated in the paca |
359 | * by the exception entry and exit code to the generic process | 361 | * by the exception entry and exit code to the generic |
360 | * user and system time records. | 362 | * process user time records. |
361 | * Must be called with interrupts disabled. | 363 | * Must be called with interrupts disabled. |
362 | * Assumes that vtime_account() has been called recently | 364 | * Assumes that vtime_account_system/idle() has been called |
363 | * (i.e. since the last entry from usermode) so that | 365 | * recently (i.e. since the last entry from usermode) so that |
364 | * get_paca()->user_time_scaled is up to date. | 366 | * get_paca()->user_time_scaled is up to date. |
365 | */ | 367 | */ |
366 | void account_process_tick(struct task_struct *tsk, int user_tick) | 368 | void vtime_account_user(struct task_struct *tsk) |
367 | { | 369 | { |
368 | cputime_t utime, utimescaled; | 370 | cputime_t utime, utimescaled; |
369 | 371 | ||
@@ -375,12 +377,6 @@ void account_process_tick(struct task_struct *tsk, int user_tick) | |||
375 | account_user_time(tsk, utime, utimescaled); | 377 | account_user_time(tsk, utime, utimescaled); |
376 | } | 378 | } |
377 | 379 | ||
378 | void vtime_task_switch(struct task_struct *prev) | ||
379 | { | ||
380 | vtime_account(prev); | ||
381 | account_process_tick(prev, 0); | ||
382 | } | ||
383 | |||
384 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ | 380 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ |
385 | #define calc_cputime_factors() | 381 | #define calc_cputime_factors() |
386 | #endif | 382 | #endif |
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index 023d5ae24482..d2ff41370c0c 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | 15 | ||
16 | #define __ARCH_HAS_VTIME_ACCOUNT | 16 | #define __ARCH_HAS_VTIME_ACCOUNT |
17 | #define __ARCH_HAS_VTIME_TASK_SWITCH | ||
17 | 18 | ||
18 | /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ | 19 | /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ |
19 | 20 | ||
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 783e988c4e1e..e84b8b68444a 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -112,7 +112,12 @@ void vtime_task_switch(struct task_struct *prev) | |||
112 | S390_lowcore.system_timer = ti->system_timer; | 112 | S390_lowcore.system_timer = ti->system_timer; |
113 | } | 113 | } |
114 | 114 | ||
115 | void account_process_tick(struct task_struct *tsk, int user_tick) | 115 | /* |
116 | * In s390, accounting pending user time also implies | ||
117 | * accounting system time in order to correctly compute | ||
118 | * the stolen time accounting. | ||
119 | */ | ||
120 | void vtime_account_user(struct task_struct *tsk) | ||
116 | { | 121 | { |
117 | if (do_account_vtime(tsk, HARDIRQ_OFFSET)) | 122 | if (do_account_vtime(tsk, HARDIRQ_OFFSET)) |
118 | virt_timer_expire(); | 123 | virt_timer_expire(); |
@@ -127,6 +132,8 @@ void vtime_account(struct task_struct *tsk) | |||
127 | struct thread_info *ti = task_thread_info(tsk); | 132 | struct thread_info *ti = task_thread_info(tsk); |
128 | u64 timer, system; | 133 | u64 timer, system; |
129 | 134 | ||
135 | WARN_ON_ONCE(!irqs_disabled()); | ||
136 | |||
130 | timer = S390_lowcore.last_update_timer; | 137 | timer = S390_lowcore.last_update_timer; |
131 | S390_lowcore.last_update_timer = get_vtimer(); | 138 | S390_lowcore.last_update_timer = get_vtimer(); |
132 | S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; | 139 | S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; |
@@ -140,9 +147,9 @@ void vtime_account(struct task_struct *tsk) | |||
140 | } | 147 | } |
141 | EXPORT_SYMBOL_GPL(vtime_account); | 148 | EXPORT_SYMBOL_GPL(vtime_account); |
142 | 149 | ||
143 | void __vtime_account_system(struct task_struct *tsk) | 150 | void vtime_account_system(struct task_struct *tsk) |
144 | __attribute__((alias("vtime_account"))); | 151 | __attribute__((alias("vtime_account"))); |
145 | EXPORT_SYMBOL_GPL(__vtime_account_system); | 152 | EXPORT_SYMBOL_GPL(vtime_account_system); |
146 | 153 | ||
147 | void __kprobes vtime_stop_cpu(void) | 154 | void __kprobes vtime_stop_cpu(void) |
148 | { | 155 | { |
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 1865b1f29770..66b70780e910 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h | |||
@@ -127,7 +127,15 @@ extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t) | |||
127 | extern void account_steal_time(cputime_t); | 127 | extern void account_steal_time(cputime_t); |
128 | extern void account_idle_time(cputime_t); | 128 | extern void account_idle_time(cputime_t); |
129 | 129 | ||
130 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
131 | static inline void account_process_tick(struct task_struct *tsk, int user) | ||
132 | { | ||
133 | vtime_account_user(tsk); | ||
134 | } | ||
135 | #else | ||
130 | extern void account_process_tick(struct task_struct *, int user); | 136 | extern void account_process_tick(struct task_struct *, int user); |
137 | #endif | ||
138 | |||
131 | extern void account_steal_ticks(unsigned long ticks); | 139 | extern void account_steal_ticks(unsigned long ticks); |
132 | extern void account_idle_ticks(unsigned long ticks); | 140 | extern void account_idle_ticks(unsigned long ticks); |
133 | 141 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 3738c260dde7..d5cddd8dcc5c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -730,7 +730,7 @@ static inline void kvm_guest_enter(void) | |||
730 | * This is running in ioctl context so we can avoid | 730 | * This is running in ioctl context so we can avoid |
731 | * the call to vtime_account() with its unnecessary idle check. | 731 | * the call to vtime_account() with its unnecessary idle check. |
732 | */ | 732 | */ |
733 | vtime_account_system(current); | 733 | vtime_account_system_irqsafe(current); |
734 | current->flags |= PF_VCPU; | 734 | current->flags |= PF_VCPU; |
735 | /* KVM does not hold any references to rcu protected data when it | 735 | /* KVM does not hold any references to rcu protected data when it |
736 | * switches CPU into a guest mode. In fact switching to a guest mode | 736 | * switches CPU into a guest mode. In fact switching to a guest mode |
@@ -748,7 +748,7 @@ static inline void kvm_guest_exit(void) | |||
748 | * This is running in ioctl context so we can avoid | 748 | * This is running in ioctl context so we can avoid |
749 | * the call to vtime_account() with its unnecessary idle check. | 749 | * the call to vtime_account() with its unnecessary idle check. |
750 | */ | 750 | */ |
751 | vtime_account_system(current); | 751 | vtime_account_system_irqsafe(current); |
752 | current->flags &= ~PF_VCPU; | 752 | current->flags &= ~PF_VCPU; |
753 | } | 753 | } |
754 | 754 | ||
diff --git a/include/linux/vtime.h b/include/linux/vtime.h index 0c2a2d303020..ae30ab58431a 100644 --- a/include/linux/vtime.h +++ b/include/linux/vtime.h | |||
@@ -5,14 +5,15 @@ struct task_struct; | |||
5 | 5 | ||
6 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 6 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
7 | extern void vtime_task_switch(struct task_struct *prev); | 7 | extern void vtime_task_switch(struct task_struct *prev); |
8 | extern void __vtime_account_system(struct task_struct *tsk); | ||
9 | extern void vtime_account_system(struct task_struct *tsk); | 8 | extern void vtime_account_system(struct task_struct *tsk); |
10 | extern void __vtime_account_idle(struct task_struct *tsk); | 9 | extern void vtime_account_system_irqsafe(struct task_struct *tsk); |
10 | extern void vtime_account_idle(struct task_struct *tsk); | ||
11 | extern void vtime_account_user(struct task_struct *tsk); | ||
11 | extern void vtime_account(struct task_struct *tsk); | 12 | extern void vtime_account(struct task_struct *tsk); |
12 | #else | 13 | #else |
13 | static inline void vtime_task_switch(struct task_struct *prev) { } | 14 | static inline void vtime_task_switch(struct task_struct *prev) { } |
14 | static inline void __vtime_account_system(struct task_struct *tsk) { } | ||
15 | static inline void vtime_account_system(struct task_struct *tsk) { } | 15 | static inline void vtime_account_system(struct task_struct *tsk) { } |
16 | static inline void vtime_account_system_irqsafe(struct task_struct *tsk) { } | ||
16 | static inline void vtime_account(struct task_struct *tsk) { } | 17 | static inline void vtime_account(struct task_struct *tsk) { } |
17 | #endif | 18 | #endif |
18 | 19 | ||
@@ -40,7 +41,7 @@ static inline void vtime_account_irq_enter(struct task_struct *tsk) | |||
40 | static inline void vtime_account_irq_exit(struct task_struct *tsk) | 41 | static inline void vtime_account_irq_exit(struct task_struct *tsk) |
41 | { | 42 | { |
42 | /* On hard|softirq exit we always account to hard|softirq cputime */ | 43 | /* On hard|softirq exit we always account to hard|softirq cputime */ |
43 | __vtime_account_system(tsk); | 44 | vtime_account_system(tsk); |
44 | irqtime_account_irq(tsk); | 45 | irqtime_account_irq(tsk); |
45 | } | 46 | } |
46 | 47 | ||
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index b7f731768625..293b202fcf79 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c | |||
@@ -461,20 +461,33 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime | |||
461 | *st = cputime.stime; | 461 | *st = cputime.stime; |
462 | } | 462 | } |
463 | 463 | ||
464 | void vtime_account_system(struct task_struct *tsk) | 464 | void vtime_account_system_irqsafe(struct task_struct *tsk) |
465 | { | 465 | { |
466 | unsigned long flags; | 466 | unsigned long flags; |
467 | 467 | ||
468 | local_irq_save(flags); | 468 | local_irq_save(flags); |
469 | __vtime_account_system(tsk); | 469 | vtime_account_system(tsk); |
470 | local_irq_restore(flags); | 470 | local_irq_restore(flags); |
471 | } | 471 | } |
472 | EXPORT_SYMBOL_GPL(vtime_account_system); | 472 | EXPORT_SYMBOL_GPL(vtime_account_system_irqsafe); |
473 | |||
474 | #ifndef __ARCH_HAS_VTIME_TASK_SWITCH | ||
475 | void vtime_task_switch(struct task_struct *prev) | ||
476 | { | ||
477 | if (is_idle_task(prev)) | ||
478 | vtime_account_idle(prev); | ||
479 | else | ||
480 | vtime_account_system(prev); | ||
481 | |||
482 | vtime_account_user(prev); | ||
483 | arch_vtime_task_switch(prev); | ||
484 | } | ||
485 | #endif | ||
473 | 486 | ||
474 | /* | 487 | /* |
475 | * Archs that account the whole time spent in the idle task | 488 | * Archs that account the whole time spent in the idle task |
476 | * (outside irq) as idle time can rely on this and just implement | 489 | * (outside irq) as idle time can rely on this and just implement |
477 | * __vtime_account_system() and __vtime_account_idle(). Archs that | 490 | * vtime_account_system() and vtime_account_idle(). Archs that |
478 | * have other meaning of the idle time (s390 only includes the | 491 | * have other meaning of the idle time (s390 only includes the |
479 | * time spent by the CPU when it's in low power mode) must override | 492 | * time spent by the CPU when it's in low power mode) must override |
480 | * vtime_account(). | 493 | * vtime_account(). |
@@ -482,16 +495,10 @@ EXPORT_SYMBOL_GPL(vtime_account_system); | |||
482 | #ifndef __ARCH_HAS_VTIME_ACCOUNT | 495 | #ifndef __ARCH_HAS_VTIME_ACCOUNT |
483 | void vtime_account(struct task_struct *tsk) | 496 | void vtime_account(struct task_struct *tsk) |
484 | { | 497 | { |
485 | unsigned long flags; | ||
486 | |||
487 | local_irq_save(flags); | ||
488 | |||
489 | if (in_interrupt() || !is_idle_task(tsk)) | 498 | if (in_interrupt() || !is_idle_task(tsk)) |
490 | __vtime_account_system(tsk); | 499 | vtime_account_system(tsk); |
491 | else | 500 | else |
492 | __vtime_account_idle(tsk); | 501 | vtime_account_idle(tsk); |
493 | |||
494 | local_irq_restore(flags); | ||
495 | } | 502 | } |
496 | EXPORT_SYMBOL_GPL(vtime_account); | 503 | EXPORT_SYMBOL_GPL(vtime_account); |
497 | #endif /* __ARCH_HAS_VTIME_ACCOUNT */ | 504 | #endif /* __ARCH_HAS_VTIME_ACCOUNT */ |