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

Commit 606dba2e authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

sched: Push put_prev_task() into pick_next_task()



In order to avoid having to do put/set on a whole cgroup hierarchy
when we context switch, push the put into pick_next_task() so that
both operations are in the same function. Further changes then allow
us to possibly optimize away redundant work.

Signed-off-by: default avatarPeter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1328936700.2476.17.camel@laptop


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent fed14d45
Loading
Loading
Loading
Loading
+8 −13
Original line number Diff line number Diff line
@@ -2579,18 +2579,11 @@ static inline void schedule_debug(struct task_struct *prev)
	schedstat_inc(this_rq(), sched_count);
}

static void put_prev_task(struct rq *rq, struct task_struct *prev)
{
	if (prev->on_rq || rq->skip_clock_update < 0)
		update_rq_clock(rq);
	prev->sched_class->put_prev_task(rq, prev);
}

/*
 * Pick up the highest-prio task:
 */
static inline struct task_struct *
pick_next_task(struct rq *rq)
pick_next_task(struct rq *rq, struct task_struct *prev)
{
	const struct sched_class *class;
	struct task_struct *p;
@@ -2600,13 +2593,13 @@ pick_next_task(struct rq *rq)
	 * the fair class we can call that function directly:
	 */
	if (likely(rq->nr_running == rq->cfs.h_nr_running)) {
		p = fair_sched_class.pick_next_task(rq);
		p = fair_sched_class.pick_next_task(rq, prev);
		if (likely(p))
			return p;
	}

	for_each_class(class) {
		p = class->pick_next_task(rq);
		p = class->pick_next_task(rq, prev);
		if (p)
			return p;
	}
@@ -2714,8 +2707,10 @@ static void __sched __schedule(void)
			rq->idle_stamp = 0;
	}

	put_prev_task(rq, prev);
	next = pick_next_task(rq);
	if (prev->on_rq || rq->skip_clock_update < 0)
		update_rq_clock(rq);

	next = pick_next_task(rq, prev);
	clear_tsk_need_resched(prev);
	clear_preempt_need_resched();
	rq->skip_clock_update = 0;
@@ -4748,7 +4743,7 @@ static void migrate_tasks(unsigned int dead_cpu)
		if (rq->nr_running == 1)
			break;

		next = pick_next_task(rq);
		next = pick_next_task(rq, NULL);
		BUG_ON(!next);
		next->sched_class->put_prev_task(rq, next);

+4 −1
Original line number Diff line number Diff line
@@ -990,7 +990,7 @@ static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq,
	return rb_entry(left, struct sched_dl_entity, rb_node);
}

struct task_struct *pick_next_task_dl(struct rq *rq)
struct task_struct *pick_next_task_dl(struct rq *rq, struct task_struct *prev)
{
	struct sched_dl_entity *dl_se;
	struct task_struct *p;
@@ -1001,6 +1001,9 @@ struct task_struct *pick_next_task_dl(struct rq *rq)
	if (unlikely(!dl_rq->dl_nr_running))
		return NULL;

	if (prev)
		prev->sched_class->put_prev_task(rq, prev);

	dl_se = pick_next_dl_entity(rq, dl_rq);
	BUG_ON(!dl_se);

+5 −1
Original line number Diff line number Diff line
@@ -4655,7 +4655,8 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
		set_last_buddy(se);
}

static struct task_struct *pick_next_task_fair(struct rq *rq)
static struct task_struct *
pick_next_task_fair(struct rq *rq, struct task_struct *prev)
{
	struct task_struct *p;
	struct cfs_rq *cfs_rq = &rq->cfs;
@@ -4664,6 +4665,9 @@ static struct task_struct *pick_next_task_fair(struct rq *rq)
	if (!cfs_rq->nr_running)
		return NULL;

	if (prev)
		prev->sched_class->put_prev_task(rq, prev);

	do {
		se = pick_next_entity(cfs_rq);
		set_next_entity(cfs_rq, se);
+5 −1
Original line number Diff line number Diff line
@@ -33,8 +33,12 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl
	resched_task(rq->idle);
}

static struct task_struct *pick_next_task_idle(struct rq *rq)
static struct task_struct *
pick_next_task_idle(struct rq *rq, struct task_struct *prev)
{
	if (prev)
		prev->sched_class->put_prev_task(rq, prev);

	schedstat_inc(rq, sched_goidle);
#ifdef CONFIG_SMP
	/* Trigger the post schedule to do an idle_enter for CFS */
+16 −11
Original line number Diff line number Diff line
@@ -1310,15 +1310,7 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
{
	struct sched_rt_entity *rt_se;
	struct task_struct *p;
	struct rt_rq *rt_rq;

	rt_rq = &rq->rt;

	if (!rt_rq->rt_nr_running)
		return NULL;

	if (rt_rq_throttled(rt_rq))
		return NULL;
	struct rt_rq *rt_rq  = &rq->rt;

	do {
		rt_se = pick_next_rt_entity(rq, rt_rq);
@@ -1332,9 +1324,22 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
	return p;
}

static struct task_struct *pick_next_task_rt(struct rq *rq)
static struct task_struct *
pick_next_task_rt(struct rq *rq, struct task_struct *prev)
{
	struct task_struct *p = _pick_next_task_rt(rq);
	struct task_struct *p;
	struct rt_rq *rt_rq = &rq->rt;

	if (!rt_rq->rt_nr_running)
		return NULL;

	if (rt_rq_throttled(rt_rq))
		return NULL;

	if (prev)
		prev->sched_class->put_prev_task(rq, prev);

	p = _pick_next_task_rt(rq);

	/* The running task is never eligible for pushing */
	if (p)
Loading