diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-20 14:18:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-20 14:18:35 -0400 |
commit | a3d5c3460a86f52ea435b3fb98be112bd18faabc (patch) | |
tree | 48a32968b569af0e0f0af1def3effa0770710fea /kernel/context_tracking.c | |
parent | 86c76676cfdbf283f6131d5a2783bed3f3d490ea (diff) | |
parent | 29bb9e5a75684106a37593ad75ec75ff8312731b (diff) |
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler fixes from Ingo Molnar:
"Two smaller fixes - plus a context tracking tracing fix that is a bit
bigger"
* 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
tracing/context-tracking: Add preempt_schedule_context() for tracing
sched: Fix clear NOHZ_BALANCE_KICK
sched/x86: Construct all sibling maps if smt
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 85bdde1137eb..383f8231e436 100644 --- a/kernel/context_tracking.c +++ b/kernel/context_tracking.c | |||
@@ -70,6 +70,46 @@ void user_enter(void) | |||
70 | local_irq_restore(flags); | 70 | local_irq_restore(flags); |
71 | } | 71 | } |
72 | 72 | ||
73 | #ifdef CONFIG_PREEMPT | ||
74 | /** | ||
75 | * preempt_schedule_context - preempt_schedule called by tracing | ||
76 | * | ||
77 | * The tracing infrastructure uses preempt_enable_notrace to prevent | ||
78 | * recursion and tracing preempt enabling caused by the tracing | ||
79 | * infrastructure itself. But as tracing can happen in areas coming | ||
80 | * from userspace or just about to enter userspace, a preempt enable | ||
81 | * can occur before user_exit() is called. This will cause the scheduler | ||
82 | * to be called when the system is still in usermode. | ||
83 | * | ||
84 | * To prevent this, the preempt_enable_notrace will use this function | ||
85 | * instead of preempt_schedule() to exit user context if needed before | ||
86 | * calling the scheduler. | ||
87 | */ | ||
88 | void __sched notrace preempt_schedule_context(void) | ||
89 | { | ||
90 | struct thread_info *ti = current_thread_info(); | ||
91 | enum ctx_state prev_ctx; | ||
92 | |||
93 | if (likely(ti->preempt_count || irqs_disabled())) | ||
94 | return; | ||
95 | |||
96 | /* | ||
97 | * Need to disable preemption in case user_exit() is traced | ||
98 | * and the tracer calls preempt_enable_notrace() causing | ||
99 | * an infinite recursion. | ||
100 | */ | ||
101 | preempt_disable_notrace(); | ||
102 | prev_ctx = exception_enter(); | ||
103 | preempt_enable_no_resched_notrace(); | ||
104 | |||
105 | preempt_schedule(); | ||
106 | |||
107 | preempt_disable_notrace(); | ||
108 | exception_exit(prev_ctx); | ||
109 | preempt_enable_notrace(); | ||
110 | } | ||
111 | EXPORT_SYMBOL_GPL(preempt_schedule_context); | ||
112 | #endif /* CONFIG_PREEMPT */ | ||
73 | 113 | ||
74 | /** | 114 | /** |
75 | * user_exit - Inform the context tracking that the CPU is | 115 | * user_exit - Inform the context tracking that the CPU is |