diff options
Diffstat (limited to 'kernel/sched.c')
| -rw-r--r-- | kernel/sched.c | 55 | 
1 files changed, 53 insertions, 2 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 591d5e7f757..c74b0d23c75 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> @@ -645,6 +646,24 @@ static inline void update_rq_clock(struct rq *rq)  # define const_debug static const  #endif +/** + * runqueue_is_locked + * + * Returns true if the current cpu runqueue is locked. + * This interface allows printk to be called with the runqueue lock + * held and know whether or not it is OK to wake up the klogd. + */ +int runqueue_is_locked(void) +{ +	int cpu = get_cpu(); +	struct rq *rq = cpu_rq(cpu); +	int ret; + +	ret = spin_is_locked(&rq->lock); +	put_cpu(); +	return ret; +} +  /*   * Debugging: various feature bits   */ @@ -2318,6 +2337,9 @@ out_activate:  	success = 1;  out_running: +	trace_mark(kernel_sched_wakeup, +		"pid %d state %ld ## rq %p task %p rq->curr %p", +		p->pid, p->state, rq, p, rq->curr);  	check_preempt_curr(rq, p);  	p->state = TASK_RUNNING; @@ -2450,6 +2472,9 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)  		p->sched_class->task_new(rq, p);  		inc_nr_running(rq);  	} +	trace_mark(kernel_sched_wakeup_new, +		"pid %d state %ld ## rq %p task %p rq->curr %p", +		p->pid, p->state, rq, p, rq->curr);  	check_preempt_curr(rq, p);  #ifdef CONFIG_SMP  	if (p->sched_class->task_wake_up) @@ -2622,6 +2647,11 @@ context_switch(struct rq *rq, struct task_struct *prev,  	struct mm_struct *mm, *oldmm;  	prepare_task_switch(rq, prev, next); +	trace_mark(kernel_sched_schedule, +		"prev_pid %d next_pid %d prev_state %ld " +		"## rq %p prev %p next %p", +		prev->pid, next->pid, prev->state, +		rq, prev, next);  	mm = next->mm;  	oldmm = prev->active_mm;  	/* @@ -4221,26 +4251,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?  	 */ @@ -4252,7 +4300,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); @@ -5566,7 +5617,7 @@ out_unlock:  	return retval;  } -static const char stat_nam[] = "RSDTtZX"; +static const char stat_nam[] = TASK_STATE_TO_CHAR_STR;  void sched_show_task(struct task_struct *p)  {  |