Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2caf4703 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of...

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-sched-devel

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-sched-devel:
  sched: tune multi-core idle balancing
  sched: retune wake granularity
  sched: wakeup-buddy tasks are cache-hot
  sched: improve affine wakeups
  sched, net: socket wakeups are sync
  sched: clean up wakeup balancing, code flow
  sched: clean up wakeup balancing, rename variables
  sched: clean up wakeup balancing, move wake_affine()
parents 6c3c3158 33b0c421
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -929,6 +929,9 @@ struct sched_entity {
	u64			vruntime;
	u64			prev_sum_exec_runtime;

	u64			last_wakeup;
	u64			avg_overlap;

#ifdef CONFIG_SCHEDSTATS
	u64			wait_start;
	u64			wait_max;
+0 −1
Original line number Diff line number Diff line
@@ -138,7 +138,6 @@
				| SD_BALANCE_FORK	\
				| SD_BALANCE_EXEC	\
				| SD_WAKE_AFFINE	\
				| SD_WAKE_IDLE		\
				| SD_SHARE_PKG_RESOURCES\
				| BALANCE_FOR_MC_POWER,	\
	.last_balance		= jiffies,		\
+10 −1
Original line number Diff line number Diff line
@@ -1396,6 +1396,12 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
{
	s64 delta;

	/*
	 * Buddy candidates are cache hot:
	 */
	if (&p->se == cfs_rq_of(&p->se)->next)
		return 1;

	if (p->sched_class != &fair_sched_class)
		return 0;

@@ -1855,10 +1861,11 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
		schedstat_inc(p, se.nr_wakeups_remote);
	update_rq_clock(rq);
	activate_task(rq, p, 1);
	check_preempt_curr(rq, p);
	success = 1;

out_running:
	check_preempt_curr(rq, p);

	p->state = TASK_RUNNING;
#ifdef CONFIG_SMP
	if (p->sched_class->task_wake_up)
@@ -1892,6 +1899,8 @@ static void __sched_fork(struct task_struct *p)
	p->se.exec_start		= 0;
	p->se.sum_exec_runtime		= 0;
	p->se.prev_sum_exec_runtime	= 0;
	p->se.last_wakeup		= 0;
	p->se.avg_overlap		= 0;

#ifdef CONFIG_SCHEDSTATS
	p->se.wait_start		= 0;
+1 −0
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
	PN(se.exec_start);
	PN(se.vruntime);
	PN(se.sum_exec_runtime);
	PN(se.avg_overlap);

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

+118 −73
Original line number Diff line number Diff line
@@ -73,13 +73,13 @@ unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL;

/*
 * SCHED_OTHER wake-up granularity.
 * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds)
 * (default: 5 msec * (1 + ilog(ncpus)), units: nanoseconds)
 *
 * This option delays the preemption effects of decoupled workloads
 * and reduces their over-scheduling. Synchronous workloads will still
 * have immediate wakeup/sleep latencies.
 */
unsigned int sysctl_sched_wakeup_granularity = 10000000UL;
unsigned int sysctl_sched_wakeup_granularity = 5000000UL;

const_debug unsigned int sysctl_sched_migration_cost = 500000UL;

@@ -556,6 +556,21 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
	account_entity_enqueue(cfs_rq, se);
}

static void update_avg(u64 *avg, u64 sample)
{
	s64 diff = sample - *avg;
	*avg += diff >> 3;
}

static void update_avg_stats(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
	if (!se->last_wakeup)
		return;

	update_avg(&se->avg_overlap, se->sum_exec_runtime - se->last_wakeup);
	se->last_wakeup = 0;
}

static void
dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
{
@@ -566,6 +581,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)

	update_stats_dequeue(cfs_rq, se);
	if (sleep) {
		update_avg_stats(cfs_rq, se);
#ifdef CONFIG_SCHEDSTATS
		if (entity_is_task(se)) {
			struct task_struct *tsk = task_of(se);
@@ -980,55 +996,32 @@ static inline int wake_idle(int cpu, struct task_struct *p)
#endif

#ifdef CONFIG_SMP
static int select_task_rq_fair(struct task_struct *p, int sync)
{
	int cpu, this_cpu;
	struct rq *rq;
	struct sched_domain *sd, *this_sd = NULL;
	int new_cpu;

	cpu      = task_cpu(p);
	rq       = task_rq(p);
	this_cpu = smp_processor_id();
	new_cpu  = cpu;

	if (cpu == this_cpu)
		goto out_set_cpu;

	for_each_domain(this_cpu, sd) {
		if (cpu_isset(cpu, sd->span)) {
			this_sd = sd;
			break;
		}
	}

	if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
		goto out_set_cpu;

	/*
	 * Check for affine wakeup and passive balancing possibilities.
	 */
	if (this_sd) {
		int idx = this_sd->wake_idx;
		unsigned int imbalance;
		unsigned long load, this_load;
static const struct sched_class fair_sched_class;

		imbalance = 100 + (this_sd->imbalance_pct - 100) / 2;

		load = source_load(cpu, idx);
		this_load = target_load(this_cpu, idx);

		new_cpu = this_cpu; /* Wake to this CPU if we can */

		if (this_sd->flags & SD_WAKE_AFFINE) {
static int
wake_affine(struct rq *rq, struct sched_domain *this_sd, struct rq *this_rq,
	    struct task_struct *p, int prev_cpu, int this_cpu, int sync,
	    int idx, unsigned long load, unsigned long this_load,
	    unsigned int imbalance)
{
	struct task_struct *curr = this_rq->curr;
	unsigned long tl = this_load;
	unsigned long tl_per_task;

	if (!(this_sd->flags & SD_WAKE_AFFINE))
		return 0;

	/*
			 * Attract cache-cold tasks on sync wakeups:
	 * If the currently running task will sleep within
	 * a reasonable amount of time then attract this newly
	 * woken task:
	 */
			if (sync && !task_hot(p, rq->clock, this_sd))
				goto out_set_cpu;
	if (sync && curr->sched_class == &fair_sched_class) {
		if (curr->se.avg_overlap < sysctl_sched_migration_cost &&
				p->se.avg_overlap < sysctl_sched_migration_cost)
			return 1;
	}

	schedstat_inc(p, se.nr_wakeups_affine_attempts);
	tl_per_task = cpu_avg_load_per_task(this_cpu);
@@ -1041,8 +1034,7 @@ static int select_task_rq_fair(struct task_struct *p, int sync)
	if (sync)
		tl -= current->se.load.weight;

			if ((tl <= load &&
				tl + target_load(cpu, idx) <= tl_per_task) ||
	if ((tl <= load && tl + target_load(prev_cpu, idx) <= tl_per_task) ||
			100*(tl + p->se.load.weight) <= imbalance*load) {
		/*
		 * This domain has SD_WAKE_AFFINE and
@@ -1051,10 +1043,61 @@ static int select_task_rq_fair(struct task_struct *p, int sync)
		 */
		schedstat_inc(this_sd, ttwu_move_affine);
		schedstat_inc(p, se.nr_wakeups_affine);
				goto out_set_cpu;

		return 1;
	}
	return 0;
}

static int select_task_rq_fair(struct task_struct *p, int sync)
{
	struct sched_domain *sd, *this_sd = NULL;
	int prev_cpu, this_cpu, new_cpu;
	unsigned long load, this_load;
	struct rq *rq, *this_rq;
	unsigned int imbalance;
	int idx;

	prev_cpu	= task_cpu(p);
	rq		= task_rq(p);
	this_cpu	= smp_processor_id();
	this_rq		= cpu_rq(this_cpu);
	new_cpu		= prev_cpu;

	/*
	 * 'this_sd' is the first domain that both
	 * this_cpu and prev_cpu are present in:
	 */
	for_each_domain(this_cpu, sd) {
		if (cpu_isset(prev_cpu, sd->span)) {
			this_sd = sd;
			break;
		}
	}

	if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
		goto out;

	/*
	 * Check for affine wakeup and passive balancing possibilities.
	 */
	if (!this_sd)
		goto out;

	idx = this_sd->wake_idx;

	imbalance = 100 + (this_sd->imbalance_pct - 100) / 2;

	load = source_load(prev_cpu, idx);
	this_load = target_load(this_cpu, idx);

	if (wake_affine(rq, this_sd, this_rq, p, prev_cpu, this_cpu, sync, idx,
				     load, this_load, imbalance))
		return this_cpu;

	if (prev_cpu == this_cpu)
		goto out;

	/*
	 * Start passive balancing when half the imbalance_pct
	 * limit is reached.
@@ -1063,13 +1106,11 @@ static int select_task_rq_fair(struct task_struct *p, int sync)
		if (imbalance*this_load <= 100*load) {
			schedstat_inc(this_sd, ttwu_move_balance);
			schedstat_inc(p, se.nr_wakeups_passive);
				goto out_set_cpu;
			}
			return this_cpu;
		}
	}

	new_cpu = cpu; /* Could not wake to this_cpu. Wake to cpu instead */
out_set_cpu:
out:
	return wake_idle(new_cpu, p);
}
#endif /* CONFIG_SMP */
@@ -1092,6 +1133,10 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
		return;
	}

	se->last_wakeup = se->sum_exec_runtime;
	if (unlikely(se == pse))
		return;

	cfs_rq_of(pse)->next = pse;

	/*
Loading