mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 23:39:18 +00:00
2e70933866
The context tracking subsystem has the ability to selectively enable the tracking on any defined subset of CPU. This means that we can define a CPU range that doesn't run the context tracking and another range that does. Now what we want in practice is to enable the tracking on full dynticks CPUs only. In order to perform this, we just need to pass our full dynticks CPU range selection from the full dynticks subsystem to the context tracking. This way we can spare the overhead of RCU user extended quiescent state and vtime maintainance on the CPUs that are outside the full dynticks range. Just keep in mind the raw context tracking itself is still necessary everywhere. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Li Zhong <zhong@linux.vnet.ibm.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Kevin Hilman <khilman@linaro.org>
94 lines
2.2 KiB
C
94 lines
2.2 KiB
C
#ifndef _LINUX_CONTEXT_TRACKING_H
|
|
#define _LINUX_CONTEXT_TRACKING_H
|
|
|
|
#include <linux/sched.h>
|
|
#include <linux/percpu.h>
|
|
#include <linux/vtime.h>
|
|
#include <asm/ptrace.h>
|
|
|
|
struct context_tracking {
|
|
/*
|
|
* When active is false, probes are unset in order
|
|
* to minimize overhead: TIF flags are cleared
|
|
* and calls to user_enter/exit are ignored. This
|
|
* may be further optimized using static keys.
|
|
*/
|
|
bool active;
|
|
enum ctx_state {
|
|
IN_KERNEL = 0,
|
|
IN_USER,
|
|
} state;
|
|
};
|
|
|
|
|
|
#ifdef CONFIG_CONTEXT_TRACKING
|
|
DECLARE_PER_CPU(struct context_tracking, context_tracking);
|
|
|
|
static inline bool context_tracking_in_user(void)
|
|
{
|
|
return __this_cpu_read(context_tracking.state) == IN_USER;
|
|
}
|
|
|
|
static inline bool context_tracking_active(void)
|
|
{
|
|
return __this_cpu_read(context_tracking.active);
|
|
}
|
|
|
|
extern void context_tracking_cpu_set(int cpu);
|
|
|
|
extern void user_enter(void);
|
|
extern void user_exit(void);
|
|
|
|
static inline enum ctx_state exception_enter(void)
|
|
{
|
|
enum ctx_state prev_ctx;
|
|
|
|
prev_ctx = this_cpu_read(context_tracking.state);
|
|
user_exit();
|
|
|
|
return prev_ctx;
|
|
}
|
|
|
|
static inline void exception_exit(enum ctx_state prev_ctx)
|
|
{
|
|
if (prev_ctx == IN_USER)
|
|
user_enter();
|
|
}
|
|
|
|
extern void context_tracking_task_switch(struct task_struct *prev,
|
|
struct task_struct *next);
|
|
#else
|
|
static inline bool context_tracking_in_user(void) { return false; }
|
|
static inline void user_enter(void) { }
|
|
static inline void user_exit(void) { }
|
|
static inline enum ctx_state exception_enter(void) { return 0; }
|
|
static inline void exception_exit(enum ctx_state prev_ctx) { }
|
|
static inline void context_tracking_task_switch(struct task_struct *prev,
|
|
struct task_struct *next) { }
|
|
#endif /* !CONFIG_CONTEXT_TRACKING */
|
|
|
|
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
|
|
extern void guest_enter(void);
|
|
extern void guest_exit(void);
|
|
#else
|
|
static inline void guest_enter(void)
|
|
{
|
|
/*
|
|
* This is running in ioctl context so its safe
|
|
* to assume that it's the stime pending cputime
|
|
* to flush.
|
|
*/
|
|
vtime_account_system(current);
|
|
current->flags |= PF_VCPU;
|
|
}
|
|
|
|
static inline void guest_exit(void)
|
|
{
|
|
/* Flush the guest cputime we spent on the guest */
|
|
vtime_account_system(current);
|
|
current->flags &= ~PF_VCPU;
|
|
}
|
|
#endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */
|
|
|
|
#endif
|