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

Commit 3dbd5342 authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds
Browse files

[PATCH] sched: multilevel sbe sbf



The fundamental problem that Suresh has with balance on exec and fork is that
it only tries to balance the top level domain with the flag set.

This was worked around by removing degenerate domains, but is still a problem
if people want to start using more complex sched-domains, especially
multilevel NUMA that ia64 is already using.

This patch makes balance on fork and exec try balancing over not just the top
most domain with the flag set, but all the way down the domain tree.

Signed-off-by: default avatarNick Piggin <nickpiggin@yahoo.com.au>
Acked-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 245af2c7
Loading
Loading
Loading
Loading
+38 −7
Original line number Original line Diff line number Diff line
@@ -1319,21 +1319,24 @@ void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
			sd = tmp;
			sd = tmp;


	if (sd) {
	if (sd) {
		cpumask_t span;
		int new_cpu;
		int new_cpu;
		struct sched_group *group;
		struct sched_group *group;


again:
		schedstat_inc(sd, sbf_cnt);
		schedstat_inc(sd, sbf_cnt);
		span = sd->span;
		cpu = task_cpu(p);
		cpu = task_cpu(p);
		group = find_idlest_group(sd, p, cpu);
		group = find_idlest_group(sd, p, cpu);
		if (!group) {
		if (!group) {
			schedstat_inc(sd, sbf_balanced);
			schedstat_inc(sd, sbf_balanced);
			goto no_forkbalance;
			goto nextlevel;
		}
		}


		new_cpu = find_idlest_cpu(group, cpu);
		new_cpu = find_idlest_cpu(group, cpu);
		if (new_cpu == -1 || new_cpu == cpu) {
		if (new_cpu == -1 || new_cpu == cpu) {
			schedstat_inc(sd, sbf_balanced);
			schedstat_inc(sd, sbf_balanced);
			goto no_forkbalance;
			goto nextlevel;
		}
		}


		if (cpu_isset(new_cpu, p->cpus_allowed)) {
		if (cpu_isset(new_cpu, p->cpus_allowed)) {
@@ -1343,9 +1346,21 @@ void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
			rq = task_rq_lock(p, &flags);
			rq = task_rq_lock(p, &flags);
			cpu = task_cpu(p);
			cpu = task_cpu(p);
		}
		}

		/* Now try balancing at a lower domain level */
nextlevel:
		sd = NULL;
		for_each_domain(cpu, tmp) {
			if (cpus_subset(span, tmp->span))
				break;
			if (tmp->flags & SD_BALANCE_FORK)
				sd = tmp;
		}

		if (sd)
			goto again;
	}
	}


no_forkbalance:
#endif
#endif
	/*
	/*
	 * We decrease the sleep average of forking parents
	 * We decrease the sleep average of forking parents
@@ -1711,25 +1726,41 @@ void sched_exec(void)
			sd = tmp;
			sd = tmp;


	if (sd) {
	if (sd) {
		cpumask_t span;
		struct sched_group *group;
		struct sched_group *group;
again:
		schedstat_inc(sd, sbe_cnt);
		schedstat_inc(sd, sbe_cnt);
		span = sd->span;
		group = find_idlest_group(sd, current, this_cpu);
		group = find_idlest_group(sd, current, this_cpu);
		if (!group) {
		if (!group) {
			schedstat_inc(sd, sbe_balanced);
			schedstat_inc(sd, sbe_balanced);
			goto out;
			goto nextlevel;
		}
		}
		new_cpu = find_idlest_cpu(group, this_cpu);
		new_cpu = find_idlest_cpu(group, this_cpu);
		if (new_cpu == -1 || new_cpu == this_cpu) {
		if (new_cpu == -1 || new_cpu == this_cpu) {
			schedstat_inc(sd, sbe_balanced);
			schedstat_inc(sd, sbe_balanced);
			goto out;
			goto nextlevel;
		}
		}


		schedstat_inc(sd, sbe_pushed);
		schedstat_inc(sd, sbe_pushed);
		put_cpu();
		put_cpu();
		sched_migrate_task(current, new_cpu);
		sched_migrate_task(current, new_cpu);
		return;

		/* Now try balancing at a lower domain level */
		this_cpu = get_cpu();
nextlevel:
		sd = NULL;
		for_each_domain(this_cpu, tmp) {
			if (cpus_subset(span, tmp->span))
				break;
			if (tmp->flags & SD_BALANCE_EXEC)
				sd = tmp;
		}
		}
out:

		if (sd)
			goto again;
	}

	put_cpu();
	put_cpu();
}
}