Commit 31c952dc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'sched-fixes-for-linus' of...

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_rt: don't use first_cpu on cpumask created with cpumask_and
  sched: fix buddie group latency
  sched: clear buddies more aggressively
  sched: symmetric sync vs avg_overlap
  sched: fix sync wakeups
  cpuset: fix possible deadlock in async_rebuild_sched_domains
parents 9e6235e9 3d398703
...@@ -60,6 +60,14 @@ ...@@ -60,6 +60,14 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/cgroup.h> #include <linux/cgroup.h>
/*
* Workqueue for cpuset related tasks.
*
* Using kevent workqueue may cause deadlock when memory_migrate
* is set. So we create a separate workqueue thread for cpuset.
*/
static struct workqueue_struct *cpuset_wq;
/* /*
* Tracks how many cpusets are currently defined in system. * Tracks how many cpusets are currently defined in system.
* When there is only one cpuset (the root cpuset) we can * When there is only one cpuset (the root cpuset) we can
...@@ -831,7 +839,7 @@ static DECLARE_WORK(rebuild_sched_domains_work, do_rebuild_sched_domains); ...@@ -831,7 +839,7 @@ static DECLARE_WORK(rebuild_sched_domains_work, do_rebuild_sched_domains);
*/ */
static void async_rebuild_sched_domains(void) static void async_rebuild_sched_domains(void)
{ {
schedule_work(&rebuild_sched_domains_work); queue_work(cpuset_wq, &rebuild_sched_domains_work);
} }
/* /*
...@@ -2111,6 +2119,9 @@ void __init cpuset_init_smp(void) ...@@ -2111,6 +2119,9 @@ void __init cpuset_init_smp(void)
hotcpu_notifier(cpuset_track_online_cpus, 0); hotcpu_notifier(cpuset_track_online_cpus, 0);
hotplug_memory_notifier(cpuset_track_online_nodes, 10); hotplug_memory_notifier(cpuset_track_online_nodes, 10);
cpuset_wq = create_singlethread_workqueue("cpuset");
BUG_ON(!cpuset_wq);
} }
/** /**
......
...@@ -2266,6 +2266,16 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) ...@@ -2266,6 +2266,16 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
if (!sched_feat(SYNC_WAKEUPS)) if (!sched_feat(SYNC_WAKEUPS))
sync = 0; sync = 0;
if (!sync) {
if (current->se.avg_overlap < sysctl_sched_migration_cost &&
p->se.avg_overlap < sysctl_sched_migration_cost)
sync = 1;
} else {
if (current->se.avg_overlap >= sysctl_sched_migration_cost ||
p->se.avg_overlap >= sysctl_sched_migration_cost)
sync = 0;
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (sched_feat(LB_WAKEUP_UPDATE)) { if (sched_feat(LB_WAKEUP_UPDATE)) {
struct sched_domain *sd; struct sched_domain *sd;
......
...@@ -719,7 +719,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) ...@@ -719,7 +719,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
__enqueue_entity(cfs_rq, se); __enqueue_entity(cfs_rq, se);
} }
static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
{ {
if (cfs_rq->last == se) if (cfs_rq->last == se)
cfs_rq->last = NULL; cfs_rq->last = NULL;
...@@ -728,6 +728,12 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) ...@@ -728,6 +728,12 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
cfs_rq->next = NULL; cfs_rq->next = NULL;
} }
static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
for_each_sched_entity(se)
__clear_buddies(cfs_rq_of(se), se);
}
static void static void
dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
{ {
...@@ -768,8 +774,14 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) ...@@ -768,8 +774,14 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
ideal_runtime = sched_slice(cfs_rq, curr); ideal_runtime = sched_slice(cfs_rq, curr);
delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;
if (delta_exec > ideal_runtime) if (delta_exec > ideal_runtime) {
resched_task(rq_of(cfs_rq)->curr); resched_task(rq_of(cfs_rq)->curr);
/*
* The current task ran long enough, ensure it doesn't get
* re-elected due to buddy favours.
*/
clear_buddies(cfs_rq, curr);
}
} }
static void static void
...@@ -1179,20 +1191,15 @@ wake_affine(struct sched_domain *this_sd, struct rq *this_rq, ...@@ -1179,20 +1191,15 @@ wake_affine(struct sched_domain *this_sd, struct rq *this_rq,
int idx, unsigned long load, unsigned long this_load, int idx, unsigned long load, unsigned long this_load,
unsigned int imbalance) unsigned int imbalance)
{ {
struct task_struct *curr = this_rq->curr;
struct task_group *tg;
unsigned long tl = this_load; unsigned long tl = this_load;
unsigned long tl_per_task; unsigned long tl_per_task;
struct task_group *tg;
unsigned long weight; unsigned long weight;
int balanced; int balanced;
if (!(this_sd->flags & SD_WAKE_AFFINE) || !sched_feat(AFFINE_WAKEUPS)) if (!(this_sd->flags & SD_WAKE_AFFINE) || !sched_feat(AFFINE_WAKEUPS))
return 0; return 0;
if (sync && (curr->se.avg_overlap > sysctl_sched_migration_cost ||
p->se.avg_overlap > sysctl_sched_migration_cost))
sync = 0;
/* /*
* If sync wakeup then subtract the (maximum possible) * If sync wakeup then subtract the (maximum possible)
* effect of the currently running task from the load * effect of the currently running task from the load
...@@ -1419,9 +1426,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync) ...@@ -1419,9 +1426,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync)
if (!sched_feat(WAKEUP_PREEMPT)) if (!sched_feat(WAKEUP_PREEMPT))
return; return;
if (sched_feat(WAKEUP_OVERLAP) && (sync || if (sched_feat(WAKEUP_OVERLAP) && sync) {
(se->avg_overlap < sysctl_sched_migration_cost &&
pse->avg_overlap < sysctl_sched_migration_cost))) {
resched_task(curr); resched_task(curr);
return; return;
} }
...@@ -1452,6 +1457,11 @@ static struct task_struct *pick_next_task_fair(struct rq *rq) ...@@ -1452,6 +1457,11 @@ static struct task_struct *pick_next_task_fair(struct rq *rq)
do { do {
se = pick_next_entity(cfs_rq); se = pick_next_entity(cfs_rq);
/*
* If se was a buddy, clear it so that it will have to earn
* the favour again.
*/
__clear_buddies(cfs_rq, se);
set_next_entity(cfs_rq, se); set_next_entity(cfs_rq, se);
cfs_rq = group_cfs_rq(se); cfs_rq = group_cfs_rq(se);
} while (cfs_rq); } while (cfs_rq);
......
...@@ -968,8 +968,8 @@ static inline int pick_optimal_cpu(int this_cpu, cpumask_t *mask) ...@@ -968,8 +968,8 @@ static inline int pick_optimal_cpu(int this_cpu, cpumask_t *mask)
if ((this_cpu != -1) && cpu_isset(this_cpu, *mask)) if ((this_cpu != -1) && cpu_isset(this_cpu, *mask))
return this_cpu; return this_cpu;
first = first_cpu(*mask); first = cpumask_first(mask);
if (first != NR_CPUS) if (first < nr_cpu_ids)
return first; return first;
return -1; return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment