diff options
| author | Ingo Molnar <mingo@kernel.org> | 2013-02-05 07:10:33 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-02-05 07:10:33 -0500 |
| commit | b2c77a57e4a0a7877e357dead7ee8acc19944f3e (patch) | |
| tree | fa192b5a058711299c2a8ce2621df6c9bd8f3a99 /include/linux | |
| parent | c3c186403c6abd32e719f005f0af950155a9e54d (diff) | |
| parent | 6a61671bb2f3a1bd12cd17b8fca811a624782632 (diff) | |
Merge tag 'full-dynticks-cputime-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into sched/core
Pull full-dynticks (user-space execution is undisturbed and
receives no timer IRQs) preparation changes that convert the
cputime accounting code to be full-dynticks ready,
from Frederic Weisbecker:
"This implements the cputime accounting on full dynticks CPUs.
Typical cputime stats infrastructure relies on the timer tick and
its periodic polling on the CPU to account the amount of time
spent by the CPUs and the tasks per high level domains such as
userspace, kernelspace, guest, ...
Now we are preparing to implement full dynticks capability on
Linux for Real Time and HPC users who want full CPU isolation.
This feature requires a cputime accounting that doesn't depend
on the timer tick.
To implement it, this new cputime infrastructure plugs into
kernel/user/guest boundaries to take snapshots of cputime and
flush these to the stats when needed. This performs pretty
much like CONFIG_VIRT_CPU_ACCOUNTING except that context location
and cputime snaphots are synchronized between write and read
side such that the latter can safely retrieve the pending tickless
cputime of a task and add it to its latest cputime snapshot to
return the correct result to the user."
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/context_tracking.h | 28 | ||||
| -rw-r--r-- | include/linux/hardirq.h | 4 | ||||
| -rw-r--r-- | include/linux/init_task.h | 11 | ||||
| -rw-r--r-- | include/linux/kernel_stat.h | 2 | ||||
| -rw-r--r-- | include/linux/kvm_host.h | 55 | ||||
| -rw-r--r-- | include/linux/sched.h | 40 | ||||
| -rw-r--r-- | include/linux/tsacct_kern.h | 3 | ||||
| -rw-r--r-- | include/linux/vtime.h | 59 |
8 files changed, 171 insertions, 31 deletions
diff --git a/include/linux/context_tracking.h b/include/linux/context_tracking.h index e24339ccb7f0..b28d161c1091 100644 --- a/include/linux/context_tracking.h +++ b/include/linux/context_tracking.h | |||
| @@ -3,12 +3,40 @@ | |||
| 3 | 3 | ||
| 4 | #ifdef CONFIG_CONTEXT_TRACKING | 4 | #ifdef CONFIG_CONTEXT_TRACKING |
| 5 | #include <linux/sched.h> | 5 | #include <linux/sched.h> |
| 6 | #include <linux/percpu.h> | ||
| 7 | |||
| 8 | struct context_tracking { | ||
| 9 | /* | ||
| 10 | * When active is false, probes are unset in order | ||
| 11 | * to minimize overhead: TIF flags are cleared | ||
| 12 | * and calls to user_enter/exit are ignored. This | ||
| 13 | * may be further optimized using static keys. | ||
| 14 | */ | ||
| 15 | bool active; | ||
| 16 | enum { | ||
| 17 | IN_KERNEL = 0, | ||
| 18 | IN_USER, | ||
| 19 | } state; | ||
| 20 | }; | ||
| 21 | |||
| 22 | DECLARE_PER_CPU(struct context_tracking, context_tracking); | ||
| 23 | |||
| 24 | static inline bool context_tracking_in_user(void) | ||
| 25 | { | ||
| 26 | return __this_cpu_read(context_tracking.state) == IN_USER; | ||
| 27 | } | ||
| 28 | |||
| 29 | static inline bool context_tracking_active(void) | ||
| 30 | { | ||
| 31 | return __this_cpu_read(context_tracking.active); | ||
| 32 | } | ||
| 6 | 33 | ||
| 7 | extern void user_enter(void); | 34 | extern void user_enter(void); |
| 8 | extern void user_exit(void); | 35 | extern void user_exit(void); |
| 9 | extern void context_tracking_task_switch(struct task_struct *prev, | 36 | extern void context_tracking_task_switch(struct task_struct *prev, |
| 10 | struct task_struct *next); | 37 | struct task_struct *next); |
| 11 | #else | 38 | #else |
| 39 | static inline bool context_tracking_in_user(void) { return false; } | ||
| 12 | static inline void user_enter(void) { } | 40 | static inline void user_enter(void) { } |
| 13 | static inline void user_exit(void) { } | 41 | static inline void user_exit(void) { } |
| 14 | static inline void context_tracking_task_switch(struct task_struct *prev, | 42 | static inline void context_tracking_task_switch(struct task_struct *prev, |
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 624ef3f45c8e..7105d5cbb762 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
| @@ -153,7 +153,7 @@ extern void rcu_nmi_exit(void); | |||
| 153 | */ | 153 | */ |
| 154 | #define __irq_enter() \ | 154 | #define __irq_enter() \ |
| 155 | do { \ | 155 | do { \ |
| 156 | vtime_account_irq_enter(current); \ | 156 | account_irq_enter_time(current); \ |
| 157 | add_preempt_count(HARDIRQ_OFFSET); \ | 157 | add_preempt_count(HARDIRQ_OFFSET); \ |
| 158 | trace_hardirq_enter(); \ | 158 | trace_hardirq_enter(); \ |
| 159 | } while (0) | 159 | } while (0) |
| @@ -169,7 +169,7 @@ extern void irq_enter(void); | |||
| 169 | #define __irq_exit() \ | 169 | #define __irq_exit() \ |
| 170 | do { \ | 170 | do { \ |
| 171 | trace_hardirq_exit(); \ | 171 | trace_hardirq_exit(); \ |
| 172 | vtime_account_irq_exit(current); \ | 172 | account_irq_exit_time(current); \ |
| 173 | sub_preempt_count(HARDIRQ_OFFSET); \ | 173 | sub_preempt_count(HARDIRQ_OFFSET); \ |
| 174 | } while (0) | 174 | } while (0) |
| 175 | 175 | ||
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 6d087c5f57f7..cc898b871cef 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/pid_namespace.h> | 10 | #include <linux/pid_namespace.h> |
| 11 | #include <linux/user_namespace.h> | 11 | #include <linux/user_namespace.h> |
| 12 | #include <linux/securebits.h> | 12 | #include <linux/securebits.h> |
| 13 | #include <linux/seqlock.h> | ||
| 13 | #include <net/net_namespace.h> | 14 | #include <net/net_namespace.h> |
| 14 | 15 | ||
| 15 | #ifdef CONFIG_SMP | 16 | #ifdef CONFIG_SMP |
| @@ -141,6 +142,15 @@ extern struct task_group root_task_group; | |||
| 141 | # define INIT_PERF_EVENTS(tsk) | 142 | # define INIT_PERF_EVENTS(tsk) |
| 142 | #endif | 143 | #endif |
| 143 | 144 | ||
| 145 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN | ||
| 146 | # define INIT_VTIME(tsk) \ | ||
| 147 | .vtime_seqlock = __SEQLOCK_UNLOCKED(tsk.vtime_seqlock), \ | ||
| 148 | .vtime_snap = 0, \ | ||
| 149 | .vtime_snap_whence = VTIME_SYS, | ||
| 150 | #else | ||
| 151 | # define INIT_VTIME(tsk) | ||
| 152 | #endif | ||
| 153 | |||
| 144 | #define INIT_TASK_COMM "swapper" | 154 | #define INIT_TASK_COMM "swapper" |
| 145 | 155 | ||
| 146 | /* | 156 | /* |
| @@ -210,6 +220,7 @@ extern struct task_group root_task_group; | |||
| 210 | INIT_TRACE_RECURSION \ | 220 | INIT_TRACE_RECURSION \ |
| 211 | INIT_TASK_RCU_PREEMPT(tsk) \ | 221 | INIT_TASK_RCU_PREEMPT(tsk) \ |
| 212 | INIT_CPUSET_SEQ \ | 222 | INIT_CPUSET_SEQ \ |
| 223 | INIT_VTIME(tsk) \ | ||
| 213 | } | 224 | } |
| 214 | 225 | ||
| 215 | 226 | ||
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 66b70780e910..ed5f6ed6eb77 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h | |||
| @@ -127,7 +127,7 @@ 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 | 130 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
| 131 | static inline void account_process_tick(struct task_struct *tsk, int user) | 131 | static inline void account_process_tick(struct task_struct *tsk, int user) |
| 132 | { | 132 | { |
| 133 | vtime_account_user(tsk); | 133 | vtime_account_user(tsk); |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 2c497ab0d03d..b7996a768eb2 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/rcupdate.h> | 22 | #include <linux/rcupdate.h> |
| 23 | #include <linux/ratelimit.h> | 23 | #include <linux/ratelimit.h> |
| 24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
| 25 | #include <linux/irqflags.h> | ||
| 25 | #include <asm/signal.h> | 26 | #include <asm/signal.h> |
| 26 | 27 | ||
| 27 | #include <linux/kvm.h> | 28 | #include <linux/kvm.h> |
| @@ -740,15 +741,52 @@ static inline int kvm_deassign_device(struct kvm *kvm, | |||
| 740 | } | 741 | } |
| 741 | #endif /* CONFIG_IOMMU_API */ | 742 | #endif /* CONFIG_IOMMU_API */ |
| 742 | 743 | ||
| 743 | static inline void kvm_guest_enter(void) | 744 | static inline void __guest_enter(void) |
| 744 | { | 745 | { |
| 745 | BUG_ON(preemptible()); | ||
| 746 | /* | 746 | /* |
| 747 | * This is running in ioctl context so we can avoid | 747 | * This is running in ioctl context so we can avoid |
| 748 | * the call to vtime_account() with its unnecessary idle check. | 748 | * the call to vtime_account() with its unnecessary idle check. |
| 749 | */ | 749 | */ |
| 750 | vtime_account_system_irqsafe(current); | 750 | vtime_account_system(current); |
| 751 | current->flags |= PF_VCPU; | 751 | current->flags |= PF_VCPU; |
| 752 | } | ||
| 753 | |||
| 754 | static inline void __guest_exit(void) | ||
| 755 | { | ||
| 756 | /* | ||
| 757 | * This is running in ioctl context so we can avoid | ||
| 758 | * the call to vtime_account() with its unnecessary idle check. | ||
| 759 | */ | ||
| 760 | vtime_account_system(current); | ||
| 761 | current->flags &= ~PF_VCPU; | ||
| 762 | } | ||
| 763 | |||
| 764 | #ifdef CONFIG_CONTEXT_TRACKING | ||
| 765 | extern void guest_enter(void); | ||
| 766 | extern void guest_exit(void); | ||
| 767 | |||
