diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-07-01 10:27:25 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-07-01 10:27:25 +0200 |
commit | bc32134c0523c60989d2f2439e176601668a62a5 (patch) | |
tree | 03f63fc387e78592968a1f04ee4e173ca32fec20 /kernel/context_tracking.c | |
parent | 1c6770a38a6652777b9d1592b66e0d8e7dfb6160 (diff) | |
parent | 066624c6a1733a72a67f1d06d35a2153e7d9082b (diff) |
Merge branch 'for-next' into for-linus
Merge the whole changes for 3.11-rc1 merge
Diffstat (limited to 'kernel/context_tracking.c')
-rw-r--r-- | kernel/context_tracking.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c index 65349f07b87..383f8231e43 100644 --- a/kernel/context_tracking.c +++ b/kernel/context_tracking.c @@ -15,7 +15,6 @@ */ #include <linux/context_tracking.h> -#include <linux/kvm_host.h> #include <linux/rcupdate.h> #include <linux/sched.h> #include <linux/hardirq.h> @@ -71,6 +70,46 @@ void user_enter(void) local_irq_restore(flags); } +#ifdef CONFIG_PREEMPT +/** + * preempt_schedule_context - preempt_schedule called by tracing + * + * The tracing infrastructure uses preempt_enable_notrace to prevent + * recursion and tracing preempt enabling caused by the tracing + * infrastructure itself. But as tracing can happen in areas coming + * from userspace or just about to enter userspace, a preempt enable + * can occur before user_exit() is called. This will cause the scheduler + * to be called when the system is still in usermode. + * + * To prevent this, the preempt_enable_notrace will use this function + * instead of preempt_schedule() to exit user context if needed before + * calling the scheduler. + */ +void __sched notrace preempt_schedule_context(void) +{ + struct thread_info *ti = current_thread_info(); + enum ctx_state prev_ctx; + + if (likely(ti->preempt_count || irqs_disabled())) + return; + + /* + * Need to disable preemption in case user_exit() is traced + * and the tracer calls preempt_enable_notrace() causing + * an infinite recursion. + */ + preempt_disable_notrace(); + prev_ctx = exception_enter(); + preempt_enable_no_resched_notrace(); + + preempt_schedule(); + + preempt_disable_notrace(); + exception_exit(prev_ctx); + preempt_enable_notrace(); +} +EXPORT_SYMBOL_GPL(preempt_schedule_context); +#endif /* CONFIG_PREEMPT */ /** * user_exit - Inform the context tracking that the CPU is |