Commit d1f74e20 authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt

tracing/sched: Make preempt_schedule() notrace

The function tracer code uses ftrace_preempt_disable() to disable
preemption instead of normal preempt_disable(). But there's a slight
race condition that may cause it to lose a preemption check.

This was made to keep the function tracer from recursing on itself
by disabling preemption then having the enable call the function tracer
again, causing infinite recursion.

The bug was assumed to happen if the call was just in schedule, but
this is incorrect. The bug is caused by preempt_schedule() which
is called by preempt_enable(). The calling of preempt_enable() when
NEED_RESCHED was set would call preempt_schedule() which would call
the function tracer again.

By making the preempt_schedule() and add_preempt_count() notrace
then this will prevent the inifinite recursion. This is because
the add_preempt_count() would stop the preempt_enable() in the
function tracer from calling preempt_schedule() again.

The sub_preempt_count() is also made notrace just to keep it
symmetric.
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 9dda696f
...@@ -3730,7 +3730,7 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner) ...@@ -3730,7 +3730,7 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
* off of preempt_enable. Kernel preemptions off return from interrupt * off of preempt_enable. Kernel preemptions off return from interrupt
* occur there and call schedule directly. * occur there and call schedule directly.
*/ */
asmlinkage void __sched preempt_schedule(void) asmlinkage void __sched notrace preempt_schedule(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
...@@ -3742,9 +3742,9 @@ asmlinkage void __sched preempt_schedule(void) ...@@ -3742,9 +3742,9 @@ asmlinkage void __sched preempt_schedule(void)
return; return;
do { do {
add_preempt_count(PREEMPT_ACTIVE); add_preempt_count_notrace(PREEMPT_ACTIVE);
schedule(); schedule();
sub_preempt_count(PREEMPT_ACTIVE); sub_preempt_count_notrace(PREEMPT_ACTIVE);
/* /*
* Check again in case we missed a preemption opportunity * Check again in case we missed a preemption opportunity
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment