diff options
author | Ingo Molnar <mingo@kernel.org> | 2013-06-19 12:55:31 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-06-19 12:55:31 +0200 |
commit | d81344c50824a4d28a9397e97135d60075ac37ff (patch) | |
tree | d25c443fb4a764cd788db857c49dd3d3f8f722d3 /kernel/context_tracking.c | |
parent | 0de358f1c2642710d41190b73fbc295e675c4ab8 (diff) | |
parent | 29bb9e5a75684106a37593ad75ec75ff8312731b (diff) | |
download | blackbird-op-linux-d81344c50824a4d28a9397e97135d60075ac37ff.tar.gz blackbird-op-linux-d81344c50824a4d28a9397e97135d60075ac37ff.zip |
Merge branch 'sched/urgent' into sched/core
Merge in fixes before applying ongoing new work.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/context_tracking.c')
-rw-r--r-- | kernel/context_tracking.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c index 65349f07b878..66677003e223 100644 --- a/kernel/context_tracking.c +++ b/kernel/context_tracking.c @@ -71,6 +71,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 |