Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sched, block: Unify cache detection

The block layer has some code trying to determine if two CPUs share a
cache, the scheduler has a similar function. Expose the function used
by the scheduler and make the block layer use it, thereby removing the
block layers usage of CONFIG_SCHED* and topology bits.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Jens Axboe <axboe@kernel.dk>
Link: http://lkml.kernel.org/r/1327579450.2446.95.camel@twins

authored by

Peter Zijlstra and committed by
Ingo Molnar
39be3501 cb297a3e

+19 -27
+8 -8
block/blk-softirq.c
··· 8 8 #include <linux/blkdev.h> 9 9 #include <linux/interrupt.h> 10 10 #include <linux/cpu.h> 11 + #include <linux/sched.h> 11 12 12 13 #include "blk.h" 13 14 ··· 104 103 105 104 void __blk_complete_request(struct request *req) 106 105 { 107 - int ccpu, cpu, group_cpu = NR_CPUS; 106 + int ccpu, cpu; 108 107 struct request_queue *q = req->q; 109 108 unsigned long flags; 109 + bool shared = false; 110 110 111 111 BUG_ON(!q->softirq_done_fn); 112 112 ··· 119 117 */ 120 118 if (req->cpu != -1) { 121 119 ccpu = req->cpu; 122 - if (!test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags)) { 123 - ccpu = blk_cpu_to_group(ccpu); 124 - group_cpu = blk_cpu_to_group(cpu); 125 - } 120 + if (!test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags)) 121 + shared = cpus_share_cache(cpu, ccpu); 126 122 } else 127 123 ccpu = cpu; 128 124 129 125 /* 130 - * If current CPU and requested CPU are in the same group, running 131 - * softirq in current CPU. One might concern this is just like 126 + * If current CPU and requested CPU share a cache, run the softirq on 127 + * the current CPU. One might concern this is just like 132 128 * QUEUE_FLAG_SAME_FORCE, but actually not. blk_complete_request() is 133 129 * running in interrupt handler, and currently I/O controller doesn't 134 130 * support multiple interrupts, so current CPU is unique actually. This 135 131 * avoids IPI sending from current CPU to the first CPU of a group. 136 132 */ 137 - if (ccpu == cpu || ccpu == group_cpu) { 133 + if (ccpu == cpu || shared) { 138 134 struct list_head *list; 139 135 do_local: 140 136 list = &__get_cpu_var(blk_cpu_done);
-16
block/blk.h
··· 164 164 return q->nr_congestion_off; 165 165 } 166 166 167 - static inline int blk_cpu_to_group(int cpu) 168 - { 169 - int group = NR_CPUS; 170 - #ifdef CONFIG_SCHED_MC 171 - const struct cpumask *mask = cpu_coregroup_mask(cpu); 172 - group = cpumask_first(mask); 173 - #elif defined(CONFIG_SCHED_SMT) 174 - group = cpumask_first(topology_thread_cpumask(cpu)); 175 - #else 176 - return cpu; 177 - #endif 178 - if (likely(group < NR_CPUS)) 179 - return group; 180 - return cpu; 181 - } 182 - 183 167 /* 184 168 * Contribute to IO statistics IFF: 185 169 *
+8
include/linux/sched.h
··· 1052 1052 unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu); 1053 1053 unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu); 1054 1054 1055 + bool cpus_share_cache(int this_cpu, int that_cpu); 1056 + 1055 1057 #else /* CONFIG_SMP */ 1056 1058 1057 1059 struct sched_domain_attr; ··· 1063 1061 struct sched_domain_attr *dattr_new) 1064 1062 { 1065 1063 } 1064 + 1065 + static inline bool cpus_share_cache(int this_cpu, int that_cpu) 1066 + { 1067 + return true; 1068 + } 1069 + 1066 1070 #endif /* !CONFIG_SMP */ 1067 1071 1068 1072
+3 -3
kernel/sched/core.c
··· 1507 1507 } 1508 1508 #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ 1509 1509 1510 - static inline int ttwu_share_cache(int this_cpu, int that_cpu) 1510 + bool cpus_share_cache(int this_cpu, int that_cpu) 1511 1511 { 1512 1512 return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu); 1513 1513 } ··· 1518 1518 struct rq *rq = cpu_rq(cpu); 1519 1519 1520 1520 #if defined(CONFIG_SMP) 1521 - if (sched_feat(TTWU_QUEUE) && !ttwu_share_cache(smp_processor_id(), cpu)) { 1521 + if (sched_feat(TTWU_QUEUE) && !cpus_share_cache(smp_processor_id(), cpu)) { 1522 1522 sched_clock_cpu(cpu); /* sync clocks x-cpu */ 1523 1523 ttwu_queue_remote(p, cpu); 1524 1524 return; ··· 5754 5754 * 5755 5755 * Also keep a unique ID per domain (we use the first cpu number in 5756 5756 * the cpumask of the domain), this allows us to quickly tell if 5757 - * two cpus are in the same cache domain, see ttwu_share_cache(). 5757 + * two cpus are in the same cache domain, see cpus_share_cache(). 5758 5758 */ 5759 5759 DEFINE_PER_CPU(struct sched_domain *, sd_llc); 5760 5760 DEFINE_PER_CPU(int, sd_llc_id);