Skip to content

Commit ad4b78b

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
sched: Add new wakeup preemption mode: WAKEUP_RUNNING
Create a new wakeup preemption mode, preempt towards tasks that run shorter on avg. It sets next buddy to be sure we actually run the task we preempted for. Test results: root@twins:~# while :; do :; done & [1] 6537 root@twins:~# while :; do :; done & [2] 6538 root@twins:~# while :; do :; done & [3] 6539 root@twins:~# while :; do :; done & [4] 6540 root@twins:/home/peter# ./latt -c4 sleep 4 Entries: 48 (clients=4) Averages: ------------------------------ Max 4750 usec Avg 497 usec Stdev 737 usec root@twins:/home/peter# echo WAKEUP_RUNNING > /debug/sched_features root@twins:/home/peter# ./latt -c4 sleep 4 Entries: 48 (clients=4) Averages: ------------------------------ Max 14 usec Avg 5 usec Stdev 3 usec Disabled by default - needs more testing. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Mike Galbraith <efault@gmx.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> LKML-Reference: <new-submission>
1 parent eb24073 commit ad4b78b

File tree

5 files changed

+29
-10
lines changed

5 files changed

+29
-10
lines changed

include/linux/sched.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,8 @@ struct sched_entity {
11131113
u64 start_runtime;
11141114
u64 avg_wakeup;
11151115

1116+
u64 avg_running;
1117+
11161118
#ifdef CONFIG_SCHEDSTATS
11171119
u64 wait_start;
11181120
u64 wait_max;

kernel/sched.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,6 +2458,7 @@ static void __sched_fork(struct task_struct *p)
24582458
p->se.avg_overlap = 0;
24592459
p->se.start_runtime = 0;
24602460
p->se.avg_wakeup = sysctl_sched_wakeup_granularity;
2461+
p->se.avg_running = 0;
24612462

24622463
#ifdef CONFIG_SCHEDSTATS
24632464
p->se.wait_start = 0;
@@ -5310,14 +5311,13 @@ static inline void schedule_debug(struct task_struct *prev)
53105311
#endif
53115312
}
53125313

5313-
static void put_prev_task(struct rq *rq, struct task_struct *prev)
5314+
static void put_prev_task(struct rq *rq, struct task_struct *p)
53145315
{
5315-
if (prev->state == TASK_RUNNING) {
5316-
u64 runtime = prev->se.sum_exec_runtime;
5316+
u64 runtime = p->se.sum_exec_runtime - p->se.prev_sum_exec_runtime;
53175317

5318-
runtime -= prev->se.prev_sum_exec_runtime;
5319-
runtime = min_t(u64, runtime, 2*sysctl_sched_migration_cost);
5318+
update_avg(&p->se.avg_running, runtime);
53205319

5320+
if (p->state == TASK_RUNNING) {
53215321
/*
53225322
* In order to avoid avg_overlap growing stale when we are
53235323
* indeed overlapping and hence not getting put to sleep, grow
@@ -5327,9 +5327,12 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev)
53275327
* correlates to the amount of cache footprint a task can
53285328
* build up.
53295329
*/
5330-
update_avg(&prev->se.avg_overlap, runtime);
5330+
runtime = min_t(u64, runtime, 2*sysctl_sched_migration_cost);
5331+
update_avg(&p->se.avg_overlap, runtime);
5332+
} else {
5333+
update_avg(&p->se.avg_running, 0);
53315334
}
5332-
prev->sched_class->put_prev_task(rq, prev);
5335+
p->sched_class->put_prev_task(rq, p);
53335336
}
53345337

53355338
/*

kernel/sched_debug.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
395395
PN(se.sum_exec_runtime);
396396
PN(se.avg_overlap);
397397
PN(se.avg_wakeup);
398+
PN(se.avg_running);
398399

399400
nr_switches = p->nvcsw + p->nivcsw;
400401

kernel/sched_fair.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,9 +1605,6 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
16051605
return;
16061606
}
16071607

1608-
if (!sched_feat(WAKEUP_PREEMPT))
1609-
return;
1610-
16111608
if ((sched_feat(WAKEUP_SYNC) && sync) ||
16121609
(sched_feat(WAKEUP_OVERLAP) &&
16131610
(se->avg_overlap < sysctl_sched_migration_cost &&
@@ -1616,6 +1613,17 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
16161613
return;
16171614
}
16181615

1616+
if (sched_feat(WAKEUP_RUNNING)) {
1617+
if (pse->avg_running < se->avg_running) {
1618+
set_next_buddy(pse);
1619+
resched_task(curr);
1620+
return;
1621+
}
1622+
}
1623+
1624+
if (!sched_feat(WAKEUP_PREEMPT))
1625+
return;
1626+
16191627
find_matching_se(&se, &pse);
16201628

16211629
BUG_ON(!pse);

kernel/sched_features.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ SCHED_FEAT(WAKEUP_SYNC, 0)
5353
*/
5454
SCHED_FEAT(WAKEUP_OVERLAP, 0)
5555

56+
/*
57+
* Wakeup preemption towards tasks that run short
58+
*/
59+
SCHED_FEAT(WAKEUP_RUNNING, 0)
60+
5661
/*
5762
* Use the SYNC wakeup hint, pipes and the likes use this to indicate
5863
* the remote end is likely to consume the data we just wrote, and

0 commit comments

Comments
 (0)