diff options
-rw-r--r-- | kernel/sched/core.c | 34 | ||||
-rw-r--r-- | kernel/sched/fair.c | 24 | ||||
-rw-r--r-- | kernel/sched/sched.h | 42 |
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 | |||
1515 | static 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 | ||
1516 | static void ttwu_queue(struct task_struct *p, int cpu) | 1521 | static 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 | */ | ||
5760 | DEFINE_PER_CPU(struct sched_domain *, sd_llc); | ||
5761 | DEFINE_PER_CPU(int, sd_llc_id); | ||
5762 | |||
5763 | static 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 | */ | ||
2656 | static 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 | ||
488 | DECLARE_PER_CPU(struct rq, runqueues); | 488 | DECLARE_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 | */ | ||
524 | static 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 | |||
537 | DECLARE_PER_CPU(struct sched_domain *, sd_llc); | ||
538 | DECLARE_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" |