diff options
Diffstat (limited to 'kernel/sched_fair.c')
-rw-r--r-- | kernel/sched_fair.c | 80 |
1 files changed, 72 insertions, 8 deletions
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 5cc1c162044f..3816f217f119 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -719,7 +719,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) | |||
719 | __enqueue_entity(cfs_rq, se); | 719 | __enqueue_entity(cfs_rq, se); |
720 | } | 720 | } |
721 | 721 | ||
722 | static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) | 722 | static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) |
723 | { | 723 | { |
724 | if (cfs_rq->last == se) | 724 | if (cfs_rq->last == se) |
725 | cfs_rq->last = NULL; | 725 | cfs_rq->last = NULL; |
@@ -728,6 +728,12 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
728 | cfs_rq->next = NULL; | 728 | cfs_rq->next = NULL; |
729 | } | 729 | } |
730 | 730 | ||
731 | static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) | ||
732 | { | ||
733 | for_each_sched_entity(se) | ||
734 | __clear_buddies(cfs_rq_of(se), se); | ||
735 | } | ||
736 | |||
731 | static void | 737 | static void |
732 | dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) | 738 | dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) |
733 | { | 739 | { |
@@ -768,8 +774,14 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) | |||
768 | 774 | ||
769 | ideal_runtime = sched_slice(cfs_rq, curr); | 775 | ideal_runtime = sched_slice(cfs_rq, curr); |
770 | delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; | 776 | delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; |
771 | if (delta_exec > ideal_runtime) | 777 | if (delta_exec > ideal_runtime) { |
772 | resched_task(rq_of(cfs_rq)->curr); | 778 | resched_task(rq_of(cfs_rq)->curr); |
779 | /* | ||
780 | * The current task ran long enough, ensure it doesn't get | ||
781 | * re-elected due to buddy favours. | ||
782 | */ | ||
783 | clear_buddies(cfs_rq, curr); | ||
784 | } | ||
773 | } | 785 | } |
774 | 786 | ||
775 | static void | 787 | static void |
@@ -1302,16 +1314,63 @@ out: | |||
1302 | } | 1314 | } |
1303 | #endif /* CONFIG_SMP */ | 1315 | #endif /* CONFIG_SMP */ |
1304 | 1316 | ||
1305 | static unsigned long wakeup_gran(struct sched_entity *se) | 1317 | /* |
1318 | * Adaptive granularity | ||
1319 | * | ||
1320 | * se->avg_wakeup gives the average time a task runs until it does a wakeup, | ||
1321 | * with the limit of wakeup_gran -- when it never does a wakeup. | ||
1322 | * | ||
1323 | * So the smaller avg_wakeup is the faster we want this task to preempt, | ||
1324 | * but we don't want to treat the preemptee unfairly and therefore allow it | ||
1325 | * to run for at least the amount of time we'd like to run. | ||
1326 | * | ||
1327 | * NOTE: we use 2*avg_wakeup to increase the probability of actually doing one | ||
1328 | * | ||
1329 | * NOTE: we use *nr_running to scale with load, this nicely matches the | ||
1330 | * degrading latency on load. | ||
1331 | */ | ||
1332 | static unsigned long | ||
1333 | adaptive_gran(struct sched_entity *curr, struct sched_entity *se) | ||
1334 | { | ||
1335 | u64 this_run = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; | ||
1336 | u64 expected_wakeup = 2*se->avg_wakeup * cfs_rq_of(se)->nr_running; | ||
1337 | u64 gran = 0; | ||
1338 | |||
1339 | if (this_run < expected_wakeup) | ||
1340 | gran = expected_wakeup - this_run; | ||
1341 | |||
1342 | return min_t(s64, gran, sysctl_sched_wakeup_granularity); | ||
1343 | } | ||
1344 | |||
1345 | static unsigned long | ||
1346 | wakeup_gran(struct sched_entity *curr, struct sched_entity *se) | ||
1306 | { | 1347 | { |
1307 | unsigned long gran = sysctl_sched_wakeup_granularity; | 1348 | unsigned long gran = sysctl_sched_wakeup_granularity; |
1308 | 1349 | ||
1350 | if (cfs_rq_of(curr)->curr && sched_feat(ADAPTIVE_GRAN)) | ||
1351 | gran = adaptive_gran(curr, se); | ||
1352 | |||
1309 | /* | 1353 | /* |
1310 | * More easily preempt - nice tasks, while not making it harder for | 1354 | * Since its curr running now, convert the gran from real-time |
1311 | * + nice tasks. | 1355 | * to virtual-time in his units. |
1312 | */ | 1356 | */ |
1313 | if (!sched_feat(ASYM_GRAN) || se->load.weight > NICE_0_LOAD) | 1357 | if (sched_feat(ASYM_GRAN)) { |
1314 | gran = calc_delta_fair(sysctl_sched_wakeup_granularity, se); | 1358 | /* |
1359 | * By using 'se' instead of 'curr' we penalize light tasks, so | ||
1360 | * they get preempted easier. That is, if 'se' < 'curr' then | ||
1361 | * the resulting gran will be larger, therefore penalizing the | ||
1362 | * lighter, if otoh 'se' > 'curr' then the resulting gran will | ||
1363 | * be smaller, again penalizing the lighter task. | ||
1364 | * | ||
1365 | * This is especially important for buddies when the leftmost | ||
1366 | * task is higher priority than the buddy. | ||
1367 | */ | ||
1368 | if (unlikely(se->load.weight != NICE_0_LOAD)) | ||
1369 | gran = calc_delta_fair(gran, se); | ||
1370 | } else { | ||
1371 | if (unlikely(curr->load.weight != NICE_0_LOAD)) | ||
1372 | gran = calc_delta_fair(gran, curr); | ||
1373 | } | ||
1315 | 1374 | ||
1316 | return gran; | 1375 | return gran; |
1317 | } | 1376 | } |
@@ -1338,7 +1397,7 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se) | |||
1338 | if (vdiff <= 0) | 1397 | if (vdiff <= 0) |
1339 | return -1; | 1398 | return -1; |
1340 | 1399 | ||
1341 | gran = wakeup_gran(curr); | 1400 | gran = wakeup_gran(curr, se); |
1342 | if (vdiff > gran) | 1401 | if (vdiff > gran) |
1343 | return 1; | 1402 | return 1; |
1344 | 1403 | ||
@@ -1452,6 +1511,11 @@ static struct task_struct *pick_next_task_fair(struct rq *rq) | |||
1452 | 1511 | ||
1453 | do { | 1512 | do { |
1454 | se = pick_next_entity(cfs_rq); | 1513 | se = pick_next_entity(cfs_rq); |
1514 | /* | ||
1515 | * If se was a buddy, clear it so that it will have to earn | ||
1516 | * the favour again. | ||
1517 | */ | ||
1518 | __clear_buddies(cfs_rq, se); | ||
1455 | set_next_entity(cfs_rq, se); | 1519 | set_next_entity(cfs_rq, se); |
1456 | cfs_rq = group_cfs_rq(se); | 1520 | cfs_rq = group_cfs_rq(se); |
1457 | } while (cfs_rq); | 1521 | } while (cfs_rq); |