Upgrade of this_cpu_ops V3
Subsystems (30)
PATCH 11/18 x86: Use this_cpu_ops for current_cpu_data accesses
In reply to Christoph LameterCurrent_cpu_data accesses are per cpu accesses. We can also use this_cpu_ops if a scalar is retrieved.
--- arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 2 +- arch/x86/kernel/cpu/intel_cacheinfo.c | 4 ++-- arch/x86/kernel/smpboot.c | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-)
arch/x86/kernel/smpboot.c +4 -4
@@ -430,7 +430,7 @@ void __cpuinit set_cpu_sibling_map(int ccpumask_set_cpu (cpu, c->llc_shared_map); -if (current_cpu_data.x86_max_cores ==1 ) { +if (__this_cpu_read (cpu_info.x86_max_cores) ==1 ) {cpumask_copy (cpu_core_mask (cpu),cpu_sibling_mask (cpu)); c->booted_cores =1 ;return ;
@@ -1377,7 +1377,7 @@ void play_dead_common(void)mb ();/* Ack it */ -__get_cpu_var (cpu_state) =CPU_DEAD ; +__this_cpu_write (cpu_state,CPU_DEAD );/* * With physical CPU hotplug, we should halt the cpu
@@ -1401,7 +1401,7 @@ static inline void mwait_play_dead(void)return ;if (!cpu_has (¤t_cpu_data,X86_FEATURE_CLFLSH ))return ; -if (current_cpu_data.cpuid_level <CPUID_MWAIT_LEAF ) +if (__this_cpu_read (cpu_info.cpuid_level) <CPUID_MWAIT_LEAF )return ; eax =CPUID_MWAIT_LEAF ;
@@ -1452,7 +1452,7 @@ static inline void mwait_play_dead(void)static inline void hlt_play_dead (void ) { -if (current_cpu_data.x86 >=4 ) +if (__this_cpu_read (cpu_info.x86) >=4 )wbinvd ();while (1 ) {
arch/x86/kernel/cpu/cpufreq/powernow-k8.c +1 -1
@@ -521,7 +521,7 @@ static void check_supported_cpu(void *_r *rc = -ENODEV ; -if (current_cpu_data.x86_vendor !=X86_VENDOR_AMD ) +if (__this_cpu_read (cpu_info.x86_vendor) !=X86_VENDOR_AMD )return ; eax =cpuid_eax (CPUID_PROCESSOR_SIGNATURE );
arch/x86/kernel/cpu/intel_cacheinfo.c +2 -2
@@ -266,7 +266,7 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_ line_size = l2.line_size; lines_per_tag = l2.lines_per_tag;/* cpu_data has errata corrections for K7 applied */ - size_in_kb = current_cpu_data.x86_cache_size; + size_in_kb =__this_cpu_read (cpu_info.x86_cache_size);break ;case 3 :if (!l3.val)
@@ -288,7 +288,7 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_ eax->split.type = types[leaf]; eax->split.level = levels[leaf]; eax->split.num_threads_sharing =0 ; - eax->split.num_cores_on_die = current_cpu_data.x86_max_cores -1 ; + eax->split.num_cores_on_die =__this_cpu_read (cpu_info.x86_max_cores) -1 ;if (assoc ==0xffff )
PATCH 18/18 Fakekey: Simplify speakup_fake_key_pressed through this_cpu_ops
In reply to Christoph LameterThe whole function can be expressed as a simple this_cpu_read() operation. The function overhead is now likely multiple times that of the single instruction that is executed in it.
--- drivers/staging/speakup/fakekey.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/staging/speakup/fakekey.c +1 -6
@@ -96,10 +96,5 @@ void speakup_fake_down_arrow(void)*/ bool speakup_fake_key_pressed (void ) { -bool is_pressed; - - is_pressed =get_cpu_var (reporting_keystroke); -put_cpu_var (reporting_keystroke); - -return is_pressed; +return this_cpu_read (reporting_keystroke); }
cover Upgrade of this_cpu_ops V3
A patchset that adds more this_cpu operations and in particular RMV operations that can be used in various places to avoid address calculations and memory accesses by the user of fast cpu local operations with segment prefixes.
V2 has several enhancements and bugfixes that were suggested after V1
V3 removes the cmpxchg patches and focuses on the first extensions of cpu ops that were generally an improvement.
For V3 I scanned through the kernel code for obvious cases in which a __get_cpu_var or get_cpu_var can be converted to this_cpu_ops. That is often not possible because addresses of per cpu variables are needed. However, the accesses that could become converted became very cheap because this_cpu_ops typically only generate a single instruction using a segment prefix to perform the relocation to the correct per cpu area.
Cpu ops perform implied address calculations. It is therefore not possible to take the address of the result of a this_cpu_xx operation.
PATCH 3/18 percpu: Generic support for this_cpu_add,sub,dec,inc_return
Introduce generic support for this_cpu_add_return etc.
The fallback is to realize these operations with simpler __this_cpu_ops.
--- include/linux/percpu.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+)
include/linux/percpu.h +77 -0
@@ -240,6 +240,25 @@ extern void __bad_size_call_parameter(vo pscr_ret__; \ }) +#define __pcpu_size_call_return2 (stem, pcp, ...) \ +({ \ + typeof(pcp) ret__; \ + __verify_pcpu_ptr(&(pcp)); \ + switch(sizeof(pcp)) { \ + case 1: ret__ = stem##1(pcp, __VA_ARGS__); \ + break; \ + case 2: ret__ = stem##2(pcp, __VA_ARGS__); \ + break; \ + case 4: ret__ = stem##4(pcp, __VA_ARGS__); \ + break; \ + case 8: ret__ = stem##8(pcp, __VA_ARGS__); \ + break; \ + default: \ + __bad_size_call_parameter();break; \ + } \ + ret__; \ +}) +#define __pcpu_size_call (stem, variable, ...) \ do { \ __verify_pcpu_ptr(&(variable)); \
@@ -529,6 +548,64 @@ do { \# define __this_cpu_xor (pcp, val) __pcpu_size_call(__this_cpu_xor_, (pcp), (val))#endif +#define _this_cpu_generic_add_return (pcp, val) \ +({ \ + typeof(pcp) ret__; \ + preempt_disable(); \ + __this_cpu_add(pcp, val); \ + ret__ = __this_cpu_read(pcp); \ + preempt_enable(); \ + ret__; \ +}) + +#ifndef this_cpu_add_return +# ifndef this_cpu_add_return_1 +# define this_cpu_add_return_1 (pcp, val) _this_cpu_generic_add_return(pcp, val) +# endif +# ifndef this_cpu_add_return_2 +# define this_cpu_add_return_2 (pcp, val) _this_cpu_generic_add_return(pcp, val) +# endif +# ifndef this_cpu_add_return_4 +# define this_cpu_add_return_4 (pcp, val) _this_cpu_generic_add_return(pcp, val) +# endif +# ifndef this_cpu_add_return_8 +# define this_cpu_add_return_8 (pcp, val) _this_cpu_generic_add_return(pcp, val) +# endif +# define this_cpu_add_return (pcp, val) __pcpu_size_call_return2(this_cpu_add_return_, pcp, val) +#endif + +#define this_cpu_sub_return (pcp, val) this_cpu_add_return(pcp, -(val)) +#define this_cpu_inc_return (pcp) this_cpu_add_return(pcp, 1) +#define this_cpu_dec_return (pcp) this_cpu_add_return(pcp, -1) + +#define __this_cpu_generic_add_return (pcp, val) \ +({ \ + typeof(pcp) ret__; \ + __this_cpu_add(pcp, val); \ + ret__ = __this_cpu_read(pcp); \ + ret__; \ +}) + +#ifndef __this_cpu_add_return +# ifndef __this_cpu_add_return_1 +# define __this_cpu_add_return_1 (pcp, val) __this_cpu_generic_add_return(pcp, val) +# endif +# ifndef __this_cpu_add_return_2 +# define __this_cpu_add_return_2 (pcp, val) __this_cpu_generic_add_return(pcp, val) +# endif +# ifndef __this_cpu_add_return_4 +# define __this_cpu_add_return_4 (pcp, val) __this_cpu_generic_add_return(pcp, val) +# endif +# ifndef __this_cpu_add_return_8 +# define __this_cpu_add_return_8 (pcp, val) __this_cpu_generic_add_return(pcp, val) +# endif +# define __this_cpu_add_return (pcp, val) __pcpu_size_call_return2(this_cpu_add_return_, pcp, val) +#endif + +#define __this_cpu_sub_return (pcp, val) this_cpu_add_return(pcp, -(val)) +#define __this_cpu_inc_return (pcp) this_cpu_add_return(pcp, 1) +#define __this_cpu_dec_return (pcp) this_cpu_add_return(pcp, -1) +/* * IRQ safe versions of the per cpu RMW operations. Note that these operations * are *not* safe against modification of the same variable from another
PATCH 1/18 percpucounter: Optimize __percpu_counter_add a bit through the use of this_cpu() options.
In reply to Christoph LameterThe this_cpu_* options can be used to optimize __percpu_counter_add a bit. Avoids some address arithmetic and saves 12 bytes.
Before:
00000000000001d3 <__percpu_counter_add>:
1d3: 55 push %rbp 1d4: 48 89 e5 mov %rsp,%rbp 1d7: 41 55 push %r13 1d9: 41 54 push %r12 1db: 53 push %rbx 1dc: 48 89 fb mov %rdi,%rbx 1df: 48 83 ec 08 sub $0x8,%rsp 1e3: 4c 8b 67 30 mov 0x30(%rdi),%r12 1e7: 65 4c 03 24 25 00 00 add %gs:0x0,%r12 1ee: 00 00 1f0: 4d 63 2c 24 movslq (%r12),%r13 1f4: 48 63 c2 movslq %edx,%rax 1f7: 49 01 f5 add %rsi,%r13 1fa: 49 39 c5 cmp %rax,%r13 1fd: 7d 0a jge 209 <__percpu_counter_add+0x36> 1ff: f7 da neg %edx 201: 48 63 d2 movslq %edx,%rdx 204: 49 39 d5 cmp %rdx,%r13 207: 7f 1e jg 227 <__percpu_counter_add+0x54> 209: 48 89 df mov %rbx,%rdi 20c: e8 00 00 00 00 callq 211 <__percpu_counter_add+0x3e> 211: 4c 01 6b 18 add %r13,0x18(%rbx) 215: 48 89 df mov %rbx,%rdi 218: 41 c7 04 24 00 00 00 movl $0x0,(%r12) 21f: 00 220: e8 00 00 00 00 callq 225 <__percpu_counter_add+0x52> 225: eb 04 jmp 22b <__percpu_counter_add+0x58> 227: 45 89 2c 24 mov %r13d,(%r12) 22b: 5b pop %rbx 22c: 5b pop %rbx 22d: 41 5c pop %r12 22f: 41 5d pop %r13 231: c9 leaveq 232: c3 retq
After:
00000000000001d3 <__percpu_counter_add>:
1d3: 55 push %rbp 1d4: 48 63 ca movslq %edx,%rcx 1d7: 48 89 e5 mov %rsp,%rbp 1da: 41 54 push %r12 1dc: 53 push %rbx 1dd: 48 89 fb mov %rdi,%rbx 1e0: 48 8b 47 30 mov 0x30(%rdi),%rax 1e4: 65 44 8b 20 mov %gs:(%rax),%r12d 1e8: 4d 63 e4 movslq %r12d,%r12 1eb: 49 01 f4 add %rsi,%r12 1ee: 49 39 cc cmp %rcx,%r12 1f1: 7d 0a jge 1fd <__percpu_counter_add+0x2a> 1f3: f7 da neg %edx 1f5: 48 63 d2 movslq %edx,%rdx 1f8: 49 39 d4 cmp %rdx,%r12 1fb: 7f 21 jg 21e <__percpu_counter_add+0x4b> 1fd: 48 89 df mov %rbx,%rdi 200: e8 00 00 00 00 callq 205 <__percpu_counter_add+0x32> 205: 4c 01 63 18 add %r12,0x18(%rbx) 209: 48 8b 43 30 mov 0x30(%rbx),%rax 20d: 48 89 df mov %rbx,%rdi 210: 65 c7 00 00 00 00 00 movl $0x0,%gs:(%rax) 217: e8 00 00 00 00 callq 21c <__percpu_counter_add+0x49> 21c: eb 04 jmp 222 <__percpu_counter_add+0x4f> 21e: 65 44 89 20 mov %r12d,%gs:(%rax) 222: 5b pop %rbx 223: 41 5c pop %r12
225: c9 leaveq
226: c3 retq
--- lib/percpu_counter.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
lib/percpu_counter.c +3 -5
@@ -72,18 +72,16 @@ EXPORT_SYMBOL(percpu_counter_set);void __percpu_counter_add (struct percpu_counter *fbc,s64 amount,s32 batch) {s64 count; -s32 *pcount;preempt_disable (); - pcount =this_cpu_ptr (fbc->counters); - count = *pcount + amount; + count =__this_cpu_read (*fbc->counters) + amount;if (count >= batch || count <= -batch) {spin_lock (&fbc->lock); fbc->count += count; - *pcount =0 ; +__this_cpu_write (*fbc->counters,0 );spin_unlock (&fbc->lock); }else { - *pcount = count; +__this_cpu_write (*fbc->counters, count); }preempt_enable (); }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 2/18 vmstat: Optimize zone counter modifications through the use of this cpu operations
In reply to Christoph Lameterthis cpu operations can be used to slightly optimize the function. The changes will avoid some address calculations and replace them with the use of the percpu segment register.
If one would have this_cpu_inc_return and this_cpu_dec_return then it would be possible to optimize inc_zone_page_state and dec_zone_page_state even more.
V1->V2:
- Fix __dec_zone_state overflow handling
- Use s8 variables for temporary storage.
V2->V3:
- Put __percpu annotations in correct places.
--- mm/vmstat.c | 56 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 24 deletions(-)
mm/vmstat.c +32 -24
@@ -167,18 +167,20 @@ static void refresh_zone_stat_thresholdsvoid __mod_zone_page_state (struct zone *zone,enum zone_stat_item item,int delta) { -struct per_cpu_pageset *pcp =this_cpu_ptr (zone->pageset); - -s8 *p = pcp->vm_stat_diff + item; +struct per_cpu_pageset __percpu *pcp = zone->pageset; +s8 __percpu *p = pcp->vm_stat_diff + item;long x; +long t; + + x = delta +__this_cpu_read (*p); - x = delta + *p; + t =__this_cpu_read (pcp->stat_threshold); -if (unlikely (x > pcp->stat_threshold || x < -pcp->stat_threshold)) { +if (unlikely (x > t || x < -t)) {zone_page_state_add (x, zone, item); x =0 ; } - *p = x; +__this_cpu_write (*p, x); }EXPORT_SYMBOL (__mod_zone_page_state);
@@ -221,16 +223,19 @@ EXPORT_SYMBOL(mod_zone_page_state);*/ void __inc_zone_state (struct zone *zone,enum zone_stat_item item) { -struct per_cpu_pageset *pcp =this_cpu_ptr (zone->pageset); -s8 *p = pcp->vm_stat_diff + item; - - (*p)++; +struct per_cpu_pageset __percpu *pcp = zone->pageset; +s8 __percpu *p = pcp->vm_stat_diff + item; +s8 v, t; + +__this_cpu_inc (*p); + + v =__this_cpu_read (*p); + t =__this_cpu_read (pcp->stat_threshold); +if (unlikely (v > t)) { +s8 overstep = t >>1 ; -if (unlikely (*p > pcp->stat_threshold)) { -int overstep = pcp->stat_threshold /2 ; - -zone_page_state_add (*p + overstep, zone, item); - *p = -overstep; +zone_page_state_add (v + overstep, zone, item); +__this_cpu_write (*p, - overstep); } }
@@ -242,16 +247,19 @@ EXPORT_SYMBOL(__inc_zone_page_state);void __dec_zone_state (struct zone *zone,enum zone_stat_item item) { -struct per_cpu_pageset *pcp =this_cpu_ptr (zone->pageset); -s8 *p = pcp->vm_stat_diff + item; - - (*p)--; - -if (unlikely (*p < - pcp->stat_threshold)) { -int overstep = pcp->stat_threshold /2 ; +struct per_cpu_pageset __percpu *pcp = zone->pageset; +s8 __percpu *p = pcp->vm_stat_diff + item; +s8 v, t; + +__this_cpu_dec (*p); + + v =__this_cpu_read (*p); + t =__this_cpu_read (pcp->stat_threshold); +if (unlikely (v < - t)) { +s8 overstep = t >>1 ; -zone_page_state_add (*p - overstep, zone, item); - *p = overstep; +zone_page_state_add (v - overstep, zone, item); +__this_cpu_write (*p, overstep); } }
PATCH 9/18 fs: Use this_cpu_xx operations in buffer.c
In reply to Christoph LameterOptimize various per cpu area operations through the new this cpu operations. These operations avoid address calculations through the use of segment prefixes avoid multiple memory references through RMW instructions etc.
Reduces code size:
Before:
[email protected]$ size fs/buffer.o text data bss dec hex filename 19169 80 28 19277 4b4d fs/buffer.o
After:
[email protected]$ size fs/buffer.o text data bss dec hex filename 19138 80 28 19246 4b2e fs/buffer.o
--- fs/buffer.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-)
fs/buffer.c +18 -19
@@ -1270,12 +1270,10 @@ static inline void check_irqs_on(void)static void bh_lru_install (struct buffer_head *bh) {struct buffer_head *evictee =NULL ; -struct bh_lru *lru;check_irqs_on ();bh_lru_lock (); - lru = &__get_cpu_var (bh_lrus); -if (lru->bhs[0 ] != bh) { +if (__this_cpu_read (bh_lrus.bhs[0 ]) != bh) {struct buffer_head *bhs[BH_LRU_SIZE ];int in;int out =0 ;
@@ -1283,7 +1281,8 @@ static void bh_lru_install(struct bufferget_bh (bh); bhs[out++] = bh;for (in =0 ; in <BH_LRU_SIZE ; in++) { -struct buffer_head *bh2 = lru->bhs[in]; +struct buffer_head *bh2 = +__this_cpu_read (bh_lrus.bhs[in]);if (bh2 == bh) {__brelse (bh2);
@@ -1298,7 +1297,7 @@ static void bh_lru_install(struct buffer }while (out <BH_LRU_SIZE ) bhs[out++] =NULL ; -memcpy (lru->bhs, bhs,sizeof (bhs)); +memcpy (__this_cpu_ptr (&bh_lrus.bhs), bhs,sizeof (bhs)); }bh_lru_unlock ();
@@ -1313,23 +1312,22 @@ static struct buffer_head * lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size) { struct buffer_head *ret = NULL; -struct bh_lru *lru;unsigned int i;check_irqs_on ();bh_lru_lock (); - lru = &__get_cpu_var (bh_lrus);for (i =0 ; i <BH_LRU_SIZE ; i++) { -struct buffer_head *bh = lru->bhs[i]; +struct buffer_head *bh =__this_cpu_read (bh_lrus.bhs[i]);if (bh && bh->b_bdev == bdev && bh->b_blocknr == block && bh->b_size == size) {if (i) {while (i) { - lru->bhs[i] = lru->bhs[i -1 ]; +__this_cpu_write (bh_lrus.bhs[i], +__this_cpu_read (bh_lrus.bhs[i -1 ])); i--; } - lru->bhs[0 ] = bh; +__this_cpu_write (bh_lrus.bhs[0 ], bh); }get_bh (bh); ret = bh;
@@ -3203,22 +3201,23 @@ static void recalc_bh_state(void)int i;int tot =0 ; -if (__get_cpu_var (bh_accounting).ratelimit++ <4096 ) +if (__this_cpu_inc_return (bh_accounting.ratelimit) <4096 )return ; -__get_cpu_var (bh_accounting).ratelimit =0 ; +__this_cpu_write (bh_accounting.ratelimit,0 );for_each_online_cpu (i) tot +=per_cpu (bh_accounting, i).nr; buffer_heads_over_limit = (tot > max_buffer_heads); } - +struct buffer_head *alloc_buffer_head (gfp_t gfp_flags) {struct buffer_head *ret =kmem_cache_zalloc (bh_cachep, gfp_flags);if (ret) {INIT_LIST_HEAD (&ret->b_assoc_buffers); -get_cpu_var (bh_accounting).nr++; +preempt_disable (); +__this_cpu_inc (bh_accounting.nr);recalc_bh_state (); -put_cpu_var (bh_accounting); +preempt_enable (); }return ret; }
@@ -3228,9 +3227,10 @@ void free_buffer_head(struct buffer_head {BUG_ON (!list_empty (&bh->b_assoc_buffers));kmem_cache_free (bh_cachep, bh); -get_cpu_var (bh_accounting).nr--; +preempt_disable (); +__this_cpu_dec (bh_accounting.nr);recalc_bh_state (); -put_cpu_var (bh_accounting); +preempt_enable (); }EXPORT_SYMBOL (free_buffer_head);
@@ -3243,9 +3243,8 @@ static void buffer_exit_cpu(int cpu)brelse (b->bhs[i]); b->bhs[i] =NULL ; } -get_cpu_var (bh_accounting).nr +=per_cpu (bh_accounting, cpu).nr; +this_cpu_add (bh_accounting.nr,per_cpu (bh_accounting, cpu).nr);per_cpu (bh_accounting, cpu).nr =0 ; -put_cpu_var (bh_accounting); } static int buffer_cpu_notify(struct notifier_block *self,
PATCH 4/18 x86: Support for this_cpu_add,sub,dec,inc_return
In reply to Christoph LameterSupply an implementation for x86 in order to generate more efficient code.
V2->V3:
- Cleanup
- Remove strange type checking from percpu_add_return_op.
--- arch/x86/include/asm/percpu.h | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
arch/x86/include/asm/percpu.h +46 -0
@@ -177,6 +177,41 @@ do { \ } \ }while (0 ) + +/* +* Add return operation + */ +#define percpu_add_return_op (var, val) \ +({ \ + typedef typeof(var) pao_T__; \ + typeof(var) ret__ = val; \ + switch (sizeof(var)) { \ + case 1: \ + asm("xaddb %0, "__percpu_arg(1) \ + : "+q" (ret__), "+m" (var) \ + : : "memory"); \ + break; \ + case 2: \ + asm("xaddw %0, "__percpu_arg(1) \ + : "+r" (ret__), "+m" (var) \ + : : "memory"); \ + break; \ + case 4: \ + asm("xaddl %0, "__percpu_arg(1) \ + : "+r"(ret__), "+m" (var) \ + : : "memory"); \ + break; \ + case 8: \ + asm("xaddq %0, "__percpu_arg(1) \ + : "+re" (ret__), "+m" (var) \ + : : "memory"); \ + break; \ + default: __bad_percpu_size(); \ + } \ + ret__ += val; \ + ret__; \ +}) +#define percpu_from_op (op, var, constraint) \ ({ \ typeof(var) pfo_ret__; \
@@ -300,6 +335,14 @@ do { \#define irqsafe_cpu_xor_2 (pcp, val) percpu_to_op("xor", (pcp), val)#define irqsafe_cpu_xor_4 (pcp, val) percpu_to_op("xor", (pcp), val) +#ifndef CONFIG_M386 +#define __this_cpu_add_return_1 (pcp, val) percpu_add_return_op(pcp, val) +#define __this_cpu_add_return_2 (pcp, val) percpu_add_return_op(pcp, val) +#define __this_cpu_add_return_4 (pcp, val) percpu_add_return_op(pcp, val) +#define this_cpu_add_return_1 (pcp, val) percpu_add_return_op(pcp, val) +#define this_cpu_add_return_2 (pcp, val) percpu_add_return_op(pcp, val) +#define this_cpu_add_return_4 (pcp, val) percpu_add_return_op(pcp, val) +#endif /* * Per cpu atomic 64 bit operations are only available under 64 bit. * 32 bit must fall back to generic operations.
@@ -324,6 +367,9 @@ do { \#define irqsafe_cpu_or_8 (pcp, val) percpu_to_op("or", (pcp), val)#define irqsafe_cpu_xor_8 (pcp, val) percpu_to_op("xor", (pcp), val) +#define __this_cpu_add_return_8 (pcp, val) percpu_add_return_op(pcp, val) +#define this_cpu_add_return_8 (pcp, val) percpu_add_return_op(pcp, val) +#endif /* This is not atomic against other CPUs -- CPU preemption needs to be off */
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 14/18 lguest: Use this_cpu_ops
In reply to Christoph LameterUse this_cpu_ops in a couple of places in lguest.
--- arch/x86/lguest/boot.c | 2 +- drivers/lguest/page_tables.c | 2 +- drivers/lguest/x86/core.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-)
arch/x86/lguest/boot.c +1 -1
@@ -821,7 +821,7 @@ static void __init lguest_init_IRQ(void)for (i =FIRST_EXTERNAL_VECTOR ; i <NR_VECTORS ; i++) {/* Some systems map "vectors" to interrupts weirdly. Not us! */ -__get_cpu_var (vector_irq)[i] = i -FIRST_EXTERNAL_VECTOR ; +__this_cpu_write (vector_irq[i]) = i -FIRST_EXTERNAL_VECTOR ;if (i !=SYSCALL_VECTOR )set_intr_gate (i, interrupt[i -FIRST_EXTERNAL_VECTOR ]); }
drivers/lguest/page_tables.c +1 -1
@@ -1137,7 +1137,7 @@ void free_guest_pagetable(struct lguest*/ void map_switcher_in_guest (struct lg_cpu *cpu,struct lguest_pages *pages) { -pte_t *switcher_pte_page =__get_cpu_var (switcher_pte_pages); +pte_t *switcher_pte_page =__this_cpu_read (switcher_pte_pages);pte_t regs_pte;#ifdef CONFIG_X86_PAE
drivers/lguest/x86/core.c +2 -2
@@ -90,8 +90,8 @@ static void copy_in_guest_info(struct lg* meanwhile). If that's not the case, we pretend everything in the * Guest has changed. */ -if (__get_cpu_var (lg_last_cpu) != cpu || cpu->last_pages != pages) { -__get_cpu_var (lg_last_cpu) = cpu; +if (__this_cpu_read (lg_last_cpu) != cpu || cpu->last_pages != pages) { +__this_cpu_read (lg_last_cpu) = cpu; cpu->last_pages = pages; cpu->changed =CHANGED_ALL ; }
PATCH 15/18 Xen: Use this_cpu_ops
In reply to Christoph LameterUse this_cpu_ops to reduce code size and simplify things in various places.
Cc: Jeremy Fitzhardinge <[email protected]> Cc:
--- arch/x86/xen/enlighten.c | 4 ++-- arch/x86/xen/multicalls.h | 2 +- arch/x86/xen/spinlock.c | 8 ++++---- arch/x86/xen/time.c | 13 ++++++------- drivers/xen/events.c | 10 +++++----- 5 files changed, 18 insertions(+), 19 deletions(-)
arch/x86/xen/enlighten.c +2 -2
@@ -574,8 +574,8 @@ static void xen_write_idt_entry(gate_despreempt_disable (); - start =__get_cpu_var (idt_desc).address; - end = start +__get_cpu_var (idt_desc).size +1 ; + start =__this_cpu_read (idt_desc.address); + end = start +__this_cpu_read (idt_desc.size) +1 ;xen_mc_flush ();
arch/x86/xen/multicalls.h +1 -1
@@ -22,7 +22,7 @@ static inline void xen_mc_batch(void)unsigned long flags;/* need to disable interrupts until this entry is complete */ local_irq_save (flags); -__get_cpu_var (xen_mc_irq_flags) = flags; +__this_cpu_write (xen_mc_irq_flags, flags); }static inline struct multicall_space xen_mc_entry (size_t args)
arch/x86/xen/spinlock.c +4 -4
@@ -159,8 +159,8 @@ static inline struct xen_spinlock *spinn {struct xen_spinlock *prev; - prev =__get_cpu_var (lock_spinners); -__get_cpu_var (lock_spinners) = xl; + prev =__this_cpu_read (lock_spinners); +__this_cpu_write (lock_spinners, xl);wmb ();/* set lock of interest before count */
@@ -179,14 +179,14 @@ static inline void unspinning_lock(struc asm(LOCK_PREFIX " decw %0" :"+m" (xl->spinners) : :"memory" );wmb ();/* decrement count before restoring lock */ -__get_cpu_var (lock_spinners) = prev; +__this_cpu_write (lock_spinners, prev); } static noinline int xen_spin_lock_slow(struct arch_spinlock *lock, bool irq_enable) {struct xen_spinlock *xl = (struct xen_spinlock *)lock;struct xen_spinlock *prev; -int irq =__get_cpu_var (lock_kicker_irq); +int irq =__this_cpu_read (lock_kicker_irq);int ret;u64 start;
arch/x86/xen/time.c +6 -7
@@ -135,24 +135,24 @@ static void do_stolen_accounting(void)/* Add the appropriate number of ticks of stolen time, including any left-overs from last time. */ - stolen = runnable + offline +__get_cpu_var (xen_residual_stolen); + stolen = runnable + offline +__this_cpu_read (xen_residual_stolen);if (stolen <0 ) stolen =0 ; ticks =iter_div_u64_rem (stolen,NS_PER_TICK , &stolen); -__get_cpu_var (xen_residual_stolen) = stolen; +__this_cpu_write (xen_residual_stolen, stolen);account_steal_ticks (ticks);/* Add the appropriate number of ticks of blocked time, including any left-overs from last time. */ - blocked +=__get_cpu_var (xen_residual_blocked); + blocked +=__this_cpu_read (xen_residual_blocked);if (blocked <0 ) blocked =0 ; ticks =iter_div_u64_rem (blocked,NS_PER_TICK , &blocked); -__get_cpu_var (xen_residual_blocked) = blocked; +__this_cpu_write (xen_residual_blocked, blocked);account_idle_ticks (ticks); }
@@ -370,12 +370,11 @@ static DEFINE_PER_CPU(struct clock_eventstatic irqreturn_t xen_timer_interrupt (int irq,void *dev_id) { -struct clock_event_device *evt = &__get_cpu_var (xen_clock_events);irqreturn_t ret; ret =IRQ_NONE ; -if (evt->event_handler) { - evt->event_handler (evt); +if (__this_cpu_read (xen_clock_events.event_handler)) { +__this_cpu_read (xen_clock_events.event_handler)(evt); ret =IRQ_HANDLED ; }
drivers/xen/events.c +5 -5
@@ -356,7 +356,7 @@ static void unmask_evtchn(int port)struct evtchn_unmask unmask = { .port = port }; (void )HYPERVISOR_event_channel_op (EVTCHNOP_unmask, &unmask); }else { -struct vcpu_info *vcpu_info =__get_cpu_var (xen_vcpu); +struct vcpu_info *vcpu_info =__this_cpu_read (xen_vcpu);sync_clear_bit (port, &s->evtchn_mask[0 ]);
@@ -1087,7 +1087,7 @@ static void __xen_evtchn_do_upcall(void) {int cpu =get_cpu ();struct shared_info *s = HYPERVISOR_shared_info; -struct vcpu_info *vcpu_info =__get_cpu_var (xen_vcpu); +struct vcpu_info *vcpu_info =__this_cpu_read (xen_vcpu);unsigned count; do {
@@ -1095,7 +1095,7 @@ static void __xen_evtchn_do_upcall(void) vcpu_info->evtchn_upcall_pending =0 ; -if (__get_cpu_var (xed_nesting_count)++) +if (__this_cpu_inc_return (xed_nesting_count)) goto out;#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
@@ -1127,8 +1127,8 @@ static void __xen_evtchn_do_upcall(void)BUG_ON (!irqs_disabled ()); - count =__get_cpu_var (xed_nesting_count); -__get_cpu_var (xed_nesting_count) =0 ; + count =__this_cpu_read (xed_nesting_count); +__this_cpu_write (xed_nesting_count,0 ); }while (count !=1 || vcpu_info->evtchn_upcall_pending); out:
PATCH 6/18 vmstat: Use this_cpu_inc_return for vm statistics
In reply to Christoph Lameterthis_cpu_inc_return() saves us a memory access there. Code size does not change.
V1->V2:
- Fixed the location of the __per_cpu pointer attributes
- Sparse checkedV2->V3:
- Move fixes to __percpu attribute usage to earlier patch
--- mm/vmstat.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
mm/vmstat.c +2 -6
@@ -227,9 +227,7 @@ void __inc_zone_state(struct zone *zone,s8 __percpu *p = pcp->vm_stat_diff + item;s8 v, t; -__this_cpu_inc (*p); - - v =__this_cpu_read (*p); + v =__this_cpu_inc_return (*p); t =__this_cpu_read (pcp->stat_threshold);if (unlikely (v > t)) {s8 overstep = t >>1 ;
@@ -251,9 +249,7 @@ void __dec_zone_state(struct zone *zone,s8 __percpu *p = pcp->vm_stat_diff + item;s8 v, t; -__this_cpu_dec (*p); - - v =__this_cpu_read (*p); + v =__this_cpu_dec_return (*p); t =__this_cpu_read (pcp->stat_threshold);if (unlikely (v < - t)) {s8 overstep = t >>1 ;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 13/18 drivers: Replace __get_cpu_var with __this_cpu_read if not used for an address.
In reply to Christoph Lameter__get_cpu_var() can be replaced with this_cpu_read and will then use a single read instruction with implied address calculation to access the correct per cpu instance.
However, the address of a per cpu variable passed to __this_cpu_read() cannot be determed (since its an implied address conversion through segment prefixes). Therefore apply this only to uses of __get_cpu_var where the addres of the variable is not used.
--- drivers/acpi/processor_idle.c | 6 +++--- drivers/char/random.c | 2 +- drivers/cpuidle/cpuidle.c | 2 +- drivers/s390/cio/cio.c | 2 +- drivers/staging/speakup/fakekey.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-)
drivers/acpi/processor_idle.c +3 -3
@@ -746,7 +746,7 @@ static int acpi_idle_enter_c1(struct cpustruct acpi_processor *pr;struct acpi_processor_cx *cx =cpuidle_get_statedata (state); - pr =__get_cpu_var (processors); + pr =__this_cpu_read (processors);if (unlikely (!pr))return 0 ;
@@ -787,7 +787,7 @@ static int acpi_idle_enter_simple(structs64 idle_time_ns;s64 idle_time; - pr =__get_cpu_var (processors); + pr =__this_cpu_read (processors);if (unlikely (!pr))return 0 ;
@@ -864,7 +864,7 @@ static int acpi_idle_enter_bm(struct cpus64 idle_time; - pr =__get_cpu_var (processors); + pr =__this_cpu_read (processors);if (unlikely (!pr))return 0 ;
drivers/char/random.c +1 -1
@@ -626,7 +626,7 @@ static void add_timer_randomness(structpreempt_disable ();/* if over the trickle threshold, use only 1 in 4096 samples */ if (input_pool.entropy_count > trickle_thresh && - (__get_cpu_var (trickle_count)++ &0xfff )) + (__this_cpu_inc_return (trickle_count) &0xfff )) goto out; sample.jiffies = jiffies;
drivers/cpuidle/cpuidle.c +1 -1
@@ -49,7 +49,7 @@ static int __cpuidle_register_device(str*/ static void cpuidle_idle_call (void ) { -struct cpuidle_device *dev =__get_cpu_var (cpuidle_devices); +struct cpuidle_device *dev =__this_cpu_read (cpuidle_devices);struct cpuidle_state *target_state;int next_state;
drivers/s390/cio/cio.c +1 -1
@@ -619,7 +619,7 @@ void __irq_entry do_IRQ(struct pt_regs *s390_idle_check (regs, S390_lowcore.int_clock, S390_lowcore.async_enter_timer);irq_enter (); -__get_cpu_var (s390_idle).nohz_delay =1 ; +__this_cpu_write (s390_idle.nohz_delay,1 );if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)/* Serve timer interrupts first. */ clock_comparator_work ();
drivers/staging/speakup/fakekey.c +2 -2
@@ -79,10 +79,10 @@ void speakup_fake_down_arrow(void)/* don't change CPU */ preempt_disable (); -__get_cpu_var (reporting_keystroke) = true; + __this_cpu_write(reporting_keystroke), true);input_report_key (virt_keyboard,KEY_DOWN ,PRESSED );input_report_key (virt_keyboard,KEY_DOWN ,RELEASED ); -__get_cpu_var (reporting_keystroke) = false; +__this_cpu_write (reporting_keystroke, false);/* reenable preemption */ preempt_enable ();
PATCH 5/18 x86: Use this_cpu_inc_return for nmi counter
In reply to Christoph Lameterthis_cpu_inc_return() saves us a memory access there.
--- arch/x86/kernel/apic/nmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/x86/kernel/apic/nmi.c +1 -2
@@ -432,8 +432,7 @@ nmi_watchdog_tick(struct pt_regs *regs,* Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ... */ -__this_cpu_inc (alert_counter); -if (__this_cpu_read (alert_counter) ==5 * nmi_hz) +if (__this_cpu_inc_return (alert_counter) ==5 * nmi_hz)/* * die_nmi will return ONLY if NOTIFY_STOP happens.. */
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 8/18 Taskstats: Use this_cpu_ops
In reply to Christoph LameterUse this_cpu_inc_return in one place and avoid ugly __raw_get_cpu in another.
--- kernel/taskstats.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/taskstats.c +2 -3
@@ -89,8 +89,7 @@ static int prepare_reply(struct genl_infreturn -ENOMEM ;if (!info) { -int seq =get_cpu_var (taskstats_seqnum)++; -put_cpu_var (taskstats_seqnum); +int seq =this_cpu_inc_return (taskstats_seqnum); reply =genlmsg_put (skb,0 , seq, &family,0 , cmd); }else
@@ -581,7 +580,7 @@ void taskstats_exit(struct task_struct *fill_tgid_exit (tsk); } - listeners = &__raw_get_cpu_var (listener_array); + listeners =__this_cpu_ptr (listener_array);if (list_empty (&listeners->list))return ;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 10/18 x86: Use this_cpu_ops to optimize code
In reply to Christoph LameterGo through x86 code and replace __get_cpu_var and get_cpu_var instances that refer to a scalar and are not used for address determinations.
--- arch/x86/include/asm/debugreg.h | 2 - arch/x86/kernel/apic/io_apic.c | 4 +-- arch/x86/kernel/apic/nmi.c | 24 +++++++++++----------- arch/x86/kernel/apic/x2apic_uv_x.c | 8 +++---- arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 2 - arch/x86/kernel/cpu/mcheck/mce.c | 6 ++--- arch/x86/kernel/cpu/perf_event.c | 32 ++++++++++++------------------ arch/x86/kernel/cpu/perf_event_intel.c | 4 +-- arch/x86/kernel/ftrace.c | 6 ++--- arch/x86/kernel/hw_breakpoint.c | 12 +++++------ arch/x86/kernel/irq.c | 6 ++--- arch/x86/kernel/irq_32.c | 4 +-- arch/x86/kernel/tsc.c | 2 - arch/x86/kvm/x86.c | 8 +++---- arch/x86/oprofile/nmi_int.c | 2 - 15 files changed, 58 insertions(+), 64 deletions(-)
arch/x86/include/asm/debugreg.h +1 -1
@@ -94,7 +94,7 @@ static inline void hw_breakpoint_disablestatic inline int hw_breakpoint_active (void ) { -return __get_cpu_var (cpu_dr7) &DR_GLOBAL_ENABLE_MASK ; +return __this_cpu_read (cpu_dr7) &DR_GLOBAL_ENABLE_MASK ; }extern void aout_dump_debugregs (struct user *dump);
arch/x86/kernel/apic/io_apic.c +2 -2
@@ -2302,7 +2302,7 @@ asmlinkage void smp_irq_move_cleanup_intunsigned int irr;struct irq_desc *desc;struct irq_cfg *cfg; - irq =__get_cpu_var (vector_irq)[vector]; + irq =__this_cpu_read (vector_irq[vector]);if (irq ==-1 )continue ;
@@ -2336,7 +2336,7 @@ asmlinkage void smp_irq_move_cleanup_int apic->send_IPI_self (IRQ_MOVE_CLEANUP_VECTOR ); goto unlock; } -__get_cpu_var (vector_irq)[vector] =-1 ; +__this_cpu_write (vector_irq[vector],-1 ); unlock:raw_spin_unlock (&desc->lock); }
arch/x86/kernel/apic/nmi.c +12 -12
@@ -306,12 +306,12 @@ void acpi_nmi_disable(void)*/ void cpu_nmi_set_wd_enabled (void ) { -__get_cpu_var (wd_enabled) =1 ; +__this_cpu_write (wd_enabled,1 ); }void setup_apic_nmi_watchdog (void *unused) { -if (__get_cpu_var (wd_enabled)) +if (__this_cpu_read (wd_enabled))return ;/* cheap hack to support suspend/resume */
@@ -322,12 +322,12 @@ void setup_apic_nmi_watchdog(void *unuseswitch (nmi_watchdog) {case NMI_LOCAL_APIC :if (lapic_watchdog_init (nmi_hz) <0 ) { -__get_cpu_var (wd_enabled) =0 ; +__this_cpu_write (wd_enabled,0 );return ; }/* FALL THROUGH */ case NMI_IO_APIC : -__get_cpu_var (wd_enabled) =1 ; +__this_cpu_write (wd_enabled,1 );atomic_inc (&nmi_active); } }
@@ -337,13 +337,13 @@ void stop_apic_nmi_watchdog(void *unused/* only support LOCAL and IO APICs for now */ if (!nmi_watchdog_active ())return ; -if (__get_cpu_var (wd_enabled) ==0 ) +if (__this_cpu_read (wd_enabled) ==0 )return ;if (nmi_watchdog ==NMI_LOCAL_APIC )lapic_watchdog_stop ();else __acpi_nmi_disable (NULL ); -__get_cpu_var (wd_enabled) =0 ; +__this_cpu_write (wd_enabled,0 );atomic_dec (&nmi_active); }
@@ -403,8 +403,8 @@ nmi_watchdog_tick(struct pt_regs *regs, sum =get_timer_irqs (cpu); -if (__get_cpu_var (nmi_touch)) { -__get_cpu_var (nmi_touch) =0 ; +if (__this_cpu_read (nmi_touch)) { +__this_cpu_write (nmi_touch,0 ); touched =1 ; }
@@ -427,7 +427,7 @@ nmi_watchdog_tick(struct pt_regs *regs, touched =1 ;/* if the none of the timers isn't firing, this cpu isn't doing much */ -if (!touched &&__get_cpu_var (last_irq_sum) == sum) { +if (!touched &&__this_cpu_read (last_irq_sum) == sum) {/* * Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ...
@@ -439,12 +439,12 @@ nmi_watchdog_tick(struct pt_regs *regs,die_nmi ("BUG: NMI Watchdog detected LOCKUP" , regs, panic_on_timeout); }else { -__get_cpu_var (last_irq_sum) = sum; +__this_cpu_write (last_irq_sum, sum);__this_cpu_write (alert_counter,0 ); }/* see if the nmi watchdog went off */ -if (!__get_cpu_var (wd_enabled)) +if (!__this_cpu_read (wd_enabled))return rc;switch (nmi_watchdog) {case NMI_LOCAL_APIC :
@@ -466,7 +466,7 @@ nmi_watchdog_tick(struct pt_regs *regs,static void enable_ioapic_nmi_watchdog_single (void *unused) { -__get_cpu_var (wd_enabled) =1 ; +__this_cpu_write (wd_enabled,1 );atomic_inc (&nmi_active);__acpi_nmi_enable (NULL ); }
arch/x86/kernel/apic/x2apic_uv_x.c +4 -4
@@ -118,8 +118,8 @@ static int __init uv_acpi_madt_oem_checkelse if (!strcmp (oem_table_id,"UVX" )) uv_system_type =UV_X2APIC ;else if (!strcmp (oem_table_id,"UVH" )) { -__get_cpu_var (x2apic_extra_bits) = - nodeid << (uvh_apicid.s.pnode_shift -1 ); +__this_cpu_write (x2apic_extra_bits, + nodeid << (uvh_apicid.s.pnode_shift -1 )); uv_system_type =UV_NON_UNIQUE_APIC ;uv_set_apicid_hibit ();return 1 ;
@@ -284,7 +284,7 @@ static unsigned int x2apic_get_apic_id(uunsigned int id;WARN_ON (preemptible () &&num_online_cpus () >1 ); - id = x |__get_cpu_var (x2apic_extra_bits); + id = x |__this_cpu_read (x2apic_extra_bits);return id; }
@@ -376,7 +376,7 @@ struct apic __refdata apic_x2apic_uv_x =static __cpuinit void set_x2apic_extra_bits (int pnode) { -__get_cpu_var (x2apic_extra_bits) = (pnode <<6 ); +__this_cpu_write (x2apic_extra_bits, (pnode <<6 )); }/*
arch/x86/kernel/cpu/cpufreq/powernow-k8.c +1 -1
@@ -1377,7 +1377,7 @@ static int __devexit powernowk8_cpu_exitstatic void query_values_on_cpu (void *_err) {int *err = _err; -struct powernow_k8_data *data =__get_cpu_var (powernow_data); +struct powernow_k8_data *data =__this_cpu_read (powernow_data); *err =query_current_values_with_pending_wait (data); }
arch/x86/kernel/cpu/mcheck/mce.c +3 -3
@@ -326,7 +326,7 @@ static void mce_panic(char *msg, structstatic int msr_to_offset (u32 msr) { -unsigned bank =__get_cpu_var (injectm.bank); +unsigned bank =__this_cpu_read (injectm.bank);if (msr == rip_msr)return offsetof(struct mce , ip);
@@ -346,7 +346,7 @@ static u64 mce_rdmsrl(u32 msr) {u64 v; -if (__get_cpu_var (injectm).finished) { +if (__this_cpu_read (injectm.finished)) {int offset =msr_to_offset (msr);if (offset <0 )
@@ -369,7 +369,7 @@ static u64 mce_rdmsrl(u32 msr)static void mce_wrmsrl (u32 msr,u64 v) { -if (__get_cpu_var (injectm).finished) { +if (__this_cpu_read (injectm.finished)) {int offset =msr_to_offset (msr);if (offset >=0 )
arch/x86/kernel/cpu/perf_event.c +13 -19
@@ -968,8 +968,7 @@ x86_perf_event_set_period(struct perf_evstatic void x86_pmu_enable_event (struct perf_event *event) { -struct cpu_hw_events *cpuc = &__get_cpu_var (cpu_hw_events); -if (cpuc->enabled) +if (__this_cpu_read (cpu_hw_events.enabled))__x86_pmu_enable_event (&event->hw,ARCH_PERFMON_EVENTSEL_ENABLE ); }
@@ -1108,12 +1107,11 @@ void perf_event_print_debug(void)static void x86_pmu_stop (struct perf_event *event,int flags) { -struct cpu_hw_events *cpuc = &__get_cpu_var (cpu_hw_events);struct hw_perf_event *hwc = &event->hw; -if (__test_and_clear_bit (hwc->idx, cpuc->active_mask)) { +if (__test_and_clear_bit (hwc->idx,__get_cpu_var (cpu_hw_events).active_mask)) { x86_pmu.disable (event); - cpuc->events[hwc->idx] =NULL ; +__this_cpu_write (cpu_hw_events.events[hwc->idx],NULL );WARN_ON_ONCE (hwc->state &PERF_HES_STOPPED ); hwc->state |=PERF_HES_STOPPED ; }
@@ -1243,7 +1241,7 @@ perf_event_nmi_handler(struct notifier_bbreak ;case DIE_NMIUNKNOWN : this_nmi =percpu_read (irq_stat.__nmi_count); -if (this_nmi !=__get_cpu_var (pmu_nmi).marked) +if (this_nmi !=__this_cpu_read (pmu_nmi.marked))/* let the kernel handle the unknown nmi */ return NOTIFY_DONE ;/*
@@ -1267,8 +1265,8 @@ perf_event_nmi_handler(struct notifier_b this_nmi =percpu_read (irq_stat.__nmi_count);if ((handled >1 ) ||/* the next nmi could be a back-to-back nmi */ - ((__get_cpu_var (pmu_nmi).marked == this_nmi) && - (__get_cpu_var (pmu_nmi).handled >1 ))) { + ((__this_cpu_read (pmu_nmi.marked) == this_nmi) && + (__this_cpu_read (pmu_nmi.handled) >1 ))) {/* * We could have two subsequent back-to-back nmis: The * first handles more than one counter, the 2nd
@@ -1279,8 +1277,8 @@ perf_event_nmi_handler(struct notifier_b* handling more than one counter. We will mark the * next (3rd) and then drop it if unhandled. */ -__get_cpu_var (pmu_nmi).marked = this_nmi +1 ; -__get_cpu_var (pmu_nmi).handled = handled; +__this_cpu_write (pmu_nmi.marked, this_nmi +1 ); +__this_cpu_write (pmu_nmi.handled, handled); }return NOTIFY_STOP ;
@@ -1454,11 +1452,9 @@ static inline void x86_pmu_read(struct p*/ static void x86_pmu_start_txn (struct pmu *pmu) { -struct cpu_hw_events *cpuc = &__get_cpu_var (cpu_hw_events); -perf_pmu_disable (pmu); - cpuc->group_flag |=PERF_EVENT_TXN ; - cpuc->n_txn =0 ; +__this_cpu_or (cpu_hw_events.group_flag,PERF_EVENT_TXN ); +__this_cpu_write (cpu_hw_events.n_txn,0 ); }/*
@@ -1468,14 +1464,12 @@ static void x86_pmu_start_txn(struct pmu*/ static void x86_pmu_cancel_txn (struct pmu *pmu) { -struct cpu_hw_events *cpuc = &__get_cpu_var (cpu_hw_events); - - cpuc->group_flag &= ~PERF_EVENT_TXN ; +__this_cpu_and (cpu_hw_events.group_flag, ~PERF_EVENT_TXN );/* * Truncate the collected events. */ - cpuc->n_added -= cpuc->n_txn; - cpuc->n_events -= cpuc->n_txn; +__this_cpu_sub (cpu_hw_events.n_added,__this_cpu_read (cpu_hw_events.n_txn)); +__this_cpu_sub (cpu_hw_events.n_events,__this_cpu_read (cpu_hw_events.n_txn));perf_pmu_enable (pmu); }
arch/x86/kernel/cpu/perf_event_intel.c +2 -2
@@ -649,7 +649,7 @@ static void intel_pmu_enable_event(strucstruct hw_perf_event *hwc = &event->hw;if (unlikely (hwc->idx ==X86_PMC_IDX_FIXED_BTS )) { -if (!__get_cpu_var (cpu_hw_events).enabled) +if (!__this_cpu_read (cpu_hw_events.enabled))return ;intel_pmu_enable_bts (hwc->config);
@@ -679,7 +679,7 @@ static int intel_pmu_save_and_restart(ststatic void intel_pmu_reset (void ) { -struct debug_store *ds =__get_cpu_var (cpu_hw_events).ds; +struct debug_store *ds =__this_cpu_read (cpu_hw_events.ds);unsigned long flags;int idx;
arch/x86/kernel/ftrace.c +3 -3
@@ -167,9 +167,9 @@ static void ftrace_mod_code(void)void ftrace_nmi_enter (void ) { -__get_cpu_var (save_modifying_code) = modifying_code; +__this_cpu_write (save_modifying_code, modifying_code); -if (!__get_cpu_var (save_modifying_code)) +if (!__this_cpu_read (save_modifying_code))return ;if (atomic_inc_return (&nmi_running) &MOD_CODE_WRITE_FLAG ) {
@@ -183,7 +183,7 @@ void ftrace_nmi_enter(void)void ftrace_nmi_exit (void ) { -if (!__get_cpu_var (save_modifying_code)) +if (!__this_cpu_read (save_modifying_code))return ;/* Finish all executions before clearing nmi_running */
arch/x86/kernel/hw_breakpoint.c +6 -6
@@ -122,7 +122,7 @@ int arch_install_hw_breakpoint(struct pereturn -EBUSY ;set_debugreg (info->address, i); -__get_cpu_var (cpu_debugreg[i]) = info->address; +__this_cpu_write (cpu_debugreg[i], info->address); dr7 = &__get_cpu_var (cpu_dr7); *dr7 |=encode_dr7 (i, info->len, info->type);
@@ -397,12 +397,12 @@ void flush_ptrace_hw_breakpoint(struct tvoid hw_breakpoint_restore (void ) { -set_debugreg (__get_cpu_var (cpu_debugreg[0 ]),0 ); -set_debugreg (__get_cpu_var (cpu_debugreg[1 ]),1 ); -set_debugreg (__get_cpu_var (cpu_debugreg[2 ]),2 ); -set_debugreg (__get_cpu_var (cpu_debugreg[3 ]),3 ); +set_debugreg (__this_cpu_read (cpu_debugreg[0 ]),0 ); +set_debugreg (__this_cpu_read (cpu_debugreg[1 ]),1 ); +set_debugreg (__this_cpu_read (cpu_debugreg[2 ]),2 ); +set_debugreg (__this_cpu_read (cpu_debugreg[3 ]),3 );set_debugreg (current->thread.debugreg6,6 ); -set_debugreg (__get_cpu_var (cpu_dr7),7 ); +set_debugreg (__this_cpu_read (cpu_dr7),7 ); }EXPORT_SYMBOL_GPL (hw_breakpoint_restore);
arch/x86/kernel/irq.c +3 -3
@@ -234,7 +234,7 @@ unsigned int __irq_entry do_IRQ(struct pexit_idle ();irq_enter (); - irq =__get_cpu_var (vector_irq)[vector]; + irq =__this_cpu_read (vector_irq[vector]);if (!handle_irq (irq, regs)) {ack_APIC_irq ();
@@ -350,12 +350,12 @@ void fixup_irqs(void)for (vector =FIRST_EXTERNAL_VECTOR ; vector <NR_VECTORS ; vector++) {unsigned int irr; -if (__get_cpu_var (vector_irq)[vector] <0 ) +if (__this_cpu_read (vector_irq[vector]) <0 )continue ; irr =apic_read (APIC_IRR + (vector /32 *0x10 ));if (irr & (1 << (vector %32 ))) { - irq =__get_cpu_var (vector_irq)[vector]; + irq =__this_cpu_read (vector_irq[vector]); data =irq_get_irq_data (irq);raw_spin_lock (&desc->lock);
arch/x86/kernel/irq_32.c +2 -2
@@ -79,7 +79,7 @@ execute_on_irq_stack(int overflow, strucu32 *isp, arg1, arg2; curctx = (union irq_ctx *)current_thread_info (); - irqctx =__get_cpu_var (hardirq_ctx); + irqctx =__this_cpu_read (hardirq_ctx);/* * this is where we switch to the IRQ stack. However, if we are
@@ -166,7 +166,7 @@ asmlinkage void do_softirq(void)if (local_softirq_pending ()) { curctx =current_thread_info (); - irqctx =__get_cpu_var (softirq_ctx); + irqctx =__this_cpu_read (softirq_ctx); irqctx->tinfo.task = curctx->task; irqctx->tinfo.previous_esp = current_stack_pointer;
arch/x86/kernel/tsc.c +1 -1
@@ -659,7 +659,7 @@ void restore_sched_clock_state(void)local_irq_save (flags); -__get_cpu_var (cyc2ns_offset) =0 ; +__this_cpu_write (cyc2ns_offset,0 ); offset = cyc2ns_suspend -sched_clock ();for_each_possible_cpu (cpu)
arch/x86/kvm/x86.c +4 -4
@@ -981,7 +981,7 @@ static inline u64 nsec_to_cycles(u64 nseif (kvm_tsc_changes_freq ())printk_once (KERN_WARNING "kvm: unreliable cycle conversion on adjustable rate TSC\n" ); - ret = nsec *__get_cpu_var (cpu_tsc_khz); + ret = nsec *__this_cpu_read (cpu_tsc_khz);do_div (ret,USEC_PER_SEC );return ret; }
@@ -1066,7 +1066,7 @@ static int kvm_guest_time_update(structlocal_irq_save (flags);kvm_get_msr (v,MSR_IA32_TSC , &tsc_timestamp); kernel_ns =get_kernel_ns (); - this_tsc_khz =__get_cpu_var (cpu_tsc_khz); + this_tsc_khz =__this_cpu_read (cpu_tsc_khz);if (unlikely (this_tsc_khz ==0 )) {local_irq_restore (flags);
@@ -4432,7 +4432,7 @@ EXPORT_SYMBOL_GPL(kvm_fast_pio_out);static void tsc_bad (void *info) { -__get_cpu_var (cpu_tsc_khz) =0 ; +__this_cpu_write (cpu_tsc_khz,0 ); }static void tsc_khz_changed (void *data)
@@ -4446,7 +4446,7 @@ static void tsc_khz_changed(void *data) khz =cpufreq_quick_get (raw_smp_processor_id ());if (!khz) khz = tsc_khz; -__get_cpu_var (cpu_tsc_khz) = khz; +__this_cpu_write (cpu_tsc_khz, khz); } static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
arch/x86/oprofile/nmi_int.c +1 -1
@@ -143,7 +143,7 @@ static inline int has_mux(void)inline int op_x86_phys_to_virt (int phys) { -return __get_cpu_var (switch_index) + phys; +return __this_cpu_read (switch_index) + phys; }inline int op_x86_virt_to_phys (int virt)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 16/18 kprobes: Use this_cpu_ops
In reply to Christoph LameterUse this_cpu ops in various places to optimize per cpu data access.
--- arch/x86/kernel/kprobes.c | 14 +++++++------- include/linux/kprobes.h | 4 ++-- kernel/kprobes.c | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-)
arch/x86/kernel/kprobes.c +7 -7
@@ -403,7 +403,7 @@ static void __kprobes save_previous_kprostatic void __kprobes restore_previous_kprobe (struct kprobe_ctlblk *kcb) { -__get_cpu_var (current_kprobe) = kcb->prev_kprobe.kp; +__this_cpu_write (current_kprobe, kcb->prev_kprobe.kp); kcb->kprobe_status = kcb->prev_kprobe.status; kcb->kprobe_old_flags = kcb->prev_kprobe.old_flags; kcb->kprobe_saved_flags = kcb->prev_kprobe.saved_flags;
@@ -412,7 +412,7 @@ static void __kprobes restore_previous_kstatic void __kprobes set_current_kprobe (struct kprobe *p,struct pt_regs *regs,struct kprobe_ctlblk *kcb) { -__get_cpu_var (current_kprobe) = p; +__this_cpu_write (current_kprobe, p); kcb->kprobe_saved_flags = kcb->kprobe_old_flags = (regs->flags & (X86_EFLAGS_TF |X86_EFLAGS_IF ));if (is_IF_modifier (p->ainsn.insn))
@@ -586,7 +586,7 @@ static int __kprobes kprobe_handler(strupreempt_enable_no_resched ();return 1 ; }else if (kprobe_running ()) { - p =__get_cpu_var (current_kprobe); + p =__this_cpu_read (current_kprobe);if (p->break_handler && p->break_handler (p, regs)) {setup_singlestep (p, regs, kcb,0 );return 1 ;
@@ -759,11 +759,11 @@ static __used __kprobes void *trampoline orig_ret_address = (unsigned long )ri->ret_addr;if (ri->rp && ri->rp->handler) { -__get_cpu_var (current_kprobe) = &ri->rp->kp; +__this_cpu_write (current_kprobe, &ri->rp->kp);get_kprobe_ctlblk ()->kprobe_status =KPROBE_HIT_ACTIVE ; ri->ret_addr = correct_ret_addr; ri->rp->handler (ri, regs); -__get_cpu_var (current_kprobe) =NULL ; +__this_cpu_write (current_kprobe,NULL ); }recycle_rp_inst (ri, &empty_rp);
@@ -1198,10 +1198,10 @@ static void __kprobes optimized_callback regs->ip = (unsigned long )op->kp.addr +INT3_SIZE ; regs->orig_ax = ~0UL ; -__get_cpu_var (current_kprobe) = &op->kp; +__this_cpu_write (current_kprobe, &op->kp); kcb->kprobe_status =KPROBE_HIT_ACTIVE ;opt_pre_handler (&op->kp, regs); -__get_cpu_var (current_kprobe) =NULL ; +__this_cpu_write (current_kprobe,NULL ); }preempt_enable_no_resched (); }
include/linux/kprobes.h +2 -2
@@ -303,12 +303,12 @@ struct hlist_head * kretprobe_inst_table/* kprobe_running() will just return the current_kprobe on this CPU */ static inline struct kprobe *kprobe_running (void ) { -return (__get_cpu_var (current_kprobe)); +return (__this_cpu_read (current_kprobe)); }static inline void reset_current_kprobe (void ) { -__get_cpu_var (current_kprobe) =NULL ; +__this_cpu_write (current_kprobe,NULL ); }static inline struct kprobe_ctlblk *get_kprobe_ctlblk (void )
kernel/kprobes.c +4 -4
@@ -317,12 +317,12 @@ void __kprobes free_optinsn_slot(kprobe_/* We have preemption disabled.. so it is safe to use __ versions */ static inline void set_kprobe_instance (struct kprobe *kp) { -__get_cpu_var (kprobe_instance) = kp; +__this_cpu_write (kprobe_instance, kp); }static inline void reset_kprobe_instance (void ) { -__get_cpu_var (kprobe_instance) =NULL ; +__this_cpu_write (kprobe_instance,NULL ); }/*
@@ -775,7 +775,7 @@ static void __kprobes aggr_post_handler(static int __kprobes aggr_fault_handler (struct kprobe *p,struct pt_regs *regs,int trapnr) { -struct kprobe *cur =__get_cpu_var (kprobe_instance); +struct kprobe *cur =__this_cpu_read (kprobe_instance);/* * if we faulted "during" the execution of a user specified
@@ -790,7 +790,7 @@ static int __kprobes aggr_fault_handler(static int __kprobes aggr_break_handler (struct kprobe *p,struct pt_regs *regs) { -struct kprobe *cur =__get_cpu_var (kprobe_instance); +struct kprobe *cur =__this_cpu_read (kprobe_instance);int ret =0 ;if (cur && cur->break_handler) {
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 17/18 Connector: Use this_cpu operations
In reply to Christoph Lameterget_seq can benefit from this_cpu_operations. Address calculation is avoided and the increment is done using an xadd.
--- drivers/connector/cn_proc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/connector/cn_proc.c +3 -2
@@ -43,9 +43,10 @@ static DEFINE_PER_CPU(__u32, proc_event_static inline void get_seq (__u32 *ts,int *cpu) { - *ts =get_cpu_var (proc_event_counts)++; +preempt_disable (); + *ts =__this_cpu_inc (proc_event_counts); *cpu =smp_processor_id (); -put_cpu_var (proc_event_counts); +preempt_enable (); }void proc_fork_connector (struct task_struct *task)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 12/18 Core: Replace __get_cpu_var with __this_cpu_read if not used for an address.
In reply to Christoph Lameter__get_cpu_var() can be replaced with this_cpu_read and will then use a single read instruction with implied address calculation to access the correct per cpu instance.
However, the address of a per cpu variable passed to __this_cpu_read() cannot be determed (since its an implied address conversion through segment prefixes). Therefore apply this only to uses of __get_cpu_var where the addres of the variable is not used.
--- include/asm-generic/irq_regs.h | 8 +++---- include/linux/elevator.h | 12 ++--------- include/linux/kernel_stat.h | 2 - kernel/exit.c | 2 - kernel/fork.c | 2 - kernel/hrtimer.c | 2 - kernel/printk.c | 4 +-- kernel/rcutree.c | 4 +-- kernel/softirq.c | 44 ++++++++++++++++++++--------------------- kernel/time/tick-common.c | 2 - kernel/time/tick-oneshot.c | 4 +-- kernel/watchdog.c | 36 ++++++++++++++++----------------- mm/slab.c | 6 ++--- 13 files changed, 61 insertions(+), 67 deletions(-)
mm/slab.c +3 -3
@@ -829,12 +829,12 @@ static void init_reap_node(int cpu)static void next_reap_node (void ) { -int node =__get_cpu_var (slab_reap_node); +int node =__this_cpu_read (slab_reap_node); node =next_node (node, node_online_map);if (unlikely (node >=MAX_NUMNODES )) node =first_node (node_online_map); -__get_cpu_var (slab_reap_node) = node; +__this_cpu_write (slab_reap_node, node); }#else
@@ -1012,7 +1012,7 @@ static void __drain_alien_cache(struct k*/ static void reap_alien (struct kmem_cache *cachep,struct kmem_list3 *l3) { -int node =__get_cpu_var (slab_reap_node); +int node =__this_cpu_read (slab_reap_node);if (l3->alien) {struct array_cache *ac = l3->alien[node];
kernel/rcutree.c +2 -2
@@ -367,8 +367,8 @@ void rcu_irq_exit(void)WARN_ON_ONCE (rdtp->dynticks &0x1 );/* If the interrupt queued a callback, get out of dyntick mode. */ -if (__get_cpu_var (rcu_sched_data).nxtlist || -__get_cpu_var (rcu_bh_data).nxtlist) +if (__this_cpu_read (rcu_sched_data.nxtlist) || +__this_cpu_read (rcu_bh_data.nxtlist))set_need_resched (); }
kernel/softirq.c +22 -22
105 lines not on this page · raw message
kernel/time/tick-common.c +1 -1
@@ -49,7 +49,7 @@ struct tick_device *tick_get_device(int*/ int tick_is_oneshot_available (void ) { -struct clock_event_device *dev =__get_cpu_var (tick_cpu_device).evtdev; +struct clock_event_device *dev =__this_cpu_read (tick_cpu_device.evtdev);return dev && (dev->features &CLOCK_EVT_FEAT_ONESHOT ); }
kernel/time/tick-oneshot.c +2 -2
@@ -95,7 +95,7 @@ int tick_dev_program_event(struct clock_*/ int tick_program_event (ktime_t expires,int force) { -struct clock_event_device *dev =__get_cpu_var (tick_cpu_device).evtdev; +struct clock_event_device *dev =__this_cpu_read (tick_cpu_device.evtdev);return tick_dev_program_event (dev, expires, force); }
@@ -167,7 +167,7 @@ int tick_oneshot_mode_active(void)int ret;local_irq_save (flags); - ret =__get_cpu_var (tick_cpu_device).mode ==TICKDEV_MODE_ONESHOT ; + ret =__this_cpu_read (tick_cpu_device.mode) ==TICKDEV_MODE_ONESHOT ;local_irq_restore (flags);return ret;
kernel/watchdog.c +18 -18
@@ -116,12 +116,12 @@ static void __touch_watchdog(void) {int this_cpu =smp_processor_id (); -__get_cpu_var (watchdog_touch_ts) =get_timestamp (this_cpu); +__this_cpu_write (watchdog_touch_ts,get_timestamp (this_cpu)); }void touch_softlockup_watchdog (void ) { -__raw_get_cpu_var (watchdog_touch_ts) =0 ; +__this_cpu_write (watchdog_touch_ts,0 ); }EXPORT_SYMBOL (touch_softlockup_watchdog);
@@ -165,12 +165,12 @@ void touch_softlockup_watchdog_sync(void/* watchdog detector functions */ static int is_hardlockup (void ) { -unsigned long hrint =__get_cpu_var (hrtimer_interrupts); +unsigned long hrint =__this_cpu_read (hrtimer_interrupts); -if (__get_cpu_var (hrtimer_interrupts_saved) == hrint) +if (__this_cpu_read (hrtimer_interrupts_saved) == hrint)return 1 ; -__get_cpu_var (hrtimer_interrupts_saved) = hrint; +__this_cpu_write (hrtimer_interrupts_saved, hrint);return 0 ; }#endif
@@ -203,8 +203,8 @@ static void watchdog_overflow_callback(s/* Ensure the watchdog never gets throttled */ event->hw.interrupts =0 ; -if (__get_cpu_var (watchdog_nmi_touch) == true) { -__get_cpu_var (watchdog_nmi_touch) = false; +if (__this_cpu_read (watchdog_nmi_touch) == true) { +__this_cpu_write (watchdog_nmi_touch, false);return ; }
@@ -218,7 +218,7 @@ static void watchdog_overflow_callback(sint this_cpu =smp_processor_id ();/* only print hardlockups once */ -if (__get_cpu_var (hard_watchdog_warn) == true) +if (__this_cpu_read (hard_watchdog_warn) == true)return ;if (hardlockup_panic)
@@ -226,16 +226,16 @@ static void watchdog_overflow_callback(s else WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu); -__get_cpu_var (hard_watchdog_warn) = true; +__this_cpu_write (hard_watchdog_warn, true); return; } -__get_cpu_var (hard_watchdog_warn) = false; +__this_cpu_write (hard_watchdog_warn, false);return ; }static void watchdog_interrupt_count (void ) { -__get_cpu_var (hrtimer_interrupts)++; +__this_cpu_inc (hrtimer_interrupts); }#else static inline void watchdog_interrupt_count (void ) {return ; }
@@ -244,7 +244,7 @@ static inline void watchdog_interrupt_co/* watchdog kicker functions */ static enum hrtimer_restart watchdog_timer_fn (struct hrtimer *hrtimer) { -unsigned long touch_ts =__get_cpu_var (watchdog_touch_ts); +unsigned long touch_ts =__this_cpu_read (watchdog_touch_ts);struct pt_regs *regs =get_irq_regs ();int duration;
@@ -252,18 +252,18 @@ static enum hrtimer_restart watchdog_timwatchdog_interrupt_count ();/* kick the softlockup detector */ -wake_up_process (__get_cpu_var (softlockup_watchdog)); +wake_up_process (__this_cpu_read (softlockup_watchdog));/* .. and repeat */ hrtimer_forward_now (hrtimer,ns_to_ktime (get_sample_period ()));if (touch_ts ==0 ) { -if (unlikely (__get_cpu_var (softlockup_touch_sync))) { +if (unlikely (__this_cpu_read (softlockup_touch_sync))) {/* * If the time stamp was touched atomically * make sure the scheduler tick is up to date. */ -__get_cpu_var (softlockup_touch_sync) = false; +__this_cpu_write (softlockup_touch_sync, false);sched_clock_tick (); }__touch_watchdog ();
@@ -279,7 +279,7 @@ static enum hrtimer_restart watchdog_tim duration =is_softlockup (touch_ts);if (unlikely (duration)) {/* only warn once */ -if (__get_cpu_var (soft_watchdog_warn) == true) +if (__this_cpu_read (soft_watchdog_warn) == true)return HRTIMER_RESTART ; printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
@@ -294,9 +294,9 @@ static enum hrtimer_restart watchdog_timif (softlockup_panic)panic ("softlockup: hung tasks" ); -__get_cpu_var (soft_watchdog_warn) = true; +__this_cpu_write (soft_watchdog_warn, true); }else -__get_cpu_var (soft_watchdog_warn) = false; +__this_cpu_write (soft_watchdog_warn, false);return HRTIMER_RESTART ; }
kernel/printk.c +2 -2
@@ -1074,8 +1074,8 @@ static DEFINE_PER_CPU(int, printk_pendinvoid printk_tick (void ) { -if (__get_cpu_var (printk_pending)) { -__get_cpu_var (printk_pending) =0 ; +if (__this_cpu_read (printk_pending)) { +__this_cpu_write (printk_pending,0 );wake_up_interruptible (&log_wait); } }
include/asm-generic/irq_regs.h +4 -4
@@ -22,15 +22,15 @@ DECLARE_PER_CPU(struct pt_regs *, __irq_static inline struct pt_regs *get_irq_regs (void ) { -return __get_cpu_var (__irq_regs); +return __this_cpu_read (__irq_regs); }static inline struct pt_regs *set_irq_regs (struct pt_regs *new_regs) { -struct pt_regs *old_regs, **pp_regs = &__get_cpu_var (__irq_regs); +struct pt_regs *old_regs; - old_regs = *pp_regs; - *pp_regs = new_regs; + old_regs =__this_cpu_read (__irq_regs); +__this_cpu_write (__irq_regs, new_regs);return old_regs; }
include/linux/elevator.h +3 -9
@@ -195,15 +195,9 @@ enum {/* * io context count accounting */ -#define elv_ioc_count_mod (name, __val) \ - do { \ - preempt_disable(); \ - __get_cpu_var(name) += (__val); \ - preempt_enable(); \ - } while (0) - -#define elv_ioc_count_inc (name) elv_ioc_count_mod(name, 1) -#define elv_ioc_count_dec (name) elv_ioc_count_mod(name, -1) +#define elv_ioc_count_mod (name, __val) this_cpu_add(name, __val) +#define elv_ioc_count_inc (name) this_cpu_inc(name) +#define elv_ioc_count_dec (name) this_cpu_dec(name)#define elv_ioc_count_read (name) \ ({ \
include/linux/kernel_stat.h +1 -1
@@ -47,7 +47,7 @@ extern unsigned long long nr_context_swi#ifndef CONFIG_GENERIC_HARDIRQS #define kstat_irqs_this_cpu (irq) \ - (kstat_this_cpu.irqs[irq]) + (this_cpu_read(kstat.irqs[irq])struct irq_desc ;
kernel/exit.c +1 -1
@@ -69,7 +69,7 @@ static void __unhash_process(struct tasklist_del_rcu (&p->tasks);list_del_init (&p->sibling); -__get_cpu_var (process_counts)--; +__this_cpu_dec (process_counts); }list_del_rcu (&p->thread_group); }
kernel/fork.c +1 -1
@@ -1282,7 +1282,7 @@ static struct task_struct *copy_process(attach_pid (p,PIDTYPE_SID ,task_session (current));list_add_tail (&p->sibling, &p->real_parent->children);list_add_tail_rcu (&p->tasks, &init_task.tasks); -__get_cpu_var (process_counts)++; +__this_cpu_inc (process_counts); }attach_pid (p,PIDTYPE_PID , pid); nr_threads++;
kernel/hrtimer.c +1 -1
@@ -497,7 +497,7 @@ static inline int hrtimer_is_hres_enable*/ static inline int hrtimer_hres_active (void ) { -return __get_cpu_var (hrtimer_bases).hres_active; +return __this_cpu_read (hrtimer_bases.hres_active); }/*
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 7/18 highmem: Use this_cpu_xx_return() operations
In reply to Christoph LameterUse this_cpu operations to optimize access primitives for highmem.
The main effect is the avoidance of address calculations through the use of a segment prefix.
--- include/linux/highmem.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
include/linux/highmem.h +4 -3
@@ -81,7 +81,8 @@ DECLARE_PER_CPU(int, __kmap_atomic_idx);static inline int kmap_atomic_idx_push (void ) { -int idx =__get_cpu_var (__kmap_atomic_idx)++; +int idx =__this_cpu_inc_return (__kmap_atomic_idx) -1 ; +#ifdef CONFIG_DEBUG_HIGHMEM WARN_ON_ONCE (in_irq () && !irqs_disabled ());BUG_ON (idx >KM_TYPE_NR );
@@ -91,12 +92,12 @@ static inline int kmap_atomic_idx_push(vstatic inline int kmap_atomic_idx (void ) { -return __get_cpu_var (__kmap_atomic_idx) -1 ; +return __this_cpu_read (__kmap_atomic_idx) -1 ; }static inline int kmap_atomic_idx_pop (void ) { -int idx = --__get_cpu_var (__kmap_atomic_idx); +int idx =__this_cpu_dec_return (__kmap_atomic_idx);#ifdef CONFIG_DEBUG_HIGHMEM BUG_ON (idx <0 );#endif
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 07/18] highmem: Use this_cpu_xx_return() operations
Quoted 30 lines · Christoph Lameter
pièce jointe document texte brut (
this_cpu_highmem)
Usethis_cpuoperations to optimize access primitives for highmem.The main effect is the avoidance of address calculations through the use of a segment prefix.
Cc Peter Zijlstra <[email protected]>Cc Catalin Marinas <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- include/linux/highmem.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)Index:
linux-2.6/include/linux/highmem.h
===================================================================include/linux/highmem.h +2
-1@@ -81,7 +81,8 @@ DECLARE_PER_CPU(int, __kmap_atomic_idx);static inline int kmap_atomic_idx_push (void ) { -int idx =__get_cpu_var (__kmap_atomic_idx)++; +int idx =__this_cpu_inc_return (__kmap_atomic_idx) -1 ; +#ifdef CONFIG_DEBUG_HIGHMEM WARN_ON_ONCE (in_irq () && !irqs_disabled ());BUG_ON (idx >KM_TYPE_NR );@@ -91,12 +92,12 @@ static inline int kmap_atomic_idx_push(v
include/linux/highmem.h static inline int kmap_atomic_idx_push(v · line 100
Quoted 10 lines
include/linux/highmem.h +2
-2static inline int kmap_atomic_idx (void ) { -return __get_cpu_var (__kmap_atomic_idx) -1 ; +return __this_cpu_read (__kmap_atomic_idx) -1 ; }static inline int kmap_atomic_idx_pop (void ) { -int idx = --__get_cpu_var (__kmap_atomic_idx); +int idx =__this_cpu_dec_return (__kmap_atomic_idx);
__this_cpu_dec_return() is only needed if CONFIG_DEBUG_HIGHMEM
include/linux/highmem.h static inline int kmap_atomic_idx_push(v · line 103
Quoted 4 lines
include/linux/highmem.h +0
-0#ifdef CONFIG_DEBUG_HIGHMEM BUG_ON (idx <0 );#endif
You could change kmap_atomic_idx_pop() to return void, and use __this_cpu_dec(__kmap_atomic_idx)
Peter Zijlstra
Acked-by Rik van RielRe: [thisops uV3 07/18] highmem: Use this_cpu_xx_return() operations
Quoted 44 lines · Eric Dumazet
Quoted 30 lines · Christoph Lameter
pièce jointe document texte brut (
this_cpu_highmem)
Usethis_cpuoperations to optimize access primitives for highmem.The main effect is the avoidance of address calculations through the use of a segment prefix.
Cc Peter Zijlstra <[email protected]>Cc Catalin Marinas <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- include/linux/highmem.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)Index:
linux-2.6/include/linux/highmem.h
===================================================================include/linux/highmem.h +2
-1@@ -81,7 +81,8 @@ DECLARE_PER_CPU(int, __kmap_atomic_idx);static inline int kmap_atomic_idx_push (void ) { -int idx =__get_cpu_var (__kmap_atomic_idx)++; +int idx =__this_cpu_inc_return (__kmap_atomic_idx) -1 ; +#ifdef CONFIG_DEBUG_HIGHMEM WARN_ON_ONCE (in_irq () && !irqs_disabled ());BUG_ON (idx >KM_TYPE_NR );@@ -91,12 +92,12 @@ static inline int kmap_atomic_idx_push(vinclude/linux/highmem.h static inline int kmap_atomic_idx_push(v · line 100
Quoted 10 lines
include/linux/highmem.h +2
-2static inline int kmap_atomic_idx (void ) { -return __get_cpu_var (__kmap_atomic_idx) -1 ; +return __this_cpu_read (__kmap_atomic_idx) -1 ; }static inline int kmap_atomic_idx_pop (void ) { -int idx = --__get_cpu_var (__kmap_atomic_idx); +int idx =__this_cpu_dec_return (__kmap_atomic_idx);
__this_cpu_dec_return()is only needed ifCONFIG_DEBUG_HIGHMEM
Quoted 7 lines
include/linux/highmem.h static inline int kmap_atomic_idx_push(v · line 103
Quoted 4 lines
include/linux/highmem.h +0
-0#ifdef CONFIG_DEBUG_HIGHMEM BUG_ON (idx <0 );#endif You could change
kmap_atomic_idx_pop()to return void, and use__this_cpu_dec(__kmap_atomic_idx)
You can do the void change unconditionally, the debug code already uses kmap_atomic_idx() because of:
---
commit 20273941f2129aa5a432796d98a276ed73d60782
Author: Peter Zijlstra <[email protected]> Date: Wed Oct 27 15:32:58 2010 -0700
mm: fix race in kunmap_atomic()
Christoph reported a nice splat which illustrated a race in the new stack based kmap_atomic implementation.
The problem is that we pop our stack slot before we're completely done resetting its state -- in particular clearing the PTE (sometimes that's CONFIG_DEBUG_HIGHMEM). If an interrupt happens before we actually clear the PTE used for the last slot, that interrupt can reuse the slot in a dirty state, which triggers a BUG in kmap_atomic().
Fix this by introducing kmap_atomic_idx() which reports the current slot index without actually releasing it and use that to find the PTE and delay the _pop() until after we're completely done.
arch/arm/mm/highmem.c +2 -1
@@ -89,7 +89,7 @@ void __kunmap_atomic(void *kvaddr)int idx, type;if (kvaddr >= (void *)FIXADDR_START ) { - type =kmap_atomic_idx_pop (); + type =kmap_atomic_idx (); idx = type +KM_TYPE_NR *smp_processor_id ();if (cache_is_vivt ())
@@ -101,6 +101,7 @@ void __kunmap_atomic(void *kvaddr)#else (void ) idx;/* to kill a warning */ #endif +kmap_atomic_idx_pop (); }else if (vaddr >=PKMAP_ADDR (0 ) && vaddr <PKMAP_ADDR (LAST_PKMAP )) {/* this address was obtained through kmap_high_get() */ kunmap_high (pte_page (pkmap_page_table[PKMAP_NR (vaddr)]));
arch/frv/mm/highmem.c +2 -1
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(__kmap_atomic);void __kunmap_atomic (void *kvaddr) { -int type =kmap_atomic_idx_pop (); +int type =kmap_atomic_idx ();switch (type) {case 0 :__kunmap_atomic_primary (4 ,6 );break ;case 1 :__kunmap_atomic_primary (5 ,7 );break ;
@@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr)default :BUG (); } +kmap_atomic_idx_pop ();pagefault_enable (); }EXPORT_SYMBOL (__kunmap_atomic);
arch/mips/mm/highmem.c +2 -1
@@ -74,7 +74,7 @@ void __kunmap_atomic(void *kvaddr)return ; } - type =kmap_atomic_idx_pop (); + type =kmap_atomic_idx ();#ifdef CONFIG_DEBUG_HIGHMEM {int idx = type +KM_TYPE_NR *smp_processor_id ();
@@ -89,6 +89,7 @@ void __kunmap_atomic(void *kvaddr) local_flush_tlb_one(vaddr); }#endif +kmap_atomic_idx_pop ();pagefault_enable (); }EXPORT_SYMBOL (__kunmap_atomic);
arch/mn10300/include/asm/highmem.h +3 -1
@@ -101,7 +101,7 @@ static inline void __kunmap_atomic(unsigned long vaddr)return ; } - type =kmap_atomic_idx_pop (); + type =kmap_atomic_idx ();#if HIGHMEM_DEBUG {
@@ -119,6 +119,8 @@ static inline void __kunmap_atomic(unsigned long vaddr)__flush_tlb_one (vaddr); }#endif + +kmap_atomic_idx_pop ();pagefault_enable (); }#endif /* __KERNEL__ */
arch/powerpc/mm/highmem.c +3 -1
@@ -62,7 +62,7 @@ void __kunmap_atomic(void *kvaddr)return ; } - type =kmap_atomic_idx_pop (); + type =kmap_atomic_idx ();#ifdef CONFIG_DEBUG_HIGHMEM {
@@ -79,6 +79,8 @@ void __kunmap_atomic(void *kvaddr) local_flush_tlb_page(NULL, vaddr); }#endif + +kmap_atomic_idx_pop ();pagefault_enable (); }EXPORT_SYMBOL (__kunmap_atomic);
arch/sparc/mm/highmem.c +3 -1
@@ -75,7 +75,7 @@ void __kunmap_atomic(void *kvaddr)return ; } - type =kmap_atomic_idx_pop (); + type =kmap_atomic_idx ();#ifdef CONFIG_DEBUG_HIGHMEM {
@@ -104,6 +104,8 @@ void __kunmap_atomic(void *kvaddr) #endif }#endif + +kmap_atomic_idx_pop ();pagefault_enable (); }EXPORT_SYMBOL (__kunmap_atomic);
arch/tile/mm/highmem.c +2 -1
@@ -241,7 +241,7 @@ void __kunmap_atomic(void *kvaddr)pte_t pteval = *pte;int idx, type; - type =kmap_atomic_idx_pop (); + type =kmap_atomic_idx (); idx = type +KM_TYPE_NR *smp_processor_id ();/*
@@ -252,6 +252,7 @@ void __kunmap_atomic(void *kvaddr)BUG_ON (!pte_present (pteval) && !pte_migrating (pteval));kmap_atomic_unregister (pte_page (pteval), vaddr);kpte_clear_flush (pte, vaddr); +kmap_atomic_idx_pop (); }else {/* Must be a lowmem page */ BUG_ON (vaddr <PAGE_OFFSET );
arch/x86/mm/highmem_32.c +2 -1
@@ -74,7 +74,7 @@ void __kunmap_atomic(void *kvaddr) vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {int idx, type; - type =kmap_atomic_idx_pop (); + type =kmap_atomic_idx (); idx = type +KM_TYPE_NR *smp_processor_id ();#ifdef CONFIG_DEBUG_HIGHMEM
@@ -87,6 +87,7 @@ void __kunmap_atomic(void *kvaddr)* attributes or becomes a protected page in a hypervisor. */ kpte_clear_flush (kmap_pte-idx, vaddr); +kmap_atomic_idx_pop (); }#ifdef CONFIG_DEBUG_HIGHMEM else {
arch/x86/mm/iomap_32.c +2 -1
@@ -98,7 +98,7 @@ iounmap_atomic(void __iomem *kvaddr) vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {int idx, type; - type =kmap_atomic_idx_pop (); + type =kmap_atomic_idx (); idx = type +KM_TYPE_NR *smp_processor_id ();#ifdef CONFIG_DEBUG_HIGHMEM
@@ -111,6 +111,7 @@ iounmap_atomic(void __iomem *kvaddr)* attributes or becomes a protected page in a hypervisor. */ kpte_clear_flush (kmap_pte-idx, vaddr); +kmap_atomic_idx_pop (); }pagefault_enable ();
include/linux/highmem.h +5 -0
@@ -88,6 +88,11 @@ static inline int kmap_atomic_idx_push(void)return idx; } +static inline int kmap_atomic_idx (void ) +{ +return __get_cpu_var (__kmap_atomic_idx) -1 ; +} +static inline int kmap_atomic_idx_pop (void ) {int idx = --__get_cpu_var (__kmap_atomic_idx);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 07/18] highmem: Use this_cpu_xx_return() operations
In reply to Eric DumazetQuoted 6 lines · Eric Dumazet
Review
Quoted 3 lines
{
(quoted diff) +1
-1- int idx = --__get_cpu_var(__kmap_atomic_idx); + int idx = __this_cpu_dec_return(__kmap_atomic_idx);
__this_cpu_dec_return()is only needed ifCONFIG_DEBUG_HIGHMEM
Quoted 7 lines
Quoted 4 lines
#ifdef
CONFIG_DEBUG_HIGHMEM
BUG_ON(idx < 0);
#endifYou could change
kmap_atomic_idx_pop()to return void, and use__this_cpu_dec(__kmap_atomic_idx)
The following would do?
Subject: highmem: Use this_cpu_dec instead of __this_cpu_dec_return if !DEBUG_HIGHMEM
--- include/linux/highmem.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
include/linux/highmem.h +7 -2
@@ -95,14 +95,19 @@ static inline int kmap_atomic_idx(void) return __this_cpu_read(__kmap_atomic_idx) - 1; } +#ifdef CONFIG_DEBUG_HIGHMEM static inline int kmap_atomic_idx_pop (void ) {int idx =__this_cpu_dec_return (__kmap_atomic_idx); -#ifdef CONFIG_DEBUG_HIGHMEM BUG_ON (idx <0 ); -#endif return idx; } +#else +static inline void kmap_atomic_idx_pop (void ) +{ +__this_cpu_dec (__kmap_atomic_idx); +} +#endif #endif
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 07/18] highmem: Use this_cpu_xx_return() operations
Le mardi 30 novembre 2010 A 13:26 -0600, Christoph Lameter a A(C)crit :
Quoted 43 lines · Eric Dumazet
Quoted 7 lines
Review
Quoted 4 lines
{
(quoted diff) +1
-1- int idx = --__get_cpu_var(__kmap_atomic_idx); + int idx = __this_cpu_dec_return(__kmap_atomic_idx);
__this_cpu_dec_return()is only needed ifCONFIG_DEBUG_HIGHMEMQuoted 7 lines
Quoted 4 lines
#ifdef
CONFIG_DEBUG_HIGHMEM
BUG_ON(idx < 0);
#endifYou could change
kmap_atomic_idx_pop()to return void, and use__this_cpu_dec(__kmap_atomic_idx)The following would do?
Subject: highmem: Use
this_cpu_decinstead of__this_cpu_dec_returnif !DEBUG_HIGHMEMSigned-off-by Christoph Lameter <[email protected]>--- include/linux/highmem.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)Index:
linux-2.6/include/linux/highmem.h
===================================================================include/linux/highmem.h +1
-2@@ -95,14 +95,19 @@ static inline int kmap_atomic_idx(void)return __this_cpu_read (__kmap_atomic_idx) -1 ; } +#ifdef CONFIG_DEBUG_HIGHMEM static inline int kmap_atomic_idx_pop (void ) {int idx =__this_cpu_dec_return (__kmap_atomic_idx); -#ifdef CONFIG_DEBUG_HIGHMEM BUG_ON (idx <0 ); -#endif return idx;
include/linux/highmem.h static inline int kmap_atomic_idx(void) · line 113
Quoted 10 lines
include/linux/highmem.h +6
-0} +#else +static inline void kmap_atomic_idx_pop (void ) +{ +__this_cpu_dec (__kmap_atomic_idx); +} +#endif #endif
well maybe a single prototype ;)
static inline void kmap_atomic_idx_pop(void)
{
#ifdef CONFIG_DEBUG_HIGHMEM
int idx = __this_cpu_dec_return(__kmap_atomic_idx);
BUG_ON(idx < 0);
#else
__this_cpu_dec(__kmap_atomic_idx);#endif
}
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 07/18] highmem: Use this_cpu_xx_return() operations
Quoted 5 lines · Eric Dumazet
well maybe a single prototype ;)
static inline void
kmap_atomic_idx_pop(void)
{
Quoted 7 lines
#ifdef CONFIG_DEBUG_HIGHMEM int idx = __this_cpu_dec_return(__kmap_atomic_idx); BUG_ON(idx < 0); #else __this_cpu_dec(__kmap_atomic_idx);#endif
}
Right, at least a consistent prototype, the above looks fine to me.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 07/18] highmem: Use this_cpu_xx_return() operations
Quoted 14 lines · Peter Zijlstra
Quoted 5 lines · Eric Dumazet
well maybe a single prototype ;)
static inline void
kmap_atomic_idx_pop(void)
{Quoted 7 lines
#ifdef CONFIG_DEBUG_HIGHMEM int idx = __this_cpu_dec_return(__kmap_atomic_idx); BUG_ON(idx < 0); #else __this_cpu_dec(__kmap_atomic_idx);#endif
}
Quoted 1 line
Right, at least a consistent prototype, the above looks fine to me.
Ok with right spacing this is:
Subject: highmem: Use this_cpu_dec instead of __this_cpu_dec_return if !DEBUG_HIGHMEM
--- include/linux/highmem.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
include/linux/highmem.h +5 -3
@@ -95,13 +95,15 @@ static inline int kmap_atomic_idx(void) return __this_cpu_read(__kmap_atomic_idx) - 1; } -static inline int kmap_atomic_idx_pop (void ) +static inline void kmap_atomic_idx_pop (void ) { -int idx =__this_cpu_dec_return (__kmap_atomic_idx);#ifdef CONFIG_DEBUG_HIGHMEM +int idx =__this_cpu_dec_return (__kmap_atomic_idx); +BUG_ON (idx <0 ); +#else +__this_cpu_dec (__kmap_atomic_idx);#endif -return idx; }#endif
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
[extra] timers: Use this_cpu_read
In reply to Christoph LameterSubject: timers: Use this_cpu_read
Eric asked for this.
--- kernel/timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/timer.c +2 -2
@@ -1249,7 +1249,7 @@ static unsigned long cmp_next_hrtimer_ev*/ unsigned long get_next_timer_interrupt (unsigned long now) { -struct tvec_base *base =__get_cpu_var (tvec_bases); +struct tvec_base *base =__this_cpu_read (tvec_bases);unsigned long expires;spin_lock (&base->lock);
@@ -1292,7 +1292,7 @@ void update_process_times(int user_tick)*/ static void run_timer_softirq (struct softirq_action *h) { -struct tvec_base *base =__get_cpu_var (tvec_bases); +struct tvec_base *base =__this_cpu_read (tvec_bases);hrtimer_run_pending ();
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 15/18] Xen: Use this_cpu_ops
In reply to Christoph Lameterarch/x86/xen/time.c static DEFINE_PER_CPU(struct clock_event · line 377
Quoted 10 lines · Christoph Lameter
static
irqreturn_txen_timer_interrupt(int irq, void *dev_id){arch/x86/xen/time.c +2
-3-struct clock_event_device *evt = &__get_cpu_var (xen_clock_events);irqreturn_t ret; ret =IRQ_NONE ; -if (evt->event_handler) { - evt->event_handler (evt); +if (__this_cpu_read (xen_clock_events.event_handler)) { +__this_cpu_read (xen_clock_events.event_handler)(evt);
Really? What code does this generate? If this is generating two segment-prefixed reads rather than getting the address and doing normal reads on it, then I don't think it is an improvement.
The rest looks OK, I guess. How does it change the generated code?
J
Re: [thisops uV3 15/18] Xen: Use this_cpu_ops
Quoted 6 lines · Jeremy Fitzhardinge
Quoted 5 lines · Christoph Lameter
static
irqreturn_txen_timer_interrupt(int irq, void *dev_id){arch/x86/xen/time.c +0
-1-struct clock_event_device *evt = &__get_cpu_var (xen_clock_events);irqreturn_t ret;
Quoted 9 lines
arch/x86/xen/time.c static DEFINE_PER_CPU(struct clock_event · line 377
Quoted 5 lines
arch/x86/xen/time.c +2
-2ret =IRQ_NONE ; -if (evt->event_handler) { - evt->event_handler (evt); +if (__this_cpu_read (xen_clock_events.event_handler)) { +__this_cpu_read (xen_clock_events.event_handler)(evt);Really? What code does this generate? If this is generating two segment-prefixed reads rather than getting the address and doing normal reads on it, then I don't think it is an improvement.
Lets drop that hunk. No point to do optimizations at that location then.
evt is also not defined then. Without the evt address determination via __get_cpu_var we have at least 2 prefixed load and one address calculation to figure out the parameter to pass. No win.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 08/18] Taskstats: Use this_cpu_ops
In reply to Christoph LameterHello Christoph,
Quoted 15 lines · Christoph Lameter
plain text document attachment (
this_cpu_taskstats)
Usethis_cpu_inc_returnin one place and avoid ugly__raw_get_cpuin another.Cc Michael Holzheu <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- kernel/taskstats.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)Index:
linux-2.6/kernel/taskstats.c
===================================================================
kernel/taskstats.c static int prepare_reply(struct genl_inf · line 92
Quoted 6 lines
kernel/taskstats.c +1
-2@@ -89,8 +89,7 @@ static int prepare_reply(struct genl_infreturn -ENOMEM ;if (!info) { -int seq =get_cpu_var (taskstats_seqnum)++; -put_cpu_var (taskstats_seqnum); +int seq =this_cpu_inc_return (taskstats_seqnum);
Hmmm, wouldn't seq now always be one more than before?
I think that "seq = get_cpu_var(taskstats_seqnum)++" first assigns taskstats_seqnum to seq and then increases the value in contrast to this_cpu_inc_return() that returns the already increased value, correct?
Maybe that does not hurt here, Balbir?
kernel/taskstats.c void taskstats_exit(struct task_struct * · line 586
Quoted 12 lines
kernel/taskstats.c +1
-1reply =genlmsg_put (skb,0 , seq, &family,0 , cmd); }else @@ -581,7 +580,7 @@ void taskstats_exit(struct task_struct *fill_tgid_exit (tsk); } - listeners = &__raw_get_cpu_var (listener_array); + listeners =__this_cpu_ptr (listener_array);if (list_empty (&listeners->list))return ;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 08/18] Taskstats: Use this_cpu_ops
Quoted 9 lines · Michael Holzheu
kernel/taskstats.c static int prepare_reply(struct genl_inf · line 92
Quoted 6 lines
kernel/taskstats.c +1
-2return -ENOMEM ;if (!info) { -int seq =get_cpu_var (taskstats_seqnum)++; -put_cpu_var (taskstats_seqnum); +int seq =this_cpu_inc_return (taskstats_seqnum);Hmmm, wouldn't seq now always be one more than before?
Quoted 3 lines
I think that "seq = get_cpu_var(taskstats_seqnum)++" first assigns
taskstats_seqnumto seq and then increases the value in contrast tothis_cpu_inc_return()that returns the already increased value, correct?
Correct. We need to subtract one from that (which will eliminate the minus -1 that the inline this_cpu_inc_return creates).
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 14/18] lguest: Use this_cpu_ops
In reply to Christoph LameterQuoted 4 lines · Christoph Lameter
Use
this_cpu_opsin a couple of places in lguest.Cc Rusty Russell <[email protected]>Signed-off-by Christoph Lameter <[email protected]>
This doesn't even compile :(
I've applied it, and applied the following fixes, too:
lguest: compile fixes
arch/x86/lguest/boot.c: In function ‘lguest_init_IRQ’:arch/x86/lguest/boot.c:824: error: macro "__this_cpu_write" requires 2 arguments, but only 1 given arch/x86/lguest/boot.c:824: error: ‘__this_cpu_write’ undeclared (first use in this function) arch/x86/lguest/boot.c:824: error: (Each undeclared identifier is reported only once arch/x86/lguest/boot.c:824: error: for each function it appears in.)
drivers/lguest/x86/core.c: In function ‘copy_in_guest_info’:drivers/lguest/x86/core.c:94: error: lvalue required as left operand of assignment
arch/x86/lguest/boot.c +1 -1
@@ -821,7 +821,7 @@ static void __init lguest_init_IRQ(void)for (i =FIRST_EXTERNAL_VECTOR ; i <NR_VECTORS ; i++) {/* Some systems map "vectors" to interrupts weirdly. Not us! */ -__this_cpu_write (vector_irq[i]) = i -FIRST_EXTERNAL_VECTOR ; +__this_cpu_write (vector_irq[i], i -FIRST_EXTERNAL_VECTOR );if (i !=SYSCALL_VECTOR )set_intr_gate (i, interrupt[i -FIRST_EXTERNAL_VECTOR ]); }
drivers/lguest/x86/core.c +1 -1
@@ -91,7 +91,7 @@ static void copy_in_guest_info(struct lg* Guest has changed. */ if (__this_cpu_read (lg_last_cpu) != cpu || cpu->last_pages != pages) { -__this_cpu_read (lg_last_cpu) = cpu; +__this_cpu_write (lg_last_cpu, cpu); cpu->last_pages = pages; cpu->changed =CHANGED_ALL ; }
Re: [thisops uV3 14/18] lguest: Use this_cpu_ops
Quoted 1 line · Rusty Russell
This doesn't even compile :(
Yeah. I had to go through a lot of code and the build process did not build all subsystem. Sorry.
Quoted 1 line
I've applied it, and applied the following fixes, too:
Great. Thanks.
Re: [thisops uV3 14/18] lguest: Use this_cpu_ops
I dropped the patch since it is now in Rusty's tree.
Re: [thisops uV3 08/18] Taskstats: Use this_cpu_ops
In reply to Christoph LameterQuoted 11 lines · Christoph Lameter
Quoted 9 lines · Michael Holzheu
kernel/taskstats.c static int prepare_reply(struct genl_inf · line 92
Quoted 6 lines
kernel/taskstats.c +1
-2return -ENOMEM ;if (!info) { -int seq =get_cpu_var (taskstats_seqnum)++; -put_cpu_var (taskstats_seqnum); +int seq =this_cpu_inc_return (taskstats_seqnum);Hmmm, wouldn't seq now always be one more than before?
Quoted 7 lines
Quoted 3 lines
I think that "seq = get_cpu_var(taskstats_seqnum)++" first assigns
taskstats_seqnumto seq and then increases the value in contrast tothis_cpu_inc_return()that returns the already increased value, correct?Correct. We need to subtract one from that (which will eliminate the minus -1 that the inline
this_cpu_inc_returncreates).
But that breaks current behaviour, we should probably initialize all of the array to -1?
Signature · 9 lines
Three Cheers, Balbir -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/ Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [thisops uV3 08/18] Taskstats: Use this_cpu_ops
Quoted 6 lines · Balbir Singh
Quoted 3 lines
Correct. We need to subtract one from that (which will eliminate the minus -1 that the inline
this_cpu_inc_returncreates).But that breaks current behaviour, we should probably initialize all of the array to -1?
Not necessary. This_cpu_inc() uses an xadd instruction which retrieves the value and then increments the memory location. Then it adds 1. The -1 eliminates that add.
[tip:timers/core] timers: Use this_cpu_read
In reply to Christoph LameterCommit-ID: 7496351ad87e61e96b49dd7b43c6534e3401f566 Gitweb: http://git.kernel.org/tip/7496351ad87e61e96b49dd7b43c6534e3401f566 Author: Christoph Lameter <[email protected]> AuthorDate: Tue, 30 Nov 2010 14:05:53 -0600 Committer: Thomas Gleixner <[email protected]> CommitDate: Sun, 12 Dec 2010 18:38:09 +0100
timers: Use this_cpu_read
Eric asked for this.
[tglx: Because it generates faster code according to Erics ]
LKML-Reference: <[email protected]>
--- kernel/timer.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
kernel/timer.c +2 -2
@@ -1227,7 +1227,7 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,*/ unsigned long get_next_timer_interrupt (unsigned long now) { -struct tvec_base *base =__get_cpu_var (tvec_bases); +struct tvec_base *base =__this_cpu_read (tvec_bases);unsigned long expires;spin_lock (&base->lock);
@@ -1267,7 +1267,7 @@ void update_process_times(int user_tick)*/ static void run_timer_softirq (struct softirq_action *h) { -struct tvec_base *base =__get_cpu_var (tvec_bases); +struct tvec_base *base =__this_cpu_read (tvec_bases);hrtimer_run_pending ();