Skip to content

Commit f904f58

Browse files
Sebastian Andrzej SiewiorIngo Molnar
authored andcommitted
sched/debug: Fix preempt_disable_ip recording for preempt_disable()
The preempt_disable() invokes preempt_count_add() which saves the caller in ->preempt_disable_ip. It uses CALLER_ADDR1 which does not look for its caller but for the parent of the caller. Which means we get the correct caller for something like spin_lock() unless the architectures inlines those invocations. It is always wrong for preempt_disable() or local_bh_disable(). This patch makes the function get_lock_parent_ip() which tries CALLER_ADDR0,1,2 if the former is a locking function. This seems to record the preempt_disable() caller properly for preempt_disable() itself as well as for get_cpu_var() or local_bh_disable(). Steven asked for the get_parent_ip() -> get_lock_parent_ip() rename. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20160226135456.GB18244@linutronix.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent ff9a9b4 commit f904f58

File tree

4 files changed

+16
-16
lines changed

4 files changed

+16
-16
lines changed

include/linux/ftrace.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,18 @@ static inline void __ftrace_enabled_restore(int enabled)
713713
#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
714714
#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
715715

716+
static inline unsigned long get_lock_parent_ip(void)
717+
{
718+
unsigned long addr = CALLER_ADDR0;
719+
720+
if (!in_lock_functions(addr))
721+
return addr;
722+
addr = CALLER_ADDR1;
723+
if (!in_lock_functions(addr))
724+
return addr;
725+
return CALLER_ADDR2;
726+
}
727+
716728
#ifdef CONFIG_IRQSOFF_TRACER
717729
extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
718730
extern void time_hardirqs_off(unsigned long a0, unsigned long a1);

include/linux/sched.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,6 @@ extern void update_cpu_load_nohz(int active);
182182
static inline void update_cpu_load_nohz(int active) { }
183183
#endif
184184

185-
extern unsigned long get_parent_ip(unsigned long addr);
186-
187185
extern void dump_cpu_task(int cpu);
188186

189187
struct seq_file;

kernel/sched/core.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2946,16 +2946,6 @@ u64 scheduler_tick_max_deferment(void)
29462946
}
29472947
#endif
29482948

2949-
notrace unsigned long get_parent_ip(unsigned long addr)
2950-
{
2951-
if (in_lock_functions(addr)) {
2952-
addr = CALLER_ADDR2;
2953-
if (in_lock_functions(addr))
2954-
addr = CALLER_ADDR3;
2955-
}
2956-
return addr;
2957-
}
2958-
29592949
#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
29602950
defined(CONFIG_PREEMPT_TRACER))
29612951

@@ -2977,7 +2967,7 @@ void preempt_count_add(int val)
29772967
PREEMPT_MASK - 10);
29782968
#endif
29792969
if (preempt_count() == val) {
2980-
unsigned long ip = get_parent_ip(CALLER_ADDR1);
2970+
unsigned long ip = get_lock_parent_ip();
29812971
#ifdef CONFIG_DEBUG_PREEMPT
29822972
current->preempt_disable_ip = ip;
29832973
#endif
@@ -3004,7 +2994,7 @@ void preempt_count_sub(int val)
30042994
#endif
30052995

30062996
if (preempt_count() == val)
3007-
trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
2997+
trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
30082998
__preempt_count_sub(val);
30092999
}
30103000
EXPORT_SYMBOL(preempt_count_sub);

kernel/softirq.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)
116116

117117
if (preempt_count() == cnt) {
118118
#ifdef CONFIG_DEBUG_PREEMPT
119-
current->preempt_disable_ip = get_parent_ip(CALLER_ADDR1);
119+
current->preempt_disable_ip = get_lock_parent_ip();
120120
#endif
121-
trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
121+
trace_preempt_off(CALLER_ADDR0, get_lock_parent_ip());
122122
}
123123
}
124124
EXPORT_SYMBOL(__local_bh_disable_ip);

0 commit comments

Comments
 (0)