Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4e3b5cc authored by Tom Rini's avatar Tom Rini Committed by Paul Mundt
Browse files

sh: Add a simple cmpxchg().



We didn't have one of these before, a simple implementation
borrowed from MIPS as well as the __HAVE_ARCH_CMPXCHG bits.

Signed-off-by: default avatarTom Rini <trini@kernel.crashing.org>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 0c91c1a7
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 * Copyright (C) 2002 Paul Mundt
 */

#include <asm/types.h>

/*
 *	switch_to() should switch tasks to task nr n, first
@@ -260,6 +261,45 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int
	return x;
}

static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
	unsigned long new)
{
	__u32 retval;
	unsigned long flags;

	local_irq_save(flags);
	retval = *m;
	if (retval == old)
		*m = new;
	local_irq_restore(flags);       /* implies memory barrier  */
	return retval;
}

/* 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 __HAVE_ARCH_CMPXCHG 1

static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
		unsigned long new, int size)
{
	switch (size) {
	case 4:
		return __cmpxchg_u32(ptr, old, new);
	}
	__cmpxchg_called_with_bad_pointer();
	return old;
}

#define cmpxchg(ptr,o,n)						 \
  ({									 \
     __typeof__(*(ptr)) _o_ = (o);					 \
     __typeof__(*(ptr)) _n_ = (n);					 \
     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
				    (unsigned long)_n_, sizeof(*(ptr))); \
  })

/* XXX
 * disable hlt during certain critical i/o operations
 */