aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched_fair.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-11-05 13:56:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-11-05 13:56:47 -0500
commit608221fdf9a2170962295dcfbea53dc5c50d1a74 (patch)
tree26712f2f8a8a332369df2b31174c8c5b46c42164 /kernel/sched_fair.c
parent72cc129e8dae988d2a132467cfd0ecd7623c35fb (diff)
parentb84ff7d6f1b7f8a43414e74d972ec4c8f3361db4 (diff)
Merge branch 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: sched: Fix kthread_bind() by moving the body of kthread_bind() to sched.c sched: Disable SD_PREFER_LOCAL at node level sched: Fix boot crash by zalloc()ing most of the cpu masks sched: Strengthen buddies and mitigate buddy induced latencies
Diffstat (limited to 'kernel/sched_fair.c')
-rw-r--r--kernel/sched_fair.c73
1 files changed, 47 insertions, 26 deletions
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index c32c3e643daa..37087a7fac22 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -822,6 +822,26 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
822 * re-elected due to buddy favours. 822 * re-elected due to buddy favours.
823 */ 823 */
824 clear_buddies(cfs_rq, curr); 824 clear_buddies(cfs_rq, curr);
825 return;
826 }
827
828 /*
829 * Ensure that a task that missed wakeup preemption by a
830 * narrow margin doesn't have to wait for a full slice.
831 * This also mitigates buddy induced latencies under load.
832 */
833 if (!sched_feat(WAKEUP_PREEMPT))
834 return;
835
836 if (delta_exec < sysctl_sched_min_granularity)
837 return;
838
839 if (cfs_rq->nr_running > 1) {
840 struct sched_entity *se = __pick_next_entity(cfs_rq);
841 s64 delta = curr->vruntime - se->vruntime;
842
843 if (delta > ideal_runtime)
844 resched_task(rq_of(cfs_rq)->curr);
825 } 845 }
826} 846}
827 847
@@ -861,21 +881,18 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se);
861static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq) 881static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
862{ 882{
863 struct sched_entity *se = __pick_next_entity(cfs_rq); 883 struct sched_entity *se = __pick_next_entity(cfs_rq);
864 struct sched_entity *buddy; 884 struct sched_entity *left = se;
865 885
866 if (cfs_rq->next) { 886 if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, left) < 1)
867 buddy = cfs_rq->next; 887 se = cfs_rq->next;
868 cfs_rq->next = NULL;
869 if (wakeup_preempt_entity(buddy, se) < 1)
870 return buddy;
871 }
872 888
873 if (cfs_rq->last) { 889 /*
874 buddy = cfs_rq->last; 890 * Prefer last buddy, try to return the CPU to a preempted task.
875 cfs_rq->last = NULL; 891 */
876 if (wakeup_preempt_entity(buddy, se) < 1) 892 if (cfs_rq->last && wakeup_preempt_entity(cfs_rq->last, left) < 1)
877 return buddy; 893 se = cfs_rq->last;
878 } 894
895 clear_buddies(cfs_rq, se);
879 896
880 return se; 897 return se;
881} 898}
@@ -1577,6 +1594,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
1577 struct sched_entity *se = &curr->se, *pse = &p->se; 1594 struct sched_entity *se = &curr->se, *pse = &p->se;
1578 struct cfs_rq *cfs_rq = task_cfs_rq(curr); 1595 struct cfs_rq *cfs_rq = task_cfs_rq(curr);
1579 int sync = wake_flags & WF_SYNC; 1596 int sync = wake_flags & WF_SYNC;
1597 int scale = cfs_rq->nr_running >= sched_nr_latency;
1580 1598
1581 update_curr(cfs_rq); 1599 update_curr(cfs_rq);
1582 1600
@@ -1591,18 +1609,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
1591 if (unlikely(se == pse)) 1609 if (unlikely(se == pse))
1592 return; 1610 return;
1593 1611
1594 /* 1612 if (sched_feat(NEXT_BUDDY) && scale && !(wake_flags & WF_FORK))
1595 * Only set the backward buddy when the current task is still on the
1596 * rq. This can happen when a wakeup gets interleaved with schedule on
1597 * the ->pre_schedule() or idle_balance() point, either of which can
1598 * drop the rq lock.
1599 *
1600 * Also, during early boot the idle thread is in the fair class, for
1601 * obvious reasons its a bad idea to schedule back to the idle thread.
1602 */
1603 if (sched_feat(LAST_BUDDY) && likely(se->on_rq && curr != rq->idle))
1604 set_last_buddy(se);
1605 if (sched_feat(NEXT_BUDDY) && !(wake_flags & WF_FORK))
1606 set_next_buddy(pse); 1613 set_next_buddy(pse);
1607 1614
1608 /* 1615 /*
@@ -1648,8 +1655,22 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
1648 1655
1649 BUG_ON(!pse); 1656 BUG_ON(!pse);
1650 1657
1651 if (wakeup_preempt_entity(se, pse) == 1) 1658 if (wakeup_preempt_entity(se, pse) == 1) {
1652 resched_task(curr); 1659 resched_task(curr);
1660 /*
1661 * Only set the backward buddy when the current task is still
1662 * on the rq. This can happen when a wakeup gets interleaved
1663 * with schedule on the ->pre_schedule() or idle_balance()
1664 * point, either of which can * drop the rq lock.
1665 *
1666 * Also, during early boot the idle thread is in the fair class,
1667 * for obvious reasons its a bad idea to schedule back to it.
1668 */
1669 if (unlikely(!se->on_rq || curr == rq->idle))
1670 return;
1671 if (sched_feat(LAST_BUDDY) && scale && entity_is_task(se))
1672 set_last_buddy(se);
1673 }
1653} 1674}
1654 1675
1655static struct task_struct *pick_next_task_fair(struct rq *rq) 1676static struct task_struct *pick_next_task_fair(struct rq *rq)