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

[PATCH] mm: tlb_gather_mmu get_cpu_var

tlb_gather_mmu dates from before kernel preemption was allowed, and uses
smp_processor_id or __get_cpu_var to find its per-cpu mmu_gather. That works
because it's currently only called after getting page_table_lock, which is not
dropped until after the matching tlb_finish_mmu. But don't rely on that, it
will soon change: now disable preemption internally by proper get_cpu_var in
tlb_gather_mmu, put_cpu_var in tlb_finish_mmu.

Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Hugh Dickins and committed by
Linus Torvalds
15a23ffa 7be7a546

+19 -13
+3 -2
include/asm-arm/tlb.h
··· 39 39 static inline struct mmu_gather * 40 40 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) 41 41 { 42 - int cpu = smp_processor_id(); 43 - struct mmu_gather *tlb = &per_cpu(mmu_gathers, cpu); 42 + struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); 44 43 45 44 tlb->mm = mm; 46 45 tlb->freed = 0; ··· 64 65 65 66 /* keep the page table cache within bounds */ 66 67 check_pgt_cache(); 68 + 69 + put_cpu_var(mmu_gathers); 67 70 } 68 71 69 72 static inline unsigned int tlb_is_full_mm(struct mmu_gather *tlb)
+4 -3
include/asm-arm26/tlb.h
··· 17 17 unsigned int avoided_flushes; 18 18 }; 19 19 20 - extern struct mmu_gather mmu_gathers[NR_CPUS]; 20 + DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); 21 21 22 22 static inline struct mmu_gather * 23 23 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) 24 24 { 25 - int cpu = smp_processor_id(); 26 - struct mmu_gather *tlb = &mmu_gathers[cpu]; 25 + struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); 27 26 28 27 tlb->mm = mm; 29 28 tlb->freed = 0; ··· 51 52 52 53 /* keep the page table cache within bounds */ 53 54 check_pgt_cache(); 55 + 56 + put_cpu_var(mmu_gathers); 54 57 } 55 58 56 59
+5 -5
include/asm-generic/tlb.h
··· 35 35 #endif 36 36 37 37 /* struct mmu_gather is an opaque type used by the mm code for passing around 38 - * any data needed by arch specific code for tlb_remove_page. This structure 39 - * can be per-CPU or per-MM as the page table lock is held for the duration of 40 - * TLB shootdown. 38 + * any data needed by arch specific code for tlb_remove_page. 41 39 */ 42 40 struct mmu_gather { 43 41 struct mm_struct *mm; ··· 55 57 static inline struct mmu_gather * 56 58 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) 57 59 { 58 - struct mmu_gather *tlb = &per_cpu(mmu_gathers, smp_processor_id()); 60 + struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); 59 61 60 62 tlb->mm = mm; 61 63 ··· 83 85 84 86 /* tlb_finish_mmu 85 87 * Called at the end of the shootdown operation to free up any resources 86 - * that were required. The page table lock is still held at this point. 88 + * that were required. 87 89 */ 88 90 static inline void 89 91 tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) ··· 99 101 100 102 /* keep the page table cache within bounds */ 101 103 check_pgt_cache(); 104 + 105 + put_cpu_var(mmu_gathers); 102 106 } 103 107 104 108 static inline unsigned int
+4 -2
include/asm-ia64/tlb.h
··· 129 129 static inline struct mmu_gather * 130 130 tlb_gather_mmu (struct mm_struct *mm, unsigned int full_mm_flush) 131 131 { 132 - struct mmu_gather *tlb = &__get_cpu_var(mmu_gathers); 132 + struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); 133 133 134 134 tlb->mm = mm; 135 135 /* ··· 154 154 155 155 /* 156 156 * Called at the end of the shootdown operation to free up any resources that were 157 - * collected. The page table lock is still held at this point. 157 + * collected. 158 158 */ 159 159 static inline void 160 160 tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end) ··· 174 174 175 175 /* keep the page table cache within bounds */ 176 176 check_pgt_cache(); 177 + 178 + put_cpu_var(mmu_gathers); 177 179 } 178 180 179 181 static inline unsigned int
+3 -1
include/asm-sparc64/tlb.h
··· 44 44 45 45 static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) 46 46 { 47 - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); 47 + struct mmu_gather *mp = &get_cpu_var(mmu_gathers); 48 48 49 49 BUG_ON(mp->tlb_nr); 50 50 ··· 97 97 98 98 /* keep the page table cache within bounds */ 99 99 check_pgt_cache(); 100 + 101 + put_cpu_var(mmu_gathers); 100 102 } 101 103 102 104 static inline unsigned int tlb_is_full_mm(struct mmu_gather *mp)