aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorConstantine Gavrilov <constg@qlusters.com>2005-11-17 04:40:43 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-17 11:42:26 -0500
commitb7fd1edd2c0c225afa96af92d4adecb91e7d439d (patch)
tree5e8d4cbc6d16eb318bc7df102b39a09056981817
parent3b26b1100e26811e54770abaa221eae140ba840d (diff)
[PATCH] x86: fix sigaddset() inline asm memory constraint
Due to incomplete memory constraints, gcc would miscompile code with sigaddset on i386 if sig arg was const. A quote form Jakub to make the issue clear: "You need either __asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig-1) : "cc"); or __asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig-1), "m"(*set) : "cc"); because the btsl instruction doesn't just set the memory to some value, but needs to read its previous content as well. If you don't tell that fact to GCC, GCC is of course free to optimize as if the asm was just setting the value and not depended on the previous value." Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/asm-i386/signal.h31
1 files changed, 27 insertions, 4 deletions
diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h
index cbb47d34aa31..6ba29f145bf8 100644
--- a/include/asm-i386/signal.h
+++ b/include/asm-i386/signal.h
@@ -159,14 +159,37 @@ typedef struct sigaltstack {
159 159
160#define __HAVE_ARCH_SIG_BITOPS 160#define __HAVE_ARCH_SIG_BITOPS
161 161
162static __inline__ void sigaddset(sigset_t *set, int _sig) 162#define sigaddset(set,sig) \
163 (__builtin_constant_p(sig) ? \
164 __const_sigaddset((set),(sig)) : \
165 __gen_sigaddset((set),(sig)))
166
167static __inline__ void __gen_sigaddset(sigset_t *set, int _sig)
163{ 168{
164 __asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc"); 169 __asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
165} 170}
166 171
167static __inline__ void sigdelset(sigset_t *set, int _sig) 172static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
168{ 173{
169 __asm__("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc"); 174 unsigned long sig = _sig - 1;
175 set->sig[sig / _NSIG_BPW] |= 1 << (sig % _NSIG_BPW);
176}
177
178#define sigdelset(set,sig) \
179 (__builtin_constant_p(sig) ? \
180 __const_sigdelset((set),(sig)) : \
181 __gen_sigdelset((set),(sig)))
182
183
184static __inline__ void __gen_sigdelset(sigset_t *set, int _sig)
185{
186 __asm__("btrl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
187}
188
189static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
190{
191 unsigned long sig = _sig - 1;
192 set->sig[sig / _NSIG_BPW] &= ~(1 << (sig % _NSIG_BPW));
170} 193}
171 194
172static __inline__ int __const_sigismember(sigset_t *set, int _sig) 195static __inline__ int __const_sigismember(sigset_t *set, int _sig)