diff options
Diffstat (limited to 'kernel/sched.c')
| -rw-r--r-- | kernel/sched.c | 24 | 
1 files changed, 23 insertions, 1 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 73e60085236..328494e28df 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -70,6 +70,7 @@  #include <linux/bootmem.h>  #include <linux/debugfs.h>  #include <linux/ctype.h> +#include <linux/ftrace.h>  #include <asm/tlb.h>  #include <asm/irq_regs.h> @@ -4365,26 +4366,44 @@ void scheduler_tick(void)  #endif  } -#if defined(CONFIG_PREEMPT) && defined(CONFIG_DEBUG_PREEMPT) +#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ +				defined(CONFIG_PREEMPT_TRACER)) + +static inline unsigned long get_parent_ip(unsigned long addr) +{ +	if (in_lock_functions(addr)) { +		addr = CALLER_ADDR2; +		if (in_lock_functions(addr)) +			addr = CALLER_ADDR3; +	} +	return addr; +}  void __kprobes add_preempt_count(int val)  { +#ifdef CONFIG_DEBUG_PREEMPT  	/*  	 * Underflow?  	 */  	if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0)))  		return; +#endif  	preempt_count() += val; +#ifdef CONFIG_DEBUG_PREEMPT  	/*  	 * Spinlock count overflowing soon?  	 */  	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));  }  EXPORT_SYMBOL(add_preempt_count);  void __kprobes sub_preempt_count(int val)  { +#ifdef CONFIG_DEBUG_PREEMPT  	/*  	 * Underflow?  	 */ @@ -4396,7 +4415,10 @@ void __kprobes sub_preempt_count(int val)  	if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) &&  			!(preempt_count() & PREEMPT_MASK)))  		return; +#endif +	if (preempt_count() == val) +		trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));  	preempt_count() -= val;  }  EXPORT_SYMBOL(sub_preempt_count);  |