| To: | Ralf Baechle <ralf@linux-mips.org> |
|---|---|
| Subject: | Re: cmpxchg broken in some situation |
| From: | Thiemo Seufer <ths@networkno.de> |
| Date: | Tue, 2 Oct 2007 15:22:10 +0100 |
| Cc: | Fuxin Zhang <fxzhang@ict.ac.cn>, linux-mips@linux-mips.org |
| In-reply-to: | <20071002103551.GB5152@linux-mips.org> |
| Original-recipient: | rfc822;linux-mips@linux-mips.org |
| References: | <46FF7BC2.5050905@ict.ac.cn> <20071001025340.GA7091@linux-mips.org> <47010E15.7060109@ict.ac.cn> <20071001152620.GB15820@linux-mips.org> <470210B4.8020902@ict.ac.cn> <20071002103551.GB5152@linux-mips.org> |
| Sender: | linux-mips-bounce@linux-mips.org |
| User-agent: | Mutt/1.5.16 (2007-06-11) |
Ralf Baechle wrote:
> On Tue, Oct 02, 2007 at 05:34:44PM +0800, Fuxin Zhang wrote:
>
> > The problem is here:
> >
> > switch (sizeof(__ptr)) { // --> should be sizeof(*(__ptr))
> > case 4:
> > ...
> > Recompiling..
>
> There was another small kink, cmpxchg_local() does not imply a memory
> barrier so I optimized that case.
>
> And I don't complain about it being 151 lines shorter ;-)
>
> Ralf
>
> From: Ralf Baechle <ralf@linux-mips.org>
>
> [MIPS] Typeproof reimplementation of cmpxchg.
>
> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
>
> diff --git a/include/asm-mips/cmpxchg.h b/include/asm-mips/cmpxchg.h
> new file mode 100644
> index 0000000..46bac47
> --- /dev/null
> +++ b/include/asm-mips/cmpxchg.h
> @@ -0,0 +1,107 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2003, 06, 07 by Ralf Baechle (ralf@linux-mips.org)
> + */
> +#ifndef __ASM_CMPXCHG_H
> +#define __ASM_CMPXCHG_H
> +
> +#include <linux/irqflags.h>
> +
> +#define __HAVE_ARCH_CMPXCHG 1
> +
> +#define __cmpxchg_asm(ld, st, m, old, new) \
> +({ \
> + __typeof(*(m)) __ret; \
> + \
> + if (cpu_has_llsc && R10000_LLSC_WAR) { \
> + __asm__ __volatile__( \
> + " .set push \n" \
> + " .set noat \n" \
> + " .set mips3 \n" \
> + "1: " ld " %0, %2 # __cmpxchg_u32 \n" \
> + " bne %0, %z3, 2f \n" \
> + " .set mips0 \n" \
> + " move $1, %z4 \n" \
> + " .set mips3 \n" \
> + " " st " $1, %1 \n" \
> + " beqzl $1, 1b \n" \
> + "2: \n" \
> + " .set pop \n" \
> + : "=&r" (__ret), "=R" (*m) \
> + : "R" (*m), "Jr" (old), "Jr" (new) \
> + : "memory"); \
> + } else if (cpu_has_llsc) { \
> + __asm__ __volatile__( \
> + " .set push \n" \
> + " .set noat \n" \
> + " .set mips3 \n" \
> + "1: " ld " %0, %2 # __cmpxchg_u32 \n" \
> + " bne %0, %z3, 2f \n" \
> + " .set mips0 \n" \
> + " move $1, %z4 \n" \
> + " .set mips3 \n" \
> + " " st " $1, %1 \n" \
> + " beqz $1, 3f \n" \
> + "2: \n" \
> + " .subsection 2 \n" \
> + "3: b 1b \n" \
> + " .previous \n" \
> + " .set pop \n" \
> + : "=&r" (__ret), "=R" (*m) \
> + : "R" (*m), "Jr" (old), "Jr" (new) \
> + : "memory"); \
> + } else { \
> + unsigned long __flags; \
> + \
> + raw_local_irq_save(__flags); \
> + __ret = *m; \
> + if (__ret == old) \
> + *m = new; \
> + raw_local_irq_restore(__flags); \
> + } \
> + \
> + smp_llsc_mb(); \
I think this line is surplus.
> + \
> + __ret; \
> +})
> +
> +/*
> + * This function doesn't exist, so you'll get a linker error
> + * if something tries to do an invalid cmpxchg().
> + */
> +extern void __cmpxchg_called_with_bad_pointer(void);
> +
> +#define __cmpxchg(ptr,old,new,barrier)
> \
> +({ \
> + __typeof__(ptr) __ptr = (ptr); \
> + __typeof__(*(ptr)) __old = (old); \
> + __typeof__(*(ptr)) __new = (new); \
> + __typeof__(*(ptr)) __res = 0; \
Maybe we need an acquire barrier here for some systems.
> + switch (sizeof(*(__ptr))) { \
> + case 4: \
> + __res = __cmpxchg_asm("ll", "sc", __ptr, __old, __new); \
> + break; \
> + case 8: \
> + if (sizeof(long) == 8) { \
> + __res = __cmpxchg_asm("lld", "scd", __ptr, \
> + __old, __new); \
> + break; \
> + } \
> + default: \
> + __cmpxchg_called_with_bad_pointer(); \
> + break; \
> + } \
> + \
> + barrier; \
> + \
> + __res; \
> +})
> +
> +#define cmpxchg(ptr, old, new) __cmpxchg(ptr, old, new,
> smp_llsc_mb())
> +#define cmpxchg_local(ptr, old, new) __cmpxchg(ptr, old, new,)
> +
> +#endif /* __ASM_CMPXCHG_H */
Thiemo
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| ||
| Previous by Date: | Re: [PATCH] mm/pg-r4k.c: Dump the generated code, Thiemo Seufer |
|---|---|
| Next by Date: | [PATCH][4/4] remove cobalt_machine_power_off(), Yoichi Yuasa |
| Previous by Thread: | Re: cmpxchg broken in some situation, Ralf Baechle |
| Next by Thread: | Re: cmpxchg broken in some situation, Ralf Baechle |
| Indexes: | [Date] [Thread] [Top] [All Lists] |