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

Commit 95938a35 authored by Mike Galbraith's avatar Mike Galbraith Committed by Ingo Molnar
Browse files

sched: prevent wakeup over-scheduling



Prevent wakeup over-scheduling.  Once a task has been preempted by a
task of the same or lower priority, it becomes ineligible for repeated
preemption by same until it has been ticked, or slept.  Instead, the
task is marked for preemption at the next tick.  Tasks of higher
priority still preempt immediately.

Signed-off-by: default avatarMike Galbraith <efault@gmx.de>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent ce6c1311
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -912,6 +912,7 @@ struct sched_entity {
	struct load_weight	load;		/* for load-balancing */
	struct rb_node		run_node;
	unsigned int		on_rq;
	int			peer_preempt;

	u64			exec_start;
	u64			sum_exec_runtime;
+3 −1
Original line number Diff line number Diff line
@@ -445,6 +445,7 @@ enum {
	SCHED_FEAT_TREE_AVG             = 4,
	SCHED_FEAT_APPROX_AVG           = 8,
	SCHED_FEAT_WAKEUP_PREEMPT	= 16,
	SCHED_FEAT_PREEMPT_RESTRICT	= 32,
};

const_debug unsigned int sysctl_sched_features =
@@ -452,7 +453,8 @@ const_debug unsigned int sysctl_sched_features =
		SCHED_FEAT_START_DEBIT		*1 |
		SCHED_FEAT_TREE_AVG		*0 |
		SCHED_FEAT_APPROX_AVG		*0 |
		SCHED_FEAT_WAKEUP_PREEMPT	*1;
		SCHED_FEAT_WAKEUP_PREEMPT	*1 |
		SCHED_FEAT_PREEMPT_RESTRICT	*1;

#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x)

+11 −3
Original line number Diff line number Diff line
@@ -526,6 +526,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)

	update_stats_dequeue(cfs_rq, se);
	if (sleep) {
		se->peer_preempt = 0;
#ifdef CONFIG_SCHEDSTATS
		if (entity_is_task(se)) {
			struct task_struct *tsk = task_of(se);
@@ -553,8 +554,10 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)

	ideal_runtime = sched_slice(cfs_rq, curr);
	delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;
	if (delta_exec > ideal_runtime)
	if (delta_exec > ideal_runtime ||
			(sched_feat(PREEMPT_RESTRICT) && curr->peer_preempt))
		resched_task(rq_of(cfs_rq)->curr);
	curr->peer_preempt = 0;
}

static void
@@ -839,10 +842,14 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
		if (unlikely(se->load.weight != NICE_0_LOAD))
			gran = calc_delta_fair(gran, &se->load);

		if (delta > gran)
		if (delta > gran) {
			int now = !sched_feat(PREEMPT_RESTRICT);

			if (now || p->prio < curr->prio || !se->peer_preempt++)
				resched_task(curr);
		}
	}
}

static struct task_struct *pick_next_task_fair(struct rq *rq)
{
@@ -1034,6 +1041,7 @@ static void task_new_fair(struct rq *rq, struct task_struct *p)
	check_spread(cfs_rq, curr);
	__enqueue_entity(cfs_rq, se);
	account_entity_enqueue(cfs_rq, se);
	se->peer_preempt = 0;
	resched_task(rq->curr);
}