Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3163b825 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "trace: fix preemption disable tracking during context switch to idle"

parents 1d15dace 9075331c
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
@@ -3322,10 +3322,24 @@ struct preempt_store {
	u64 ts;
	unsigned long caddr[4];
	bool irqs_disabled;
	bool is_idle_task;
};

DEFINE_PER_CPU(struct preempt_store, the_ps);

/*
 * This is only called from __schedule() upon context switch.
 *
 * schedule() calls __schedule() with preemption disabled.
 * if we had entered idle and exiting idle now, reset the preemption
 * tracking otherwise we may think preemption is disabled the whole time
 * when the non idle task re-enables the preemption in schedule().
 */
static inline void preempt_latency_reset(void)
{
	if (is_idle_task(this_rq()->curr))
		this_cpu_ptr(&the_ps)->ts = 0;
}

/*
 * If the value passed in is equal to the current preempt count
 * then we just disabled preemption. Start timing the latency.
@@ -3333,7 +3347,6 @@ DEFINE_PER_CPU(struct preempt_store, the_ps);
static inline void preempt_latency_start(int val)
{
	int cpu = raw_smp_processor_id();
	struct rq *rq = cpu_rq(cpu);
	struct preempt_store *ps = &per_cpu(the_ps, cpu);

	if (preempt_count() == val) {
@@ -3347,7 +3360,6 @@ static inline void preempt_latency_start(int val)
		ps->caddr[2] = CALLER_ADDR2;
		ps->caddr[3] = CALLER_ADDR3;
		ps->irqs_disabled = irqs_disabled();
		ps->is_idle_task = (rq->curr == rq->idle);

		trace_preempt_off(CALLER_ADDR0, ip);
	}
@@ -3384,14 +3396,13 @@ static inline void preempt_latency_stop(int val)
	if (preempt_count() == val) {
		struct preempt_store *ps = &per_cpu(the_ps,
				raw_smp_processor_id());
		u64 delta = sched_clock() - ps->ts;
		u64 delta = ps->ts ? (sched_clock() - ps->ts) : 0;

		/*
		 * Trace preempt disable stack if preemption
		 * is disabled for more than the threshold.
		 */
		if (!ps->is_idle_task &&
				delta > sysctl_preemptoff_tracing_threshold_ns)
		if (delta > sysctl_preemptoff_tracing_threshold_ns)
			trace_sched_preempt_disable(delta, ps->irqs_disabled,
						ps->caddr[0], ps->caddr[1],
						ps->caddr[2], ps->caddr[3]);
@@ -3424,6 +3435,7 @@ NOKPROBE_SYMBOL(preempt_count_sub);
#else
static inline void preempt_latency_start(int val) { }
static inline void preempt_latency_stop(int val) { }
static inline void preempt_latency_reset(void) { }
#endif

static inline unsigned long get_preempt_disable_ip(struct task_struct *p)
@@ -3647,6 +3659,7 @@ static void __sched notrace __schedule(bool preempt)
		if (!prev->on_rq)
			prev->last_sleep_ts = wallclock;

		preempt_latency_reset();
		update_task_ravg(prev, rq, PUT_PREV_TASK, wallclock, 0);
		update_task_ravg(next, rq, PICK_NEXT_TASK, wallclock, 0);
		rq->nr_switches++;