atomic.h revision 7224c0d1045327d637dab2c90777b6d5ec6d6804
169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifndef __ARCH_M68K_ATOMIC__
269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define __ARCH_M68K_ATOMIC__
369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#include <linux/types.h>
5803f69144f0d48863c68f9d111b56849c7cef5bbDavid Howells#include <linux/irqflags.h>
67224c0d1045327d637dab2c90777b6d5ec6d6804Greg Ungerer#include <asm/cmpxchg.h>
769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/*
969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * Atomic operations that C can't guarantee us.  Useful for
1069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * resource counting etc..
1169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */
1269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
1369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/*
1469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * We do not have SMP m68k systems, so we don't have to deal with that.
1569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */
1669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
1769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define ATOMIC_INIT(i)	{ (i) }
1869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
1969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_read(v)		(*(volatile int *)&(v)->counter)
2069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_set(v, i)	(((v)->counter) = i)
2169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
2269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/*
2369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * The ColdFire parts cannot do some immediate to memory operations,
2469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * so for them we do not specify the "i" asm constraint.
2569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */
2669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifdef CONFIG_COLDFIRE
2769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define	ASM_DI	"d"
2849148020bcb6910ce71417bd990a5ce7017f9bd3Sam Ravnborg#else
2969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define	ASM_DI	"di"
3049148020bcb6910ce71417bd990a5ce7017f9bd3Sam Ravnborg#endif
31b417b717093085e45867770b29b9a97692cf132aGeert Uytterhoeven
3269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_add(int i, atomic_t *v)
3369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
3469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI (i));
3569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
3669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
3769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_sub(int i, atomic_t *v)
3869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
3969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI (i));
4069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
4169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
4269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_inc(atomic_t *v)
4369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
4469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__("addql #1,%0" : "+m" (*v));
4569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
4669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
4769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_dec(atomic_t *v)
4869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
4969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__("subql #1,%0" : "+m" (*v));
5069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
5169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
5269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_dec_and_test(atomic_t *v)
5369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
5469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	char c;
5569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
5669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return c != 0;
5769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
5869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
5983b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungererstatic inline int atomic_dec_and_test_lt(atomic_t *v)
6083b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer{
6183b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer	char c;
6283b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer	__asm__ __volatile__(
6383b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer		"subql #1,%1; slt %0"
6483b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer		: "=d" (c), "=m" (*v)
6583b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer		: "m" (*v));
6683b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer	return c != 0;
6783b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer}
6883b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer
6969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_inc_and_test(atomic_t *v)
7069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
7169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	char c;
7269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
7369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return c != 0;
7469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
7569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
7669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifdef CONFIG_RMW_INSNS
7769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
7869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_add_return(int i, atomic_t *v)
7969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
8069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	int t, tmp;
8169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
8269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__(
8369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			"1:	movel %2,%1\n"
8469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			"	addl %3,%1\n"
8569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			"	casl %2,%1,%0\n"
8669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			"	jne 1b"
8769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			: "+m" (*v), "=&d" (t), "=&d" (tmp)
8869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			: "g" (i), "2" (atomic_read(v)));
8969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return t;
9069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
9169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
9269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_sub_return(int i, atomic_t *v)
9369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
9469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	int t, tmp;
9569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
9669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__(
9769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			"1:	movel %2,%1\n"
9869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			"	subl %3,%1\n"
9969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			"	casl %2,%1,%0\n"
10069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			"	jne 1b"
10169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			: "+m" (*v), "=&d" (t), "=&d" (tmp)
10269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			: "g" (i), "2" (atomic_read(v)));
10369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return t;
10469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
10569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
10669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
10769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
10869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
10969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#else /* !CONFIG_RMW_INSNS */
11069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
11169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_add_return(int i, atomic_t * v)
11269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
11369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	unsigned long flags;
11469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	int t;
11569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
11669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	local_irq_save(flags);
11769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	t = atomic_read(v);
11869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	t += i;
11969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	atomic_set(v, t);
12069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	local_irq_restore(flags);
12169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
12269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return t;
12369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
12469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
12569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_sub_return(int i, atomic_t * v)
12669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
12769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	unsigned long flags;
12869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	int t;
12969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
13069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	local_irq_save(flags);
13169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	t = atomic_read(v);
13269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	t -= i;
13369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	atomic_set(v, t);
13469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	local_irq_restore(flags);
13569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
13669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return t;
13769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
13869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
13969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_cmpxchg(atomic_t *v, int old, int new)
14069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
14169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	unsigned long flags;
14269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	int prev;
14369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
14469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	local_irq_save(flags);
14569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	prev = atomic_read(v);
14669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	if (prev == old)
14769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer		atomic_set(v, new);
14869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	local_irq_restore(flags);
14969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return prev;
15069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
15169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
15269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_xchg(atomic_t *v, int new)
15369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
15469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	unsigned long flags;
15569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	int prev;
15669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
15769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	local_irq_save(flags);
15869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	prev = atomic_read(v);
15969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	atomic_set(v, new);
16069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	local_irq_restore(flags);
16169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return prev;
16269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
16369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
16469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#endif /* !CONFIG_RMW_INSNS */
16569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
16669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_dec_return(v)	atomic_sub_return(1, (v))
16769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_inc_return(v)	atomic_add_return(1, (v))
16869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
16969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_sub_and_test(int i, atomic_t *v)
17069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
17169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	char c;
17269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__("subl %2,%1; seq %0"
17369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			     : "=d" (c), "+m" (*v)
17469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			     : ASM_DI (i));
17569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return c != 0;
17669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
17769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
17869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_add_negative(int i, atomic_t *v)
17969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
18069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	char c;
18169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	__asm__ __volatile__("addl %2,%1; smi %0"
18269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			     : "=d" (c), "+m" (*v)
18335de674982aa13de98cf470c640895164017563eGreg Ungerer			     : ASM_DI (i));
18469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	return c != 0;
18569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
18669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
18769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
18869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
18935de674982aa13de98cf470c640895164017563eGreg Ungerer	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : ASM_DI (~(mask)));
19069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
19169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
19269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_set_mask(unsigned long mask, unsigned long *v)
19369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
19435de674982aa13de98cf470c640895164017563eGreg Ungerer	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : ASM_DI (mask));
19569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
19669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
197f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharmastatic __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
19869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{
19969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	int c, old;
20069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	c = atomic_read(v);
20169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	for (;;) {
20269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer		if (unlikely(c == (u)))
20369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			break;
20469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer		old = atomic_cmpxchg((v), c, c + (a));
20569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer		if (likely(old == c))
20669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer			break;
20769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer		c = old;
20869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer	}
209f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharma	return c;
21069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer}
21169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
21269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
21369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/* Atomic operations are already serializing */
21469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define smp_mb__before_atomic_dec()	barrier()
21569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define smp_mb__after_atomic_dec()	barrier()
21669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define smp_mb__before_atomic_inc()	barrier()
21769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define smp_mb__after_atomic_inc()	barrier()
21869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer
21969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#endif /* __ARCH_M68K_ATOMIC __ */
220