[PATCH] i386: generic cmpxchg
- Make cmpxchg generally available on the i386 platform. - Provide emulation of cmpxchg suitable for uniprocessor if built and run on 386. From: Christoph Lameter <clameter@sgi.com> - Cut down patch and small style changes. Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Christoph Lameter <clameter@sgi.com> Cc: "Paul E. McKenney" <paulmck@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
dbdf65b1b7
commit
53e86b91b7
@ -6,6 +6,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/msr.h>
|
||||
@ -264,5 +265,52 @@ __init int intel_cpu_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
// arch_initcall(intel_cpu_init);
|
||||
|
||||
|
@ -263,6 +263,10 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
|
||||
|
||||
#ifdef CONFIG_X86_CMPXCHG
|
||||
#define __HAVE_ARCH_CMPXCHG 1
|
||||
#define cmpxchg(ptr,o,n)\
|
||||
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
|
||||
(unsigned long)(n),sizeof(*(ptr))))
|
||||
#endif
|
||||
|
||||
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
|
||||
unsigned long new, int size)
|
||||
@ -291,10 +295,42 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
|
||||
return old;
|
||||
}
|
||||
|
||||
#define cmpxchg(ptr,o,n)\
|
||||
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
|
||||
(unsigned long)(n),sizeof(*(ptr))))
|
||||
#ifndef CONFIG_X86_CMPXCHG
|
||||
/*
|
||||
* Building a kernel capable running on 80386. It may be necessary to
|
||||
* simulate the cmpxchg on the 80386 CPU. For that purpose we define
|
||||
* a function for each of the sizes we support.
|
||||
*/
|
||||
|
||||
extern unsigned long cmpxchg_386_u8(volatile void *, u8, u8);
|
||||
extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16);
|
||||
extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32);
|
||||
|
||||
static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
|
||||
unsigned long new, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return cmpxchg_386_u8(ptr, old, new);
|
||||
case 2:
|
||||
return cmpxchg_386_u16(ptr, old, new);
|
||||
case 4:
|
||||
return cmpxchg_386_u32(ptr, old, new);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
#define cmpxchg(ptr,o,n) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) __ret; \
|
||||
if (likely(boot_cpu_data.x86 > 3)) \
|
||||
__ret = __cmpxchg((ptr), (unsigned long)(o), \
|
||||
(unsigned long)(n), sizeof(*(ptr))); \
|
||||
else \
|
||||
__ret = cmpxchg_386((ptr), (unsigned long)(o), \
|
||||
(unsigned long)(n), sizeof(*(ptr))); \
|
||||
__ret; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_CMPXCHG64
|
||||
|
Loading…
Reference in New Issue
Block a user