diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2012-07-25 01:56:04 -0400 |
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2013-01-27 13:23:27 -0500 |
| commit | abf917cd91cbb73952758f9741e2fa65002a48ee (patch) | |
| tree | 5f975b87615dcaed9c98bc74b4548d568b92dcbc | |
| parent | ae8dda5c473bf1a85913942adcaac449e5754bf3 (diff) | |
cputime: Generic on-demand virtual cputime accounting
If we want to stop the tick further idle, we need to be
able to account the cputime without using the tick.
Virtual based cputime accounting solves that problem by
hooking into kernel/user boundaries.
However implementing CONFIG_VIRT_CPU_ACCOUNTING require
low level hooks and involves more overhead. But we already
have a generic context tracking subsystem that is required
for RCU needs by archs which plan to shut down the tick
outside idle.
This patch implements a generic virtual based cputime
accounting that relies on these generic kernel/user hooks.
There are some upsides of doing this:
- This requires no arch code to implement CONFIG_VIRT_CPU_ACCOUNTING
if context tracking is already built (already necessary for RCU in full
tickless mode).
- We can rely on the generic context tracking subsystem to dynamically
(de)activate the hooks, so that we can switch anytime between virtual
and tick based accounting. This way we don't have the overhead
of the virtual accounting when the tick is running periodically.
And one downside:
- There is probably more overhead than a native virtual based cputime
accounting. But this relies on hooks that are already set anyway.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Li Zhong <zhong@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
27 files changed, 160 insertions, 54 deletions
diff --git a/arch/ia64/include/asm/cputime.h b/arch/ia64/include/asm/cputime.h index 040b31638001..e2d3f5baf265 100644 --- a/arch/ia64/include/asm/cputime.h +++ b/arch/ia64/include/asm/cputime.h | |||
| @@ -11,19 +11,19 @@ | |||
| 11 | * as published by the Free Software Foundation; either version | 11 | * as published by the Free Software Foundation; either version |
| 12 | * 2 of the License, or (at your option) any later version. | 12 | * 2 of the License, or (at your option) any later version. |
| 13 | * | 13 | * |
| 14 | * If we have CONFIG_VIRT_CPU_ACCOUNTING, we measure cpu time in nsec. | 14 | * If we have CONFIG_VIRT_CPU_ACCOUNTING_NATIVE, we measure cpu time in nsec. |
| 15 | * Otherwise we measure cpu time in jiffies using the generic definitions. | 15 | * Otherwise we measure cpu time in jiffies using the generic definitions. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #ifndef __IA64_CPUTIME_H | 18 | #ifndef __IA64_CPUTIME_H |
| 19 | #define __IA64_CPUTIME_H | 19 | #define __IA64_CPUTIME_H |
| 20 | 20 | ||
| 21 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | 21 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 22 | # include <asm-generic/cputime.h> | 22 | # include <asm-generic/cputime.h> |
| 23 | #else | 23 | #else |
| 24 | # include <asm/processor.h> | 24 | # include <asm/processor.h> |
| 25 | # include <asm-generic/cputime_nsecs.h> | 25 | # include <asm-generic/cputime_nsecs.h> |
| 26 | extern void arch_vtime_task_switch(struct task_struct *tsk); | 26 | extern void arch_vtime_task_switch(struct task_struct *tsk); |
| 27 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | 27 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ |
| 28 | 28 | ||
| 29 | #endif /* __IA64_CPUTIME_H */ | 29 | #endif /* __IA64_CPUTIME_H */ |
diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h index ff2ae4136584..020d655ed082 100644 --- a/arch/ia64/include/asm/thread_info.h +++ b/arch/ia64/include/asm/thread_info.h | |||
| @@ -31,7 +31,7 @@ struct thread_info { | |||
| 31 | mm_segment_t addr_limit; /* user-level address space limit */ | 31 | mm_segment_t addr_limit; /* user-level address space limit */ |
| 32 | int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ | 32 | int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ |
| 33 | struct restart_block restart_block; | 33 | struct restart_block restart_block; |
| 34 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 34 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 35 | __u64 ac_stamp; | 35 | __u64 ac_stamp; |
| 36 | __u64 ac_leave; | 36 | __u64 ac_leave; |
| 37 | __u64 ac_stime; | 37 | __u64 ac_stime; |
| @@ -69,7 +69,7 @@ struct thread_info { | |||
| 69 | #define task_stack_page(tsk) ((void *)(tsk)) | 69 | #define task_stack_page(tsk) ((void *)(tsk)) |
| 70 | 70 | ||
| 71 | #define __HAVE_THREAD_FUNCTIONS | 71 | #define __HAVE_THREAD_FUNCTIONS |
| 72 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 72 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 73 | #define setup_thread_stack(p, org) \ | 73 | #define setup_thread_stack(p, org) \ |
| 74 | *task_thread_info(p) = *task_thread_info(org); \ | 74 | *task_thread_info(p) = *task_thread_info(org); \ |
| 75 | task_thread_info(p)->ac_stime = 0; \ | 75 | task_thread_info(p)->ac_stime = 0; \ |
diff --git a/arch/ia64/include/asm/xen/minstate.h b/arch/ia64/include/asm/xen/minstate.h index c57fa910f2c9..00cf03e0cb82 100644 --- a/arch/ia64/include/asm/xen/minstate.h +++ b/arch/ia64/include/asm/xen/minstate.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | ||
| 2 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 2 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 3 | /* read ar.itc in advance, and use it before leaving bank 0 */ | 3 | /* read ar.itc in advance, and use it before leaving bank 0 */ |
| 4 | #define XEN_ACCOUNT_GET_STAMP \ | 4 | #define XEN_ACCOUNT_GET_STAMP \ |
| 5 | MOV_FROM_ITC(pUStk, p6, r20, r2); | 5 | MOV_FROM_ITC(pUStk, p6, r20, r2); |
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index a48bd9a9927b..46c9e3007315 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c | |||
| @@ -41,7 +41,7 @@ void foo(void) | |||
| 41 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | 41 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); |
| 42 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); | 42 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); |
| 43 | DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); | 43 | DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); |
| 44 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 44 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 45 | DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp)); | 45 | DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp)); |
| 46 | DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave)); | 46 | DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave)); |
| 47 | DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime)); | 47 | DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime)); |
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 6bfd8429ee0f..7a53530f22c2 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
| @@ -724,7 +724,7 @@ GLOBAL_ENTRY(__paravirt_leave_syscall) | |||
| 724 | #endif | 724 | #endif |
| 725 | .global __paravirt_work_processed_syscall; | 725 | .global __paravirt_work_processed_syscall; |
| 726 | __paravirt_work_processed_syscall: | 726 | __paravirt_work_processed_syscall: |
| 727 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 727 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 728 | adds r2=PT(LOADRS)+16,r12 | 728 | adds r2=PT(LOADRS)+16,r12 |
| 729 | MOV_FROM_ITC(pUStk, p9, r22, r19) // fetch time at leave | 729 | MOV_FROM_ITC(pUStk, p9, r22, r19) // fetch time at leave |
| 730 | adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 | 730 | adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 |
| @@ -762,7 +762,7 @@ __paravirt_work_processed_syscall: | |||
| 762 | 762 | ||
| 763 | ld8 r29=[r2],16 // M0|1 load cr.ipsr | 763 | ld8 r29=[r2],16 // M0|1 load cr.ipsr |
| 764 | ld8 r28=[r3],16 // M0|1 load cr.iip | 764 | ld8 r28=[r3],16 // M0|1 load cr.iip |
| 765 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 765 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 766 | (pUStk) add r14=TI_AC_LEAVE+IA64_TASK_SIZE,r13 | 766 | (pUStk) add r14=TI_AC_LEAVE+IA64_TASK_SIZE,r13 |
| 767 | ;; | 767 | ;; |
| 768 | ld8 r30=[r2],16 // M0|1 load cr.ifs | 768 | ld8 r30=[r2],16 // M0|1 load cr.ifs |
| @@ -793,7 +793,7 @@ __paravirt_work_processed_syscall: | |||
| 793 | ld8.fill r1=[r3],16 // M0|1 load r1 | 793 | ld8.fill r1=[r3],16 // M0|1 load r1 |
| 794 | (pUStk) mov r17=1 // A | 794 | (pUStk) mov r17=1 // A |
| 795 | ;; | 795 | ;; |
| 796 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 796 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 797 | (pUStk) st1 [r15]=r17 // M2|3 | 797 | (pUStk) st1 [r15]=r17 // M2|3 |
| 798 | #else | 798 | #else |
| 799 | (pUStk) st1 [r14]=r17 // M2|3 | 799 | (pUStk) st1 [r14]=r17 // M2|3 |
| @@ -813,7 +813,7 @@ __paravirt_work_processed_syscall: | |||
| 813 | shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition | 813 | shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition |
| 814 | COVER // B add current frame into dirty partition & set cr.ifs | 814 | COVER // B add current frame into dirty partition & set cr.ifs |
| 815 | ;; | 815 | ;; |
| 816 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 816 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 817 | mov r19=ar.bsp // M2 get new backing store pointer | 817 | mov r19=ar.bsp // M2 get new backing store pointer |
| 818 | st8 [r14]=r22 // M save time at leave | 818 | st8 [r14]=r22 // M save time at leave |
| 819 | mov f10=f0 // F clear f10 | 819 | mov f10=f0 // F clear f10 |
| @@ -948,7 +948,7 @@ GLOBAL_ENTRY(__paravirt_leave_kernel) | |||
| 948 | adds r16=PT(CR_IPSR)+16,r12 | 948 | adds r16=PT(CR_IPSR)+16,r12 |
| 949 | adds r17=PT(CR_IIP)+16,r12 | 949 | adds r17=PT(CR_IIP)+16,r12 |
| 950 | 950 | ||
| 951 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 951 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 952 | .pred.rel.mutex pUStk,pKStk | 952 | .pred.rel.mutex pUStk,pKStk |
| 953 | MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled | 953 | MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled |
| 954 | MOV_FROM_ITC(pUStk, p9, r22, r29) // M fetch time at leave | 954 | MOV_FROM_ITC(pUStk, p9, r22, r29) // M fetch time at leave |
| @@ -981,7 +981,7 @@ GLOBAL_ENTRY(__paravirt_leave_kernel) | |||
| 981 | ;; | 981 | ;; |
