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

Commit 5c351b80 authored by Srivatsa Vaddagiri's avatar Srivatsa Vaddagiri Committed by Steve Muckle
Browse files

sched: window-stats: Fix potential wrong use of rq



'rq' reference to a cpu where a waking task last ran can be
potentially incorrect leading to incorrect accounting. This happens
when task_cpu() changes between points A & B in try_to_wake_up()
listed below:

try_to_wake_up()
{

cpu = src_cpu = task_cpu(p);
rq = cpu_rq(src_cpu);		-> Point A

..

while (p->on_cpu)
	cpu_relax();

smp_rmb();

raw_spin_lock(&rq->lock);	-> Point B

Fix this by initializing 'rq' variable after task has slept (its
on_cpu field becomes 0).

Also avoid adding task demand to its old cpu runqueue
(prev_runnable_sum) in case it's gone offline.

Change-Id: I9e5d3beeca01796d944137b5416805b983a6e06e
Signed-off-by: default avatarSrivatsa Vaddagiri <vatsa@codeaurora.org>
parent acdce027
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -1338,7 +1338,8 @@ static void update_task_ravg(struct task_struct *p, struct rq *rq,
		mark_start = window_start;
	} while (new_window);

	if ((event == TASK_WAKE) && (rq->window_start > p->ravg.mark_start) &&
	if ((event == TASK_WAKE) && cpu_online(cpu_of(rq)) &&
		 (rq->window_start > p->ravg.mark_start) &&
		(rq->window_start - p->ravg.mark_start > window_size)) {
			if (long_sleep)
				*long_sleep = 1;
@@ -2330,8 +2331,8 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
	unsigned long flags;
	int cpu, success = 0;
	unsigned long src_cpu;
	struct rq *rq;
#ifdef CONFIG_SMP
	struct rq *rq;
	int long_sleep = 0;
	u64 wallclock;
#endif
@@ -2345,7 +2346,6 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
	smp_mb__before_spinlock();
	raw_spin_lock_irqsave(&p->pi_lock, flags);
	src_cpu = cpu = task_cpu(p);
	rq = cpu_rq(src_cpu);

	if (!(p->state & state))
		goto out;
@@ -2367,6 +2367,8 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
	 */
	smp_rmb();

	rq = cpu_rq(task_cpu(p));

	raw_spin_lock(&rq->lock);
	wallclock = sched_clock();
	update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, NULL);