diff options
author | Peter Zijlstra <peterz@infradead.org> | 2013-09-11 09:19:24 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-09-25 07:53:08 -0400 |
commit | 0c44c2d0f459cd7e275242b72f500137c4fa834d (patch) | |
tree | fdd16d5585a986cf8cbed140f533d08d152bbc4f /arch/x86/include/asm/local.h | |
parent | 4314895165623879937f46d767673654662b570c (diff) |
x86: Use asm goto to implement better modify_and_test() functions
Linus suggested using asm goto to get rid of the typical SETcc + TEST
instruction pair -- which also clobbers an extra register -- for our
typical modify_and_test() functions.
Because asm goto doesn't allow output fields it has to include an
unconditinal memory clobber when it changes a memory variable to force
a reload.
Luckily all atomic ops already imply a compiler barrier to go along
with their memory barrier semantics.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/n/tip-0mtn9siwbeo1d33bap1422se@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/include/asm/local.h')
-rw-r--r-- | arch/x86/include/asm/local.h | 28 |
1 files changed, 4 insertions, 24 deletions
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h index 2d89e3980cbd..5b23e605e707 100644 --- a/arch/x86/include/asm/local.h +++ b/arch/x86/include/asm/local.h | |||
@@ -52,12 +52,7 @@ static inline void local_sub(long i, local_t *l) | |||
52 | */ | 52 | */ |
53 | static inline int local_sub_and_test(long i, local_t *l) | 53 | static inline int local_sub_and_test(long i, local_t *l) |
54 | { | 54 | { |
55 | unsigned char c; | 55 | GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, i, "%0", "e"); |
56 | |||
57 | asm volatile(_ASM_SUB "%2,%0; sete %1" | ||
58 | : "+m" (l->a.counter), "=qm" (c) | ||
59 | : "ir" (i) : "memory"); | ||
60 | return c; | ||
61 | } | 56 | } |
62 | 57 | ||
63 | /** | 58 | /** |
@@ -70,12 +65,7 @@ static inline int local_sub_and_test(long i, local_t *l) | |||
70 | */ | 65 | */ |
71 | static inline int local_dec_and_test(local_t *l) | 66 | static inline int local_dec_and_test(local_t *l) |
72 | { | 67 | { |
73 | unsigned char c; | 68 | GEN_UNARY_RMWcc(_ASM_DEC, l->a.counter, "%0", "e"); |
74 | |||
75 | asm volatile(_ASM_DEC "%0; sete %1" | ||
76 | : "+m" (l->a.counter), "=qm" (c) | ||
77 | : : "memory"); | ||
78 | return c != 0; | ||
79 | } | 69 | } |
80 | 70 | ||
81 | /** | 71 | /** |
@@ -88,12 +78,7 @@ static inline int local_dec_and_test(local_t *l) | |||
88 | */ | 78 | */ |
89 | static inline int local_inc_and_test(local_t *l) | 79 | static inline int local_inc_and_test(local_t *l) |
90 | { | 80 | { |
91 | unsigned char c; | 81 | GEN_UNARY_RMWcc(_ASM_INC, l->a.counter, "%0", "e"); |
92 | |||
93 | asm volatile(_ASM_INC "%0; sete %1" | ||
94 | : "+m" (l->a.counter), "=qm" (c) | ||
95 | : : "memory"); | ||
96 | return c != 0; | ||
97 | } | 82 | } |
98 | 83 | ||
99 | /** | 84 | /** |
@@ -107,12 +92,7 @@ static inline int local_inc_and_test(local_t *l) | |||
107 | */ | 92 | */ |
108 | static inline int local_add_negative(long i, local_t *l) | 93 | static inline int local_add_negative(long i, local_t *l) |
109 | { | 94 | { |
110 | unsigned char c; | 95 | GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, i, "%0", "s"); |
111 | |||
112 | asm volatile(_ASM_ADD "%2,%0; sets %1" | ||
113 | : "+m" (l->a.counter), "=qm" (c) | ||
114 | : "ir" (i) : "memory"); | ||
115 | return c; | ||
116 | } | 96 | } |
117 | 97 | ||
118 | /** | 98 | /** |