aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/sched/core.c34
-rw-r--r--kernel/sched/fair.c24
-rw-r--r--kernel/sched/sched.h42
3 files changed, 70 insertions, 30 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index cdf51a2adc26..dba878c73a08 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1511,6 +1511,11 @@ static int ttwu_activate_remote(struct task_struct *p, int wake_flags)
1511 1511
1512} 1512}
1513#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ 1513#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
1514
1515static inline int ttwu_share_cache(int this_cpu, int that_cpu)
1516{
1517 return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu);
1518}
1514#endif /* CONFIG_SMP */ 1519#endif /* CONFIG_SMP */
1515 1520
1516static void ttwu_queue(struct task_struct *p, int cpu) 1521static void ttwu_queue(struct task_struct *p, int cpu)
@@ -1518,7 +1523,7 @@ static void ttwu_queue(struct task_struct *p, int cpu)
1518 struct rq *rq = cpu_rq(cpu); 1523 struct rq *rq = cpu_rq(cpu);
1519 1524
1520#if defined(CONFIG_SMP) 1525#if defined(CONFIG_SMP)
1521 if (sched_feat(TTWU_QUEUE) && cpu != smp_processor_id()) { 1526 if (sched_feat(TTWU_QUEUE) && !ttwu_share_cache(smp_processor_id(), cpu)) {
1522 sched_clock_cpu(cpu); /* sync clocks x-cpu */ 1527 sched_clock_cpu(cpu); /* sync clocks x-cpu */
1523 ttwu_queue_remote(p, cpu); 1528 ttwu_queue_remote(p, cpu);
1524 return; 1529 return;
@@ -5744,6 +5749,31 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu)
5744} 5749}
5745 5750
5746/* 5751/*
5752 * Keep a special pointer to the highest sched_domain that has
5753 * SD_SHARE_PKG_RESOURCE set (Last Level Cache Domain) for this
5754 * allows us to avoid some pointer chasing select_idle_sibling().
5755 *
5756 * Also keep a unique ID per domain (we use the first cpu number in
5757 * the cpumask of the domain), this allows us to quickly tell if
5758 * two cpus are in the same cache domain, see ttwu_share_cache().
5759 */
5760DEFINE_PER_CPU(struct sched_domain *, sd_llc);
5761DEFINE_PER_CPU(int, sd_llc_id);
5762
5763static void update_top_cache_domain(int cpu)
5764{
5765 struct sched_domain *sd;
5766 int id = cpu;
5767
5768 sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES);
5769 if (sd)
5770 id = cpumask_first(sched_domain_span(sd));
5771
5772 rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
5773 per_cpu(sd_llc_id, cpu) = id;
5774}
5775
5776/*
5747 * Attach the domain 'sd' to 'cpu' as its base domain. Callers must 5777 * Attach the domain 'sd' to 'cpu' as its base domain. Callers must
5748 * hold the hotplug lock. 5778 * hold the hotplug lock.
5749 */ 5779 */
@@ -5782,6 +5812,8 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
5782 tmp = rq->sd; 5812 tmp = rq->sd;
5783 rcu_assign_pointer(rq->sd, sd); 5813 rcu_assign_pointer(rq->sd, sd);
5784 destroy_sched_domains(tmp, cpu); 5814 destroy_sched_domains(tmp, cpu);
5815
5816 update_top_cache_domain(cpu);
5785} 5817}
5786 5818
5787/* cpus with isolated domains */ 5819/* cpus with isolated domains */
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index a4d2b7abc3cd..2237ffefdbce 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2644,28 +2644,6 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
2644 return idlest; 2644 return idlest;
2645} 2645}
2646 2646
2647/**
2648 * highest_flag_domain - Return highest sched_domain containing flag.
2649 * @cpu: The cpu whose highest level of sched domain is to
2650 * be returned.
2651 * @flag: The flag to check for the highest sched_domain
2652 * for the given cpu.
2653 *
2654 * Returns the highest sched_domain of a cpu which contains the given flag.
2655 */
2656static inline struct sched_domain *highest_flag_domain(int cpu, int flag)
2657{
2658 struct sched_domain *sd, *hsd = NULL;
2659
2660 for_each_domain(cpu, sd) {
2661 if (!(sd->flags & flag))
2662 break;
2663 hsd = sd;
2664 }
2665
2666 return hsd;
2667}
2668
2669/* 2647/*
2670 * Try and locate an idle CPU in the sched_domain. 2648 * Try and locate an idle CPU in the sched_domain.
2671 */ 2649 */
@@ -2696,7 +2674,7 @@ static int select_idle_sibling(struct task_struct *p, int target)
2696 */ 2674 */
2697 rcu_read_lock(); 2675 rcu_read_lock();
2698 2676
2699 sd = highest_flag_domain(target, SD_SHARE_PKG_RESOURCES); 2677 sd = rcu_dereference(per_cpu(sd_llc, target));
2700 for_each_lower_domain(sd) { 2678 for_each_lower_domain(sd) {
2701 sg = sd->groups; 2679 sg = sd->groups;
2702 do { 2680 do {
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index d8d3613a4055..98c0c2623db8 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -487,6 +487,14 @@ static inline int cpu_of(struct rq *rq)
487 487
488DECLARE_PER_CPU(struct rq, runqueues); 488DECLARE_PER_CPU(struct rq, runqueues);
489 489
490#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu)))
491#define this_rq() (&__get_cpu_var(runqueues))
492#define task_rq(p) cpu_rq(task_cpu(p))
493#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
494#define raw_rq() (&__raw_get_cpu_var(runqueues))
495
496#ifdef CONFIG_SMP
497
490#define rcu_dereference_check_sched_domain(p) \ 498#define rcu_dereference_check_sched_domain(p) \
491 rcu_dereference_check((p), \ 499 rcu_dereference_check((p), \
492 lockdep_is_held(&sched_domains_mutex)) 500 lockdep_is_held(&sched_domains_mutex))
@@ -499,15 +507,37 @@ DECLARE_PER_CPU(struct rq, runqueues);
499 * preempt-disabled sections. 507 * preempt-disabled sections.
500 */ 508 */
501#define for_each_domain(cpu, __sd) \ 509#define for_each_domain(cpu, __sd) \
502 for (__sd = rcu_dereference_check_sched_domain(cpu_rq(cpu)->sd); __sd; __sd = __sd->parent) 510 for (__sd = rcu_dereference_check_sched_domain(cpu_rq(cpu)->sd); \
511 __sd; __sd = __sd->parent)
503 512
504#define for_each_lower_domain(sd) for (; sd; sd = sd->child) 513#define for_each_lower_domain(sd) for (; sd; sd = sd->child)
505 514
506#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) 515/**
507#define this_rq() (&__get_cpu_var(runqueues)) 516 * highest_flag_domain - Return highest sched_domain containing flag.
508#define task_rq(p) cpu_rq(task_cpu(p)) 517 * @cpu: The cpu whose highest level of sched domain is to
509#define cpu_curr(cpu) (cpu_rq(cpu)->curr) 518 * be returned.
510#define raw_rq() (&__raw_get_cpu_var(runqueues)) 519 * @flag: The flag to check for the highest sched_domain
520 * for the given cpu.
521 *
522 * Returns the highest sched_domain of a cpu which contains the given flag.
523 */
524static inline struct sched_domain *highest_flag_domain(int cpu, int flag)
525{
526 struct sched_domain *sd, *hsd = NULL;
527
528 for_each_domain(cpu, sd) {
529 if (!(sd->flags & flag))
530 break;
531 hsd = sd;
532 }
533
534 return hsd;
535}
536
537DECLARE_PER_CPU(struct sched_domain *, sd_llc);
538DECLARE_PER_CPU(int, sd_llc_id);
539
540#endif /* CONFIG_SMP */
511 541
512#include "stats.h" 542#include "stats.h"
513#include "auto_group.h" 543#include "auto_group.h"