Fix the m68k versions of xchg() and cmpxchg() to fail to link if given an
inappropriately sized pointer rather than BUG()'ing at runtime.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Greg Ungerer <gerg@uclinux.org>
cc: linux-m68k@lists.linux-m68k.org
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((volatile struct __xchg_dummy *)(x))
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+extern unsigned long __invalid_xchg_size(unsigned long, volatile void *, int);
+
#ifndef CONFIG_RMW_INSNS
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
#ifndef CONFIG_RMW_INSNS
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
+ tmp = __invalid_xchg_size(x, ptr, size);
+ break;
}
local_irq_restore(flags);
}
local_irq_restore(flags);
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
switch (size) {
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
switch (size) {
__asm__ __volatile__
("moveb %2,%0\n\t"
"1:\n\t"
__asm__ __volatile__
("moveb %2,%0\n\t"
"1:\n\t"
"jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break;
"jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break;
__asm__ __volatile__
("movew %2,%0\n\t"
"1:\n\t"
__asm__ __volatile__
("movew %2,%0\n\t"
"1:\n\t"
"jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break;
"jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break;
__asm__ __volatile__
("movel %2,%0\n\t"
"1:\n\t"
__asm__ __volatile__
("movel %2,%0\n\t"
"1:\n\t"
"jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break;
"jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break;
+ default:
+ x = __invalid_xchg_size(x, ptr, size);
+ break;
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+extern unsigned long __invalid_cmpxchg_size(volatile void *,
+ unsigned long, unsigned long, int);
+
/*
* Atomic compare and exchange. Compare OLD with MEM, if identical,
* store NEW in MEM. Return the initial value in MEM. Success is
/*
* Atomic compare and exchange. Compare OLD with MEM, if identical,
* store NEW in MEM. Return the initial value in MEM. Success is
: "=d" (old), "=m" (*(int *)p)
: "d" (new), "0" (old), "m" (*(int *)p));
break;
: "=d" (old), "=m" (*(int *)p)
: "d" (new), "0" (old), "m" (*(int *)p));
break;
+ default:
+ old = __invalid_cmpxchg_size(p, old, new, size);
+ break;