Skip to content

Commit

Permalink
sched: prevent wakeup over-scheduling
Browse files Browse the repository at this point in the history
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: Mike Galbraith <efault@gmx.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Mike Galbraith authored and Ingo Molnar committed Oct 15, 2007
1 parent ce6c131 commit 95938a3
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 4 deletions.
1 change: 1 addition & 0 deletions include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,14 +445,16 @@ 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 =
SCHED_FEAT_NEW_FAIR_SLEEPERS *1 |
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)

Expand Down
14 changes: 11 additions & 3 deletions kernel/sched_fair.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -839,8 +842,12 @@ 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)
resched_task(curr);
if (delta > gran) {
int now = !sched_feat(PREEMPT_RESTRICT);

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

Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit 95938a3

Please sign in to comment.