78 lines
2.5 KiB
Diff
78 lines
2.5 KiB
Diff
From 8f47b1871b8aac98f1a9d93bc3467fb97b65199a Mon Sep 17 00:00:00 2001
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
Date: Fri, 7 Feb 2014 20:58:39 +0100
|
|
Subject: [PATCH 3/6] sched: Add better debug output for might_sleep()
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/3.14/patches-3.14.10-rt7.tar.xz
|
|
|
|
might_sleep() can tell us where interrupts have been disabled, but we
|
|
have no idea what disabled preemption. Add some debug infrastructure.
|
|
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
|
|
Link: http://lkml.kernel.org/r/1391803122-4425-4-git-send-email-bigeasy@linutronix.de
|
|
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
|
---
|
|
include/linux/sched.h | 3 +++
|
|
kernel/sched/core.c | 23 +++++++++++++++++++++--
|
|
2 files changed, 24 insertions(+), 2 deletions(-)
|
|
|
|
--- a/include/linux/sched.h
|
|
+++ b/include/linux/sched.h
|
|
@@ -1460,6 +1460,9 @@ struct task_struct {
|
|
struct mutex perf_event_mutex;
|
|
struct list_head perf_event_list;
|
|
#endif
|
|
+#ifdef CONFIG_DEBUG_PREEMPT
|
|
+ unsigned long preempt_disable_ip;
|
|
+#endif
|
|
#ifdef CONFIG_NUMA
|
|
struct mempolicy *mempolicy; /* Protected by alloc_lock */
|
|
short il_next;
|
|
--- a/kernel/sched/core.c
|
|
+++ b/kernel/sched/core.c
|
|
@@ -2508,8 +2508,13 @@ void __kprobes preempt_count_add(int val
|
|
DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >=
|
|
PREEMPT_MASK - 10);
|
|
#endif
|
|
- if (preempt_count() == val)
|
|
- trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
|
|
+ if (preempt_count() == val) {
|
|
+ unsigned long ip = get_parent_ip(CALLER_ADDR1);
|
|
+#ifdef CONFIG_DEBUG_PREEMPT
|
|
+ current->preempt_disable_ip = ip;
|
|
+#endif
|
|
+ trace_preempt_off(CALLER_ADDR0, ip);
|
|
+ }
|
|
}
|
|
EXPORT_SYMBOL(preempt_count_add);
|
|
|
|
@@ -2552,6 +2557,13 @@ static noinline void __schedule_bug(stru
|
|
print_modules();
|
|
if (irqs_disabled())
|
|
print_irqtrace_events(prev);
|
|
+#ifdef CONFIG_DEBUG_PREEMPT
|
|
+ if (in_atomic_preempt_off()) {
|
|
+ pr_err("Preemption disabled at:");
|
|
+ print_ip_sym(current->preempt_disable_ip);
|
|
+ pr_cont("\n");
|
|
+ }
|
|
+#endif
|
|
dump_stack();
|
|
add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
|
|
}
|
|
@@ -6965,6 +6977,13 @@ void __might_sleep(const char *file, int
|
|
debug_show_held_locks(current);
|
|
if (irqs_disabled())
|
|
print_irqtrace_events(current);
|
|
+#ifdef CONFIG_DEBUG_PREEMPT
|
|
+ if (!preempt_count_equals(preempt_offset)) {
|
|
+ pr_err("Preemption disabled at:");
|
|
+ print_ip_sym(current->preempt_disable_ip);
|
|
+ pr_cont("\n");
|
|
+ }
|
|
+#endif
|
|
dump_stack();
|
|
}
|
|
EXPORT_SYMBOL(__might_sleep);
|