aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorGreg Thelen <gthelen@google.com>2013-10-30 16:56:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-10-30 17:27:03 -0400
commitbd09d9a35111b6ffc0c7585d3853d0ec7f9f1eb4 (patch)
treed2183dd9349217860e07bb12ba9a6b6a3820b7ba /include
parent3017f079efd6af199b0852b5c425364513db460e (diff)
percpu: fix this_cpu_sub() subtrahend casting for unsigneds
this_cpu_sub() is implemented as negation and addition. This patch casts the adjustment to the counter type before negation to sign extend the adjustment. This helps in cases where the counter type is wider than an unsigned adjustment. An alternative to this patch is to declare such operations unsupported, but it seemed useful to avoid surprises. This patch specifically helps the following example: unsigned int delta = 1 preempt_disable() this_cpu_write(long_counter, 0) this_cpu_sub(long_counter, delta) preempt_enable() Before this change long_counter on a 64 bit machine ends with value 0xffffffff, rather than 0xffffffffffffffff. This is because this_cpu_sub(pcp, delta) boils down to this_cpu_add(pcp, -delta), which is basically: long_counter = 0 + 0xffffffff Also apply the same cast to: __this_cpu_sub() __this_cpu_sub_return() this_cpu_sub_return() All percpu_test.ko passes, especially the following cases which previously failed: l -= ui_one; __this_cpu_sub(long_counter, ui_one); CHECK(l, long_counter, -1); l -= ui_one; this_cpu_sub(long_counter, ui_one); CHECK(l, long_counter, -1); CHECK(l, long_counter, 0xffffffffffffffff); ul -= ui_one; __this_cpu_sub(ulong_counter, ui_one); CHECK(ul, ulong_counter, -1); CHECK(ul, ulong_counter, 0xffffffffffffffff); ul = this_cpu_sub_return(ulong_counter, ui_one); CHECK(ul, ulong_counter, 2); ul = __this_cpu_sub_return(ulong_counter, ui_one); CHECK(ul, ulong_counter, 1); Signed-off-by: Greg Thelen <gthelen@google.com> Acked-by: Tejun Heo <tj@kernel.org> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/percpu.h8
1 files changed, 4 insertions, 4 deletions
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index cc88172c7d9a..c74088ab103b 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -332,7 +332,7 @@ do { \
332#endif 332#endif
333 333
334#ifndef this_cpu_sub 334#ifndef this_cpu_sub
335# define this_cpu_sub(pcp, val) this_cpu_add((pcp), -(val)) 335# define this_cpu_sub(pcp, val) this_cpu_add((pcp), -(typeof(pcp))(val))
336#endif 336#endif
337 337
338#ifndef this_cpu_inc 338#ifndef this_cpu_inc
@@ -418,7 +418,7 @@ do { \
418# define this_cpu_add_return(pcp, val) __pcpu_size_call_return2(this_cpu_add_return_, pcp, val) 418# define this_cpu_add_return(pcp, val) __pcpu_size_call_return2(this_cpu_add_return_, pcp, val)
419#endif 419#endif
420 420
421#define this_cpu_sub_return(pcp, val) this_cpu_add_return(pcp, -(val)) 421#define this_cpu_sub_return(pcp, val) this_cpu_add_return(pcp, -(typeof(pcp))(val))
422#define this_cpu_inc_return(pcp) this_cpu_add_return(pcp, 1) 422#define this_cpu_inc_return(pcp) this_cpu_add_return(pcp, 1)
423#define this_cpu_dec_return(pcp) this_cpu_add_return(pcp, -1) 423#define this_cpu_dec_return(pcp) this_cpu_add_return(pcp, -1)
424 424
@@ -586,7 +586,7 @@ do { \
586#endif 586#endif
587 587
588#ifndef __this_cpu_sub 588#ifndef __this_cpu_sub
589# define __this_cpu_sub(pcp, val) __this_cpu_add((pcp), -(val)) 589# define __this_cpu_sub(pcp, val) __this_cpu_add((pcp), -(typeof(pcp))(val))
590#endif 590#endif
591 591
592#ifndef __this_cpu_inc 592#ifndef __this_cpu_inc
@@ -668,7 +668,7 @@ do { \
668 __pcpu_size_call_return2(__this_cpu_add_return_, pcp, val) 668 __pcpu_size_call_return2(__this_cpu_add_return_, pcp, val)
669#endif 669#endif
670 670
671#define __this_cpu_sub_return(pcp, val) __this_cpu_add_return(pcp, -(val)) 671#define __this_cpu_sub_return(pcp, val) __this_cpu_add_return(pcp, -(typeof(pcp))(val))
672#define __this_cpu_inc_return(pcp) __this_cpu_add_return(pcp, 1) 672#define __this_cpu_inc_return(pcp) __this_cpu_add_return(pcp, 1)
673#define __this_cpu_dec_return(pcp) __this_cpu_add_return(pcp, -1) 673#define __this_cpu_dec_return(pcp) __this_cpu_add_return(pcp, -1)
674 674