aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/context_tracking.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2015-05-06 12:04:24 -0400
committerIngo Molnar <mingo@kernel.org>2015-05-07 06:02:51 -0400
commitfafe870f31212a72f3c2d74e7b90e4ef39e83ee1 (patch)
treec1b1ef375b480b26a827c3c6eb12eb2de7ed164a /kernel/context_tracking.c
parentaed5ed47724f6a7453fa62e3c90f3cee93edbfe3 (diff)
context_tracking: Inherit TIF_NOHZ through forks instead of context switches
TIF_NOHZ is used by context_tracking to force syscall slow-path on every task in order to track userspace roundtrips. As such, it must be set on all running tasks. It's currently explicitly inherited through context switches. There is no need to do it in this fast-path though. The flag could simply be set once for all on all tasks, whether they are running or not. Lets do this by setting the flag for the init task on early boot, and let it propagate through fork inheritance. While at it, mark context_tracking_cpu_set() as init code, we only need it at early boot time. Suggested-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Reviewed-by: Rik van Riel <riel@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Chris Metcalf <cmetcalf@ezchip.com> Cc: Dave Jones <davej@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Mike Galbraith <umgwanakikbuti@gmail.com> Cc: Paul E . McKenney <paulmck@linux.vnet.ibm.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rafael J . Wysocki <rafael.j.wysocki@intel.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1430928266-24888-3-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/context_tracking.c')
-rw-r--r--kernel/context_tracking.c44
1 files changed, 19 insertions, 25 deletions
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
index 5b11a10e196a..0a495ab35bc7 100644
--- a/kernel/context_tracking.c
+++ b/kernel/context_tracking.c
@@ -30,14 +30,6 @@ EXPORT_SYMBOL_GPL(context_tracking_enabled);
30DEFINE_PER_CPU(struct context_tracking, context_tracking); 30DEFINE_PER_CPU(struct context_tracking, context_tracking);
31EXPORT_SYMBOL_GPL(context_tracking); 31EXPORT_SYMBOL_GPL(context_tracking);
32 32
33void context_tracking_cpu_set(int cpu)
34{
35 if (!per_cpu(context_tracking.active, cpu)) {
36 per_cpu(context_tracking.active, cpu) = true;
37 static_key_slow_inc(&context_tracking_enabled);
38 }
39}
40
41static bool context_tracking_recursion_enter(void) 33static bool context_tracking_recursion_enter(void)
42{ 34{
43 int recursion; 35 int recursion;
@@ -193,24 +185,26 @@ void context_tracking_user_exit(void)
193} 185}
194NOKPROBE_SYMBOL(context_tracking_user_exit); 186NOKPROBE_SYMBOL(context_tracking_user_exit);
195 187
196/** 188void __init context_tracking_cpu_set(int cpu)
197 * __context_tracking_task_switch - context switch the syscall callbacks
198 * @prev: the task that is being switched out
199 * @next: the task that is being switched in
200 *
201 * The context tracking uses the syscall slow path to implement its user-kernel
202 * boundaries probes on syscalls. This way it doesn't impact the syscall fast
203 * path on CPUs that don't do context tracking.
204 *
205 * But we need to clear the flag on the previous task because it may later
206 * migrate to some CPU that doesn't do the context tracking. As such the TIF
207 * flag may not be desired there.
208 */
209void __context_tracking_task_switch(struct task_struct *prev,
210 struct task_struct *next)
211{ 189{
212 clear_tsk_thread_flag(prev, TIF_NOHZ); 190 static __initdata bool initialized = false;
213 set_tsk_thread_flag(next, TIF_NOHZ); 191
192 if (!per_cpu(context_tracking.active, cpu)) {
193 per_cpu(context_tracking.active, cpu) = true;
194 static_key_slow_inc(&context_tracking_enabled);
195 }
196
197 if (initialized)
198 return;
199
200 /*
201 * Set TIF_NOHZ to init/0 and let it propagate to all tasks through fork
202 * This assumes that init is the only task at this early boot stage.
203 */
204 set_tsk_thread_flag(&init_task, TIF_NOHZ);
205 WARN_ON_ONCE(!tasklist_empty());
206
207 initialized = true;
214} 208}
215 209
216#ifdef CONFIG_CONTEXT_TRACKING_FORCE 210#ifdef CONFIG_CONTEXT_TRACKING_FORCE