diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-06 10:07:34 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-06 10:07:34 -0700 |
commit | d9a73c00161f3eaa4c8c035c62f45afd1549e38a (patch) | |
tree | c5cad9e1e286438b63e512c1912e8b7f39071886 /arch/x86/lib | |
parent | b304441c6f3a5cb5ea80b9a719d2851544f348d6 (diff) | |
parent | bf676945cb5bfe455321f57968967c18976f4995 (diff) | |
download | linux-d9a73c00161f3eaa4c8c035c62f45afd1549e38a.tar.gz linux-d9a73c00161f3eaa4c8c035c62f45afd1549e38a.tar.bz2 linux-d9a73c00161f3eaa4c8c035c62f45afd1549e38a.zip |
Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
um, x86: Cast to (u64 *) inside set_64bit()
x86-32, asm: Directly access per-cpu GDT
x86-64, asm: Directly access per-cpu IST
x86, asm: Merge cmpxchg_486_u64() and cmpxchg8b_emu()
x86, asm: Move cmpxchg emulation code to arch/x86/lib
x86, asm: Clean up and simplify <asm/cmpxchg.h>
x86, asm: Clean up and simplify set_64bit()
x86: Add memory modify constraints to xchg() and cmpxchg()
x86-64: Simplify loading initial_gs
x86: Use symbolic MSR names
x86: Remove redundant K6 MSRs
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/lib/cmpxchg.c | 54 |
2 files changed, 55 insertions, 0 deletions
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index f871e04b6965..e10cf070ede0 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -30,6 +30,7 @@ ifeq ($(CONFIG_X86_32),y) lib-y += checksum_32.o lib-y += strstr_32.o lib-y += semaphore_32.o string_32.o + lib-y += cmpxchg.o ifneq ($(CONFIG_X86_CMPXCHG64),y) lib-y += cmpxchg8b_emu.o atomic64_386_32.o endif diff --git a/arch/x86/lib/cmpxchg.c b/arch/x86/lib/cmpxchg.c new file mode 100644 index 000000000000..5d619f6df3ee --- /dev/null +++ b/arch/x86/lib/cmpxchg.c @@ -0,0 +1,54 @@ +/* + * cmpxchg*() fallbacks for CPU not supporting these instructions + */ + +#include <linux/kernel.h> +#include <linux/smp.h> +#include <linux/module.h> + +#ifndef CONFIG_X86_CMPXCHG +unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) +{ + u8 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u8 *)ptr; + if (prev == old) + *(u8 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u8); + +unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new) +{ + u16 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u16 *)ptr; + if (prev == old) + *(u16 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u16); + +unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) +{ + u32 prev; + unsigned long flags; + + /* Poor man's cmpxchg for 386. Unsuitable for SMP */ + local_irq_save(flags); + prev = *(u32 *)ptr; + if (prev == old) + *(u32 *)ptr = new; + local_irq_restore(flags); + return prev; +} +EXPORT_SYMBOL(cmpxchg_386_u32); +#endif |