From 0e03bb6d6495ac91b0ccf9263ab162352570e290 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 18 Jun 2008 21:03:26 -0700 Subject: [PATCH] --- yaml --- r: 99352 b: refs/heads/master c: 1a750e0cd7a30c478723ecfa1df685efcdd38a90 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/asm-x86/bitops.h | 28 +++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index fbfb0f7bbce4..39802ea86684 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5136dea5734cfddbc6d7ccb7ead85a3ac7ce3de2 +refs/heads/master: 1a750e0cd7a30c478723ecfa1df685efcdd38a90 diff --git a/trunk/include/asm-x86/bitops.h b/trunk/include/asm-x86/bitops.h index 7d2494bdc660..ab7635a4acd9 100644 --- a/trunk/include/asm-x86/bitops.h +++ b/trunk/include/asm-x86/bitops.h @@ -23,11 +23,22 @@ #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) /* Technically wrong, but this avoids compilation errors on some gcc versions. */ -#define ADDR "=m" (*(volatile long *) addr) +#define BITOP_ADDR(x) "=m" (*(volatile long *) (x)) #else -#define ADDR "+m" (*(volatile long *) addr) +#define BITOP_ADDR(x) "+m" (*(volatile long *) (x)) #endif +#define ADDR BITOP_ADDR(addr) + +/* + * We do the locked ops that don't return the old value as + * a mask operation on a byte. + */ +#define IS_IMMEDIATE(nr) \ + (__builtin_constant_p(nr)) +#define CONST_MASK_ADDR BITOP_ADDR(addr + (nr>>3)) +#define CONST_MASK (1 << (nr & 7)) + /** * set_bit - Atomically set a bit in memory * @nr: the bit to set @@ -43,11 +54,15 @@ * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static inline void set_bit(int nr, volatile unsigned long *addr) +static inline void set_bit(unsigned int nr, volatile unsigned long *addr) { - asm volatile(LOCK_PREFIX "bts %1,%0" : ADDR : "Ir" (nr) : "memory"); + if (IS_IMMEDIATE(nr)) + asm volatile(LOCK_PREFIX "orb %1,%0" : CONST_MASK_ADDR : "i" (CONST_MASK) : "memory"); + else + asm volatile(LOCK_PREFIX "bts %1,%0" : ADDR : "Ir" (nr) : "memory"); } + /** * __set_bit - Set a bit in memory * @nr: the bit to set @@ -74,7 +89,10 @@ static inline void __set_bit(int nr, volatile unsigned long *addr) */ static inline void clear_bit(int nr, volatile unsigned long *addr) { - asm volatile(LOCK_PREFIX "btr %1,%0" : ADDR : "Ir" (nr)); + if (IS_IMMEDIATE(nr)) + asm volatile(LOCK_PREFIX "andb %1,%0" : CONST_MASK_ADDR : "i" (~CONST_MASK)); + else + asm volatile(LOCK_PREFIX "btr %1,%0" : ADDR : "Ir" (nr)); } /*